Commit 0c7af25c by cahrens

Update student notes eventing for tags.

TNL-2172
parent 3f2c370d
...@@ -24,6 +24,7 @@ from xmodule.partitions.tests.test_partitions import MockUserPartitionScheme ...@@ -24,6 +24,7 @@ from xmodule.partitions.tests.test_partitions import MockUserPartitionScheme
from selenium.webdriver.support.select import Select from selenium.webdriver.support.select import Select
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support import expected_conditions as EC
from unittest import TestCase
from ..pages.common import BASE_URL from ..pages.common import BASE_URL
...@@ -282,7 +283,7 @@ def get_modal_alert(browser): ...@@ -282,7 +283,7 @@ def get_modal_alert(browser):
return browser.switch_to.alert return browser.switch_to.alert
class EventsTestMixin(object): class EventsTestMixin(TestCase):
""" """
Helpers and setup for running tests that evaluate events emitted Helpers and setup for running tests that evaluate events emitted
""" """
......
...@@ -8,6 +8,7 @@ from ...pages.lms.course_nav import CourseNavPage ...@@ -8,6 +8,7 @@ from ...pages.lms.course_nav import CourseNavPage
from ...pages.lms.courseware import CoursewarePage from ...pages.lms.courseware import CoursewarePage
from ...pages.lms.edxnotes import EdxNotesUnitPage, EdxNotesPage, EdxNotesPageNoContent from ...pages.lms.edxnotes import EdxNotesUnitPage, EdxNotesPage, EdxNotesPageNoContent
from ...fixtures.edxnotes import EdxNotesFixture, Note, Range from ...fixtures.edxnotes import EdxNotesFixture, Note, Range
from ..helpers import EventsTestMixin
class EdxNotesTestMixin(UniqueCourseTest): class EdxNotesTestMixin(UniqueCourseTest):
...@@ -332,7 +333,7 @@ class EdxNotesDefaultInteractionsTest(EdxNotesTestMixin): ...@@ -332,7 +333,7 @@ class EdxNotesDefaultInteractionsTest(EdxNotesTestMixin):
self.assertTrue(note.has_sr_label(1, 3, "Tags (space-separated)")) self.assertTrue(note.has_sr_label(1, 3, "Tags (space-separated)"))
class EdxNotesPageTest(EdxNotesTestMixin): class EdxNotesPageTest(EventsTestMixin, EdxNotesTestMixin):
""" """
Tests for Notes page. Tests for Notes page.
""" """
...@@ -346,7 +347,8 @@ class EdxNotesPageTest(EdxNotesTestMixin): ...@@ -346,7 +347,8 @@ class EdxNotesPageTest(EdxNotesTestMixin):
If tags are specified, they will be used for each of the 3 notes that have tags. If tags are specified, they will be used for each of the 3 notes that have tags.
""" """
xblocks = self.course_fixture.get_nested_xblocks(category="html") xblocks = self.course_fixture.get_nested_xblocks(category="html")
self._add_notes([ # pylint: disable=attribute-defined-outside-init
self.raw_note_list = [
Note( Note(
usage_id=xblocks[4].locator, usage_id=xblocks[4].locator,
user=self.username, user=self.username,
...@@ -389,9 +391,10 @@ class EdxNotesPageTest(EdxNotesTestMixin): ...@@ -389,9 +391,10 @@ class EdxNotesPageTest(EdxNotesTestMixin):
course_id=self.course_fixture._course_key, course_id=self.course_fixture._course_key,
text="Fifth note", text="Fifth note",
quote="Annotate this text", quote="Annotate this text",
updated=datetime(2015, 1, 1, 1, 1, 1, 1).isoformat(), updated=datetime(2015, 1, 1, 1, 1, 1, 1).isoformat()
), ),
]) ]
self._add_notes(self.raw_note_list)
def assertNoteContent(self, item, text=None, quote=None, unit_name=None, time_updated=None, tags=None): def assertNoteContent(self, item, text=None, quote=None, unit_name=None, time_updated=None, tags=None):
""" Verifies the expected properties of the note. """ """ Verifies the expected properties of the note. """
...@@ -418,6 +421,50 @@ class EdxNotesPageTest(EdxNotesTestMixin): ...@@ -418,6 +421,50 @@ class EdxNotesPageTest(EdxNotesTestMixin):
self.assertEqual(item.title, title) self.assertEqual(item.title, title)
self.assertEqual(item.notes, notes) self.assertEqual(item.notes, notes)
def assert_viewed_event(self, view=None):
"""
Verifies that the correct view event was captured for the Notes page.
"""
# There will always be an initial event for "Recent Activity" because that is the default view.
# If view is something besides "Recent Activity", expect 2 events, with the second one being
# the view name passed in.
if view == 'Recent Activity':
view = None
actual_events = self.wait_for_events(
event_filter={'event_type': 'edx.course.student_notes.notes_page_viewed'},
number_of_matches=1 if view is None else 2
)
expected_events = [{'event': {'view': 'Recent Activity'}}]
if view:
expected_events.append({'event': {'view': view}})
self.assert_events_match(expected_events, actual_events)
def assert_unit_link_event(self, usage_id, view):
"""
Verifies that the correct used_unit_link event was captured for the Notes page.
"""
actual_events = self.wait_for_events(
event_filter={'event_type': 'edx.course.student_notes.used_unit_link'},
number_of_matches=1
)
expected_events = [
{'event': {'component_usage_id': usage_id, 'view': view}}
]
self.assert_events_match(expected_events, actual_events)
def assert_search_event(self, search_string, number_of_results):
"""
Verifies that the correct searched event was captured for the Notes page.
"""
actual_events = self.wait_for_events(
event_filter={'event_type': 'edx.course.student_notes.searched'},
number_of_matches=1
)
expected_events = [
{'event': {'search_string': search_string, 'number_of_results': number_of_results}}
]
self.assert_events_match(expected_events, actual_events)
def test_no_content(self): def test_no_content(self):
""" """
Scenario: User can see `No content` message. Scenario: User can see `No content` message.
...@@ -438,6 +485,7 @@ class EdxNotesPageTest(EdxNotesTestMixin): ...@@ -438,6 +485,7 @@ class EdxNotesPageTest(EdxNotesTestMixin):
When I open Notes page When I open Notes page
Then I see 5 notes sorted by the updated date Then I see 5 notes sorted by the updated date
And I see correct content in the notes And I see correct content in the notes
And an event has fired indicating that the Recent Activity view was selected
""" """
self._add_default_notes() self._add_default_notes()
self.notes_page.visit() self.notes_page.visit()
...@@ -485,6 +533,8 @@ class EdxNotesPageTest(EdxNotesTestMixin): ...@@ -485,6 +533,8 @@ class EdxNotesPageTest(EdxNotesTestMixin):
time_updated="Jan 01, 2011 at 01:01 UTC" time_updated="Jan 01, 2011 at 01:01 UTC"
) )
self.assert_viewed_event()
def test_course_structure_view(self): def test_course_structure_view(self):
""" """
Scenario: User can view all notes by location in Course. Scenario: User can view all notes by location in Course.
...@@ -493,6 +543,7 @@ class EdxNotesPageTest(EdxNotesTestMixin): ...@@ -493,6 +543,7 @@ class EdxNotesPageTest(EdxNotesTestMixin):
And I switch to "Location in Course" view And I switch to "Location in Course" view
Then I see 2 groups, 3 sections and 5 notes Then I see 2 groups, 3 sections and 5 notes
And I see correct content in the notes and groups And I see correct content in the notes and groups
And an event has fired indicating that the Location in Course view was selected
""" """
self._add_default_notes() self._add_default_notes()
self.notes_page.visit().switch_to_tab("structure") self.notes_page.visit().switch_to_tab("structure")
...@@ -575,6 +626,8 @@ class EdxNotesPageTest(EdxNotesTestMixin): ...@@ -575,6 +626,8 @@ class EdxNotesPageTest(EdxNotesTestMixin):
time_updated="Jan 01, 2011 at 01:01 UTC" time_updated="Jan 01, 2011 at 01:01 UTC"
) )
self.assert_viewed_event('Location in Course')
def test_tags_view(self): def test_tags_view(self):
""" """
Scenario: User can view all notes by associated tags. Scenario: User can view all notes by associated tags.
...@@ -582,6 +635,7 @@ class EdxNotesPageTest(EdxNotesTestMixin): ...@@ -582,6 +635,7 @@ class EdxNotesPageTest(EdxNotesTestMixin):
When I switch to the "Tags" view When I switch to the "Tags" view
Then I see 4 tag groups Then I see 4 tag groups
And I see correct content in the notes and groups And I see correct content in the notes and groups
And an event has fired indicating that the Tags view was selected
""" """
self._add_default_notes() self._add_default_notes()
self.notes_page.visit().switch_to_tab("tags") self.notes_page.visit().switch_to_tab("tags")
...@@ -677,40 +731,53 @@ class EdxNotesPageTest(EdxNotesTestMixin): ...@@ -677,40 +731,53 @@ class EdxNotesPageTest(EdxNotesTestMixin):
time_updated="Jan 01, 2011 at 01:01 UTC" time_updated="Jan 01, 2011 at 01:01 UTC"
) )
self.assert_viewed_event('Tags')
def test_easy_access_from_notes_page(self): def test_easy_access_from_notes_page(self):
""" """
Scenario: Ensure that the link to the Unit works correctly. Scenario: Ensure that the link to the Unit works correctly.
Given I have a course with 5 notes Given I have a course with 5 notes
When I open Notes page When I open Notes page
And I click on the first unit link And I click on the first unit link
Then I see correct text on the unit page Then I see correct text on the unit page and a unit link event was fired
When go back to the Notes page When go back to the Notes page
And I switch to "Location in Course" view And I switch to "Location in Course" view
And I click on the second unit link And I click on the second unit link
Then I see correct text on the unit page Then I see correct text on the unit page and a unit link event was fired
When go back to the Notes page
And I switch to "Tags" view
And I click on the first unit link
Then I see correct text on the unit page and a unit link event was fired
When go back to the Notes page When go back to the Notes page
And I run the search with "Fifth" query And I run the search with "Fifth" query
And I click on the first unit link And I click on the first unit link
Then I see correct text on the unit page Then I see correct text on the unit page and a unit link event was fired
""" """
def assert_page(note): def assert_page(note, usage_id, view):
""" Verify that clicking on the unit link works properly. """
quote = note.quote quote = note.quote
note.go_to_unit() note.go_to_unit()
self.courseware_page.wait_for_page() self.courseware_page.wait_for_page()
self.assertIn(quote, self.courseware_page.xblock_component_html_content()) self.assertIn(quote, self.courseware_page.xblock_component_html_content())
self.assert_unit_link_event(usage_id, view)
self.reset_event_tracking()
self._add_default_notes() self._add_default_notes()
self.notes_page.visit() self.notes_page.visit()
note = self.notes_page.notes[0] note = self.notes_page.notes[0]
assert_page(note) assert_page(note, self.raw_note_list[4]['usage_id'], "Recent Activity")
self.notes_page.visit().switch_to_tab("structure") self.notes_page.visit().switch_to_tab("structure")
note = self.notes_page.notes[1] note = self.notes_page.notes[1]
assert_page(note) assert_page(note, self.raw_note_list[2]['usage_id'], "Location in Course")
self.notes_page.visit().switch_to_tab("tags")
note = self.notes_page.notes[0]
assert_page(note, self.raw_note_list[2]['usage_id'], "Tags")
self.notes_page.visit().search("Fifth") self.notes_page.visit().search("Fifth")
note = self.notes_page.notes[0] note = self.notes_page.notes[0]
assert_page(note) assert_page(note, self.raw_note_list[4]['usage_id'], "Search Results")
def test_search_behaves_correctly(self): def test_search_behaves_correctly(self):
""" """
...@@ -723,6 +790,8 @@ class EdxNotesPageTest(EdxNotesTestMixin): ...@@ -723,6 +790,8 @@ class EdxNotesPageTest(EdxNotesTestMixin):
When I run the search with "note" query When I run the search with "note" query
Then I see that error message disappears Then I see that error message disappears
And I see that "Search Results" tab appears with 4 notes found And I see that "Search Results" tab appears with 4 notes found
And an event has fired indicating that the Search Results view was selected
And an event has fired recording the search that was performed
""" """
self._add_default_notes() self._add_default_notes()
self.notes_page.visit() self.notes_page.visit()
...@@ -774,6 +843,9 @@ class EdxNotesPageTest(EdxNotesTestMixin): ...@@ -774,6 +843,9 @@ class EdxNotesPageTest(EdxNotesTestMixin):
time_updated="Jan 01, 2011 at 01:01 UTC" time_updated="Jan 01, 2011 at 01:01 UTC"
) )
self.assert_viewed_event('Search Results')
self.assert_search_event('note', 4)
def test_scroll_to_tag_recent_activity(self): def test_scroll_to_tag_recent_activity(self):
""" """
Scenario: Can scroll to a tag group from the Recent Activity view (default view) Scenario: Can scroll to a tag group from the Recent Activity view (default view)
......
...@@ -47,6 +47,7 @@ def edxnotes(cls): ...@@ -47,6 +47,7 @@ def edxnotes(cls):
"tokenUrl": get_token_url(self.runtime.course_id), "tokenUrl": get_token_url(self.runtime.course_id),
"endpoint": get_endpoint(), "endpoint": get_endpoint(),
"debug": settings.DEBUG, "debug": settings.DEBUG,
"eventStringLimit": settings.TRACK_MAX_EVENT / 6,
}, },
}) })
......
...@@ -98,6 +98,7 @@ class EdxNotesDecoratorTest(ModuleStoreTestCase): ...@@ -98,6 +98,7 @@ class EdxNotesDecoratorTest(ModuleStoreTestCase):
"tokenUrl": "/tokenUrl", "tokenUrl": "/tokenUrl",
"endpoint": "/endpoint", "endpoint": "/endpoint",
"debug": settings.DEBUG, "debug": settings.DEBUG,
"eventStringLimit": settings.TRACK_MAX_EVENT / 6,
}, },
} }
self.assertEqual( self.assertEqual(
......
;(function (define, undefined) { ;(function (define, undefined) {
'use strict'; 'use strict';
define(['underscore', 'backbone'], function (_, Backbone) { define(['underscore', 'backbone', 'js/edxnotes/utils/logger'], function (_, Backbone, NotesLogger) {
var TabModel = Backbone.Model.extend({ var TabModel = Backbone.Model.extend({
defaults: { defaults: {
'identifier': '', 'identifier': '',
'name': '', 'name': '',
'icon': '', 'icon': '',
'is_active': false, 'is_active': false,
'is_closable': false 'is_closable': false,
'view': ''
},
initialize: function () {
this.logger = NotesLogger.getLogger('tab');
}, },
activate: function () { activate: function () {
...@@ -18,6 +23,9 @@ define(['underscore', 'backbone'], function (_, Backbone) { ...@@ -18,6 +23,9 @@ define(['underscore', 'backbone'], function (_, Backbone) {
} }
}, this)); }, this));
this.set('is_active', true); this.set('is_active', true);
this.logger.emit('edx.course.student_notes.notes_page_viewed', {
'view': this.get('view')
});
}, },
inactivate: function () { inactivate: function () {
......
...@@ -85,18 +85,22 @@ define([ ...@@ -85,18 +85,22 @@ define([
annotationEditorShown: function (editor, annotation) { annotationEditorShown: function (editor, annotation) {
this.oldNoteText = annotation.text || ''; this.oldNoteText = annotation.text || '';
this.oldTags = annotation.tags || [];
}, },
annotationEditorHidden: function () { annotationEditorHidden: function () {
this.oldNoteText = null; this.oldNoteText = null;
this.oldTags = null;
}, },
annotationUpdated: function (annotation) { annotationUpdated: function (annotation) {
var data; var data, defaultData;
if (!this.isNew(annotation)) { if (!this.isNew(annotation)) {
defaultData = this.getDefaultData(annotation);
data = _.extend( data = _.extend(
this.getDefaultData(annotation), defaultData,
this.getText('old_note_text', this.oldNoteText) this.getText('old_note_text', this.oldNoteText, defaultData.truncated),
this.getTextArray('old_tags', this.oldTags, defaultData.truncated)
); );
this.log('edx.course.student_notes.edited', data); this.log('edx.course.student_notes.edited', data);
} }
...@@ -113,28 +117,51 @@ define([ ...@@ -113,28 +117,51 @@ define([
}, },
getDefaultData: function (annotation) { getDefaultData: function (annotation) {
var truncated = [];
return _.extend( return _.extend(
{ {
'note_id': annotation.id, 'note_id': annotation.id,
'component_usage_id': annotation.usage_id 'component_usage_id': annotation.usage_id,
'truncated': truncated
}, },
this.getText('note_text', annotation.text), this.getText('note_text', annotation.text, truncated),
this.getText('highlighted_content', annotation.quote) this.getText('highlighted_content', annotation.quote, truncated),
this.getTextArray('tags', annotation.tags, truncated)
); );
}, },
getText: function (fieldName, text) { getText: function (fieldName, text, truncated) {
var info = {}, var info = {},
truncated = false,
limit = this.options.stringLimit; limit = this.options.stringLimit;
if (_.isNumber(limit) && _.isString(text) && text.length > limit) { if (_.isNumber(limit) && _.isString(text) && text.length > limit) {
text = String(text).slice(0, limit); text = String(text).slice(0, limit);
truncated = true; truncated.push(fieldName);
} }
info[fieldName] = text; info[fieldName] = text;
info[fieldName + '_truncated'] = truncated;
return info;
},
getTextArray: function (fieldName, textArray, truncated) {
var info = {}, limit = this.options.stringLimit, totalLength=0, returnArray=[], i;
if (_.isNumber(limit) && _.isArray(textArray)) {
for (i=0; i < textArray.length; i++) {
if (_.isString(textArray[i]) && totalLength + textArray[i].length > limit) {
truncated.push(fieldName);
break;
}
totalLength += textArray[i].length;
returnArray[i] = textArray[i];
}
}
else {
returnArray = textArray;
}
info[fieldName] = returnArray;
return info; return info;
}, },
......
...@@ -49,9 +49,10 @@ define([ ...@@ -49,9 +49,10 @@ define([
unitLinkHandler: function (event) { unitLinkHandler: function (event) {
var REQUEST_TIMEOUT = 2000; var REQUEST_TIMEOUT = 2000;
event.preventDefault(); event.preventDefault();
this.logger.emit('edx.student_notes.used_unit_link', { this.logger.emit('edx.course.student_notes.used_unit_link', {
'note_id': this.model.get('id'), 'note_id': this.model.get('id'),
'component_usage_id': this.model.get('usage_id') 'component_usage_id': this.model.get('usage_id'),
'view': this.options.view
}, REQUEST_TIMEOUT).always(_.bind(function () { }, REQUEST_TIMEOUT).always(_.bind(function () {
this.redirectTo(event.target.href); this.redirectTo(event.target.href);
}, this)); }, this));
......
...@@ -34,7 +34,7 @@ define([ ...@@ -34,7 +34,7 @@ define([
tokenUrl: params.tokenUrl tokenUrl: params.tokenUrl
}, },
events: { events: {
stringLimit: 300 stringLimit: params.eventStringLimit
}, },
store: { store: {
prefix: prefix, prefix: prefix,
......
...@@ -98,7 +98,7 @@ define([ ...@@ -98,7 +98,7 @@ define([
var args = this.prepareData(data); var args = this.prepareData(data);
if (args) { if (args) {
this.options.search.apply(this, args); this.options.search.apply(this, args);
this.logger.emit('edx.student_notes.searched', { this.logger.emit('edx.course.student_notes.searched', {
'number_of_results': args[1], 'number_of_results': args[1],
'search_string': args[2] 'search_string': args[2]
}); });
......
...@@ -26,9 +26,9 @@ function (gettext, _, Backbone, NoteItemView) { ...@@ -26,9 +26,9 @@ function (gettext, _, Backbone, NoteItemView) {
}, },
getNotes: function (collection) { getNotes: function (collection) {
var container = document.createDocumentFragment(), scrollToTag = this.options.scrollToTag, var container = document.createDocumentFragment(), scrollToTag = this.options.scrollToTag, view = this.title,
notes = _.map(collection, function (model) { notes = _.map(collection, function (model) {
var note = new NoteItemView({model: model, scrollToTag: scrollToTag}); var note = new NoteItemView({model: model, scrollToTag: scrollToTag, view: view});
container.appendChild(note.render().el); container.appendChild(note.render().el);
return note; return note;
}); });
......
...@@ -4,10 +4,11 @@ define([ ...@@ -4,10 +4,11 @@ define([
'gettext', 'underscore', 'js/edxnotes/views/note_group', 'js/edxnotes/views/tab_panel', 'gettext', 'underscore', 'js/edxnotes/views/note_group', 'js/edxnotes/views/tab_panel',
'js/edxnotes/views/tab_view' 'js/edxnotes/views/tab_view'
], function (gettext, _, NoteGroupView, TabPanelView, TabView) { ], function (gettext, _, NoteGroupView, TabPanelView, TabView) {
var view = "Location in Course";
var CourseStructureView = TabView.extend({ var CourseStructureView = TabView.extend({
PanelConstructor: TabPanelView.extend({ PanelConstructor: TabPanelView.extend({
id: 'structure-panel', id: 'structure-panel',
title: 'Location in Course', title: view,
renderContent: function () { renderContent: function () {
var courseStructure = this.collection.getCourseStructure(), var courseStructure = this.collection.getCourseStructure(),
...@@ -47,7 +48,8 @@ define([ ...@@ -47,7 +48,8 @@ define([
tabInfo: { tabInfo: {
name: gettext('Location in Course'), name: gettext('Location in Course'),
identifier: 'view-course-structure', identifier: 'view-course-structure',
icon: 'fa fa-list-ul' icon: 'fa fa-list-ul',
view: view
} }
}); });
......
...@@ -3,10 +3,11 @@ ...@@ -3,10 +3,11 @@
define([ define([
'gettext', 'js/edxnotes/views/tab_panel', 'js/edxnotes/views/tab_view' 'gettext', 'js/edxnotes/views/tab_panel', 'js/edxnotes/views/tab_view'
], function (gettext, TabPanelView, TabView) { ], function (gettext, TabPanelView, TabView) {
var view = 'Recent Activity';
var RecentActivityView = TabView.extend({ var RecentActivityView = TabView.extend({
PanelConstructor: TabPanelView.extend({ PanelConstructor: TabPanelView.extend({
id: 'recent-panel', id: 'recent-panel',
title: 'Recent Activity', title: view,
className: function () { className: function () {
return [ return [
TabPanelView.prototype.className, TabPanelView.prototype.className,
...@@ -22,7 +23,8 @@ define([ ...@@ -22,7 +23,8 @@ define([
tabInfo: { tabInfo: {
identifier: 'view-recent-activity', identifier: 'view-recent-activity',
name: gettext('Recent Activity'), name: gettext('Recent Activity'),
icon: 'fa fa-clock-o' icon: 'fa fa-clock-o',
view: view
} }
}); });
......
...@@ -4,10 +4,11 @@ define([ ...@@ -4,10 +4,11 @@ define([
'jquery', 'underscore', 'gettext', 'js/edxnotes/views/tab_panel', 'js/edxnotes/views/tab_view', 'jquery', 'underscore', 'gettext', 'js/edxnotes/views/tab_panel', 'js/edxnotes/views/tab_view',
'js/edxnotes/views/search_box' 'js/edxnotes/views/search_box'
], function ($, _, gettext, TabPanelView, TabView, SearchBoxView) { ], function ($, _, gettext, TabPanelView, TabView, SearchBoxView) {
var view = 'Search Results';
var SearchResultsView = TabView.extend({ var SearchResultsView = TabView.extend({
PanelConstructor: TabPanelView.extend({ PanelConstructor: TabPanelView.extend({
id: 'search-results-panel', id: 'search-results-panel',
title: 'Search Results', title: view,
className: function () { className: function () {
return [ return [
TabPanelView.prototype.className, TabPanelView.prototype.className,
...@@ -46,7 +47,8 @@ define([ ...@@ -46,7 +47,8 @@ define([
identifier: 'view-search-results', identifier: 'view-search-results',
name: gettext('Search Results'), name: gettext('Search Results'),
icon: 'fa fa-search', icon: 'fa fa-search',
is_closable: true is_closable: true,
view: view
}, },
initialize: function (options) { initialize: function (options) {
......
...@@ -4,7 +4,7 @@ define([ ...@@ -4,7 +4,7 @@ define([
'gettext', 'jquery', 'underscore', 'js/edxnotes/views/note_group', 'js/edxnotes/views/tab_panel', 'gettext', 'jquery', 'underscore', 'js/edxnotes/views/note_group', 'js/edxnotes/views/tab_panel',
'js/edxnotes/views/tab_view' 'js/edxnotes/views/tab_view'
], function (gettext, $, _, NoteGroupView, TabPanelView, TabView) { ], function (gettext, $, _, NoteGroupView, TabPanelView, TabView) {
var view = 'Tags';
var TagsView = TabView.extend({ var TagsView = TabView.extend({
scrollToTag: function(tagName) { scrollToTag: function(tagName) {
var titleElement, displayedTitle; var titleElement, displayedTitle;
...@@ -31,7 +31,7 @@ define([ ...@@ -31,7 +31,7 @@ define([
PanelConstructor: TabPanelView.extend({ PanelConstructor: TabPanelView.extend({
id: 'tags-panel', id: 'tags-panel',
title: 'Tags', title: view,
// Translators: this is a title shown before all Notes that have no associated tags. It is put within // Translators: this is a title shown before all Notes that have no associated tags. It is put within
// brackets to differentiate it from user-defined tags, but it should still be translated. // brackets to differentiate it from user-defined tags, but it should still be translated.
noTags: gettext('[no tags]'), // User-defined tags cannot have spaces, so no risk of a collision. noTags: gettext('[no tags]'), // User-defined tags cannot have spaces, so no risk of a collision.
...@@ -128,7 +128,8 @@ define([ ...@@ -128,7 +128,8 @@ define([
// in order to group similar notes together and help with search. // in order to group similar notes together and help with search.
name: gettext('Tags'), name: gettext('Tags'),
identifier: 'view-tags', identifier: 'view-tags',
icon: 'fa fa-tag' icon: 'fa fa-tag',
view: view
} }
}); });
......
...@@ -9,19 +9,22 @@ define([ ...@@ -9,19 +9,22 @@ define([
id: 'note-123', id: 'note-123',
text: 'text-123', text: 'text-123',
quote: 'quote-123', quote: 'quote-123',
usage_id: 'usage-123' usage_id: 'usage-123',
tags: ["tag1", "tag2"]
}, },
noteWithoutId = { noteWithoutId = {
user: 'user-123', user: 'user-123',
text: 'text-123', text: 'text-123',
quote: 'quote-123', quote: 'quote-123',
usage_id: 'usage-123' usage_id: 'usage-123',
tags: ["tag1", "tag2"]
}; };
beforeEach(function() { beforeEach(function() {
this.annotator = NotesFactory.factory( this.annotator = NotesFactory.factory(
$('<div />').get(0), { $('<div />').get(0), {
endpoint: 'http://example.com/' endpoint: 'http://example.com/',
eventStringLimit: 300
} }
); );
spyOn(Logger, 'log'); spyOn(Logger, 'log');
...@@ -65,9 +68,9 @@ define([ ...@@ -65,9 +68,9 @@ define([
'edx.course.student_notes.added', { 'edx.course.student_notes.added', {
'note_id': 'note-123', 'note_id': 'note-123',
'note_text': 'text-123', 'note_text': 'text-123',
'note_text_truncated': false, 'tags': ["tag1", "tag2"],
'highlighted_content': 'quote-123', 'highlighted_content': 'quote-123',
'highlighted_content_truncated': false, 'truncated': [],
'component_usage_id': 'usage-123' 'component_usage_id': 'usage-123'
} }
); );
...@@ -75,7 +78,7 @@ define([ ...@@ -75,7 +78,7 @@ define([
it('should log the edx.course.student_notes.edited event properly', function() { it('should log the edx.course.student_notes.edited event properly', function() {
var oldNote = note, var oldNote = note,
newNote = $.extend({}, note, {text: 'text-456'}); newNote = $.extend({}, note, {text: 'text-456', tags: []});
this.annotator.publish('annotationEditorShown', [this.annotator.editor, oldNote]); this.annotator.publish('annotationEditorShown', [this.annotator.editor, oldNote]);
expect(this.annotator.plugins.Events.oldNoteText).toBe('text-123'); expect(this.annotator.plugins.Events.oldNoteText).toBe('text-123');
...@@ -86,11 +89,11 @@ define([ ...@@ -86,11 +89,11 @@ define([
'edx.course.student_notes.edited', { 'edx.course.student_notes.edited', {
'note_id': 'note-123', 'note_id': 'note-123',
'old_note_text': 'text-123', 'old_note_text': 'text-123',
'old_note_text_truncated': false,
'note_text': 'text-456', 'note_text': 'text-456',
'note_text_truncated': false, 'old_tags': ["tag1", "tag2"],
'tags': [],
'highlighted_content': 'quote-123', 'highlighted_content': 'quote-123',
'highlighted_content_truncated': false, 'truncated': [],
'component_usage_id': 'usage-123' 'component_usage_id': 'usage-123'
} }
); );
...@@ -115,9 +118,9 @@ define([ ...@@ -115,9 +118,9 @@ define([
'edx.course.student_notes.deleted', { 'edx.course.student_notes.deleted', {
'note_id': 'note-123', 'note_id': 'note-123',
'note_text': 'text-123', 'note_text': 'text-123',
'note_text_truncated': false, 'tags': ["tag1", "tag2"],
'highlighted_content': 'quote-123', 'highlighted_content': 'quote-123',
'highlighted_content_truncated': false, 'truncated': [],
'component_usage_id': 'usage-123' 'component_usage_id': 'usage-123'
} }
); );
...@@ -129,10 +132,11 @@ define([ ...@@ -129,10 +132,11 @@ define([
}); });
it('should truncate values of some fields', function() { it('should truncate values of some fields', function() {
var oldNote = $.extend({}, note, {text: Helpers.LONG_TEXT}), var oldNote = $.extend({}, note, {text: Helpers.LONG_TEXT, tags: ["review", Helpers.LONG_TEXT]}),
newNote = $.extend({}, note, { newNote = $.extend({}, note, {
text: Helpers.LONG_TEXT + '123', text: Helpers.LONG_TEXT + '123',
quote: Helpers.LONG_TEXT + '123' quote: Helpers.LONG_TEXT + '123',
tags: ["short", "tags", "will", "stay", Helpers.LONG_TEXT]
}); });
this.annotator.publish('annotationEditorShown', [this.annotator.editor, oldNote]); this.annotator.publish('annotationEditorShown', [this.annotator.editor, oldNote]);
...@@ -144,11 +148,11 @@ define([ ...@@ -144,11 +148,11 @@ define([
'edx.course.student_notes.edited', { 'edx.course.student_notes.edited', {
'note_id': 'note-123', 'note_id': 'note-123',
'old_note_text': Helpers.TRUNCATED_TEXT, 'old_note_text': Helpers.TRUNCATED_TEXT,
'old_note_text_truncated': true, 'old_tags': ["review"],
'tags': ["short", "tags", "will", "stay"],
'note_text': Helpers.TRUNCATED_TEXT, 'note_text': Helpers.TRUNCATED_TEXT,
'note_text_truncated': true,
'highlighted_content': Helpers.TRUNCATED_TEXT, 'highlighted_content': Helpers.TRUNCATED_TEXT,
'highlighted_content_truncated': true, 'truncated': ["note_text", "highlighted_content", "tags", "old_note_text", "old_tags"],
'component_usage_id': 'usage-123' 'component_usage_id': 'usage-123'
} }
); );
......
...@@ -23,7 +23,7 @@ define([ ...@@ -23,7 +23,7 @@ define([
} }
})); }));
return new NoteItemView({model: model, scrollToTag: scrollToTag}).render(); return new NoteItemView({model: model, scrollToTag: scrollToTag, view: "Test View"}).render();
}; };
beforeEach(function() { beforeEach(function() {
...@@ -82,16 +82,17 @@ define([ ...@@ -82,16 +82,17 @@ define([
expect(scrollToTagSpy.scrollToTag).toHaveBeenCalledWith("only"); expect(scrollToTagSpy.scrollToTag).toHaveBeenCalledWith("only");
}); });
it('should log the edx.student_notes.used_unit_link event properly', function () { it('should log the edx.course.student_notes.used_unit_link event properly', function () {
var requests = AjaxHelpers.requests(this), var requests = AjaxHelpers.requests(this),
view = getView(); view = getView();
spyOn(view, 'redirectTo'); spyOn(view, 'redirectTo');
view.$('.reference-unit-link').click(); view.$('.reference-unit-link').click();
expect(Logger.log).toHaveBeenCalledWith( expect(Logger.log).toHaveBeenCalledWith(
'edx.student_notes.used_unit_link', 'edx.course.student_notes.used_unit_link',
{ {
'note_id': 'id-123', 'note_id': 'id-123',
'component_usage_id': 'usage_id-123' 'component_usage_id': 'usage_id-123',
'view': 'Test View'
}, },
null, null,
{ {
......
...@@ -73,7 +73,7 @@ define([ ...@@ -73,7 +73,7 @@ define([
); );
}); });
it('should log the edx.student_notes.searched event properly', function () { it('should log the edx.course.student_notes.searched event properly', function () {
var requests = AjaxHelpers.requests(this); var requests = AjaxHelpers.requests(this);
submitForm(this.searchBox, 'test_text'); submitForm(this.searchBox, 'test_text');
AjaxHelpers.respondWithJson(requests, { AjaxHelpers.respondWithJson(requests, {
...@@ -81,7 +81,7 @@ define([ ...@@ -81,7 +81,7 @@ define([
rows: [null, null] rows: [null, null]
}); });
expect(Logger.log).toHaveBeenCalledWith('edx.student_notes.searched', { expect(Logger.log).toHaveBeenCalledWith('edx.course.student_notes.searched', {
'number_of_results': 2, 'number_of_results': 2,
'search_string': 'test_text' 'search_string': 'test_text'
}); });
......
...@@ -56,7 +56,8 @@ define([ ...@@ -56,7 +56,8 @@ define([
identifier: 'view-course-structure', identifier: 'view-course-structure',
icon: 'fa fa-list-ul', icon: 'fa fa-list-ul',
is_active: true, is_active: true,
is_closable: false is_closable: false,
view: 'Location in Course'
}); });
expect(view.$('#structure-panel')).toExist(); expect(view.$('#structure-panel')).toExist();
expect(chapters).toEqual(['First Chapter', 'Second Chapter']); expect(chapters).toEqual(['First Chapter', 'Second Chapter']);
......
...@@ -63,7 +63,8 @@ define([ ...@@ -63,7 +63,8 @@ define([
identifier: 'view-recent-activity', identifier: 'view-recent-activity',
icon: 'fa fa-clock-o', icon: 'fa fa-clock-o',
is_active: true, is_active: true,
is_closable: false is_closable: false,
view: 'Recent Activity'
}); });
expect(view.$('#recent-panel')).toExist(); expect(view.$('#recent-panel')).toExist();
expect(view.$('.note')).toHaveLength(3); expect(view.$('.note')).toHaveLength(3);
......
define([ define([
'jquery', 'js/common_helpers/template_helpers', 'js/common_helpers/ajax_helpers', 'jquery', 'underscore', 'js/common_helpers/template_helpers', 'js/common_helpers/ajax_helpers',
'logger', 'js/edxnotes/collections/tabs', 'js/edxnotes/views/tabs/search_results', 'logger', 'js/edxnotes/collections/tabs', 'js/edxnotes/views/tabs/search_results',
'js/spec/edxnotes/custom_matchers', 'jasmine-jquery' 'js/spec/edxnotes/custom_matchers', 'jasmine-jquery'
], function( ], function(
$, TemplateHelpers, AjaxHelpers, Logger, TabsCollection, SearchResultsView, $, _, TemplateHelpers, AjaxHelpers, Logger, TabsCollection, SearchResultsView,
customMatchers customMatchers
) { ) {
'use strict'; 'use strict';
...@@ -79,7 +79,8 @@ define([ ...@@ -79,7 +79,8 @@ define([
identifier: 'view-search-results', identifier: 'view-search-results',
icon: 'fa fa-search', icon: 'fa fa-search',
is_active: true, is_active: true,
is_closable: true is_closable: true,
view: 'Search Results'
}); });
expect(view.$('#search-results-panel')).toExist(); expect(view.$('#search-results-panel')).toExist();
expect(view.$('#search-results-panel')).toBeFocused(); expect(view.$('#search-results-panel')).toBeFocused();
...@@ -157,12 +158,7 @@ define([ ...@@ -157,12 +158,7 @@ define([
requests = AjaxHelpers.requests(this); requests = AjaxHelpers.requests(this);
submitForm(view.searchBox, 'test error'); submitForm(view.searchBox, 'test error');
requests[0].respond( AjaxHelpers.respondWithError(requests, 500, {error: 'test error message'});
500, {'Content-Type': 'application/json'},
JSON.stringify({
error: 'test error message'
})
);
expect(view.$('.wrapper-msg')).not.toHaveClass('is-hidden'); expect(view.$('.wrapper-msg')).not.toHaveClass('is-hidden');
expect(view.$('.wrapper-msg .copy')).toContainText('test error message'); expect(view.$('.wrapper-msg .copy')).toContainText('test error message');
......
...@@ -62,7 +62,8 @@ define([ ...@@ -62,7 +62,8 @@ define([
identifier: 'view-tags', identifier: 'view-tags',
icon: 'fa fa-tag', icon: 'fa fa-tag',
is_active: true, is_active: true,
is_closable: false is_closable: false,
view: 'Tags'
}); });
expect(view.$('#tags-panel')).toExist(); expect(view.$('#tags-panel')).toExist();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment