Merge pull request #9885 from edx/andya/teams-router-testing
Improve team testing of routers
This commit is contained in:
@@ -1,18 +1,49 @@
|
||||
define([ // jshint ignore:line
|
||||
],
|
||||
function() {
|
||||
'use strict';
|
||||
var getLocationHash;
|
||||
/**
|
||||
* Helper method that returns url hash.
|
||||
* @return {String} Returns anchor part of current url.
|
||||
*/
|
||||
getLocationHash = function() {
|
||||
return window.location.hash;
|
||||
};
|
||||
define(["backbone"],
|
||||
function(Backbone) {
|
||||
'use strict';
|
||||
var getLocationHash, preventBackboneChangingUrl;
|
||||
|
||||
return {
|
||||
'getLocationHash': getLocationHash
|
||||
};
|
||||
/**
|
||||
* Helper method that returns url hash.
|
||||
* @return {String} Returns anchor part of current url.
|
||||
*/
|
||||
getLocationHash = function() {
|
||||
return window.location.hash;
|
||||
};
|
||||
|
||||
});
|
||||
/**
|
||||
* Prevent Backbone tests from changing the browser's URL.
|
||||
*
|
||||
* This function modifies Backbone so that tests can navigate
|
||||
* without modifying the browser's URL. It works be adding
|
||||
* stub versions of Backbone's hash functions so that updating
|
||||
* the hash doesn't change the URL but instead updates a
|
||||
* local object. The router's callbacks are still invoked
|
||||
* so that to the test it appears that navigation is behaving
|
||||
* as expected.
|
||||
*
|
||||
* Note: it is important that tests don't update the browser's
|
||||
* URL because subsequent tests could find themselves in an
|
||||
* unexpected navigation state.
|
||||
*/
|
||||
preventBackboneChangingUrl = function() {
|
||||
var history = {
|
||||
currentFragment: ''
|
||||
};
|
||||
|
||||
// Stub out the Backbone router so that the browser doesn't actually navigate
|
||||
spyOn(Backbone.history, '_updateHash').andCallFake(function (location, fragment, replace) {
|
||||
history.currentFragment = fragment;
|
||||
});
|
||||
|
||||
// Stub out getHash so that Backbone thinks that the browser has navigated
|
||||
spyOn(Backbone.history, 'getHash').andCallFake(function () {
|
||||
return history.currentFragment;
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
'getLocationHash': getLocationHash,
|
||||
'preventBackboneChangingUrl': preventBackboneChangingUrl
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
define(['jquery', 'backbone', 'teams/js/teams_tab_factory',
|
||||
'teams/js/spec_helpers/team_spec_helpers'],
|
||||
function($, Backbone, TeamsTabFactory, TeamSpecHelpers) {
|
||||
'common/js/spec_helpers/page_helpers', 'teams/js/spec_helpers/team_spec_helpers'],
|
||||
function($, Backbone, TeamsTabFactory, PageHelpers, TeamSpecHelpers) {
|
||||
'use strict';
|
||||
|
||||
describe("Teams Tab Factory", function() {
|
||||
@@ -10,6 +10,7 @@ define(['jquery', 'backbone', 'teams/js/teams_tab_factory',
|
||||
|
||||
beforeEach(function() {
|
||||
setFixtures('<section class="teams-content"></section>');
|
||||
PageHelpers.preventBackboneChangingUrl();
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
@@ -17,11 +18,6 @@ define(['jquery', 'backbone', 'teams/js/teams_tab_factory',
|
||||
});
|
||||
|
||||
it('can render the "Teams" tab', function() {
|
||||
// Hack to make sure the URL fragments from earlier
|
||||
// tests don't interfere with Backbone routing by the
|
||||
// teams tab view
|
||||
document.location.hash = '';
|
||||
|
||||
initializeTeamsTabFactory();
|
||||
expect($('.teams-content').text()).toContain('See all teams in your course, organized by topic');
|
||||
});
|
||||
|
||||
@@ -3,10 +3,11 @@ define([
|
||||
'underscore',
|
||||
'backbone',
|
||||
'common/js/spec_helpers/ajax_helpers',
|
||||
'common/js/spec_helpers/page_helpers',
|
||||
'teams/js/views/edit_team',
|
||||
'teams/js/models/team',
|
||||
'teams/js/spec_helpers/team_spec_helpers'
|
||||
], function ($, _, Backbone, AjaxHelpers, TeamEditView, TeamModel, TeamSpecHelpers) {
|
||||
], function ($, _, Backbone, AjaxHelpers, PageHelpers, TeamEditView, TeamModel, TeamSpecHelpers) {
|
||||
'use strict';
|
||||
|
||||
describe('CreateEditTeam', function() {
|
||||
@@ -90,6 +91,7 @@ define([
|
||||
|
||||
beforeEach(function () {
|
||||
setFixtures('<div class="teams-content"></div>');
|
||||
PageHelpers.preventBackboneChangingUrl();
|
||||
spyOn(Backbone.history, 'navigate');
|
||||
});
|
||||
|
||||
|
||||
@@ -6,8 +6,9 @@ define([
|
||||
'teams/js/views/instructor_tools',
|
||||
'teams/js/views/team_utils',
|
||||
'teams/js/spec_helpers/team_spec_helpers',
|
||||
'common/js/spec_helpers/ajax_helpers'
|
||||
], function ($, Backbone, _, Team, InstructorToolsView, TeamUtils, TeamSpecHelpers, AjaxHelpers) {
|
||||
'common/js/spec_helpers/ajax_helpers',
|
||||
'common/js/spec_helpers/page_helpers'
|
||||
], function ($, Backbone, _, Team, InstructorToolsView, TeamUtils, TeamSpecHelpers, AjaxHelpers, PageHelpers) {
|
||||
'use strict';
|
||||
|
||||
describe('Instructor Tools', function () {
|
||||
@@ -37,6 +38,7 @@ define([
|
||||
|
||||
beforeEach(function () {
|
||||
setFixtures('<div id="page-prompt"></div>');
|
||||
PageHelpers.preventBackboneChangingUrl();
|
||||
spyOn(Backbone.history, 'navigate');
|
||||
spyOn(TeamUtils, 'showMessage');
|
||||
view = createInstructorTools().render();
|
||||
|
||||
@@ -3,13 +3,16 @@ define([
|
||||
'backbone',
|
||||
'logger',
|
||||
'common/js/spec_helpers/ajax_helpers',
|
||||
'common/js/spec_helpers/page_helpers',
|
||||
'common/js/spec_helpers/spec_helpers',
|
||||
'teams/js/views/teams_tab',
|
||||
'teams/js/spec_helpers/team_spec_helpers'
|
||||
], function ($, Backbone, Logger, AjaxHelpers, SpecHelpers, TeamsTabView, TeamSpecHelpers) {
|
||||
], function ($, Backbone, Logger, AjaxHelpers, PageHelpers, SpecHelpers, TeamsTabView, TeamSpecHelpers) {
|
||||
'use strict';
|
||||
|
||||
describe('TeamsTab', function() {
|
||||
var requests;
|
||||
|
||||
var expectError = function (teamsTabView, text) {
|
||||
expect(teamsTabView.$('.warning').text()).toContain(text);
|
||||
};
|
||||
@@ -18,13 +21,31 @@ define([
|
||||
expect(element.focus).toHaveBeenCalled();
|
||||
};
|
||||
|
||||
var createTeamsTabView = function(options) {
|
||||
var verifyTeamsRequest = function(options) {
|
||||
AjaxHelpers.expectRequestURL(requests, TeamSpecHelpers.testContext.teamsUrl,
|
||||
_.extend(
|
||||
{
|
||||
topic_id: TeamSpecHelpers.testTopicID,
|
||||
expand: 'user',
|
||||
course_id: TeamSpecHelpers.testCourseID,
|
||||
order_by: '',
|
||||
page: '1',
|
||||
page_size: '10',
|
||||
text_search: ''
|
||||
},
|
||||
options
|
||||
));
|
||||
};
|
||||
|
||||
var createTeamsTabView = function(test, options) {
|
||||
var teamsTabView = new TeamsTabView(
|
||||
{
|
||||
el: $('.teams-content'),
|
||||
context: TeamSpecHelpers.createMockContext(options)
|
||||
}
|
||||
);
|
||||
requests = AjaxHelpers.requests(test);
|
||||
PageHelpers.preventBackboneChangingUrl();
|
||||
teamsTabView.start();
|
||||
return teamsTabView;
|
||||
};
|
||||
@@ -39,7 +60,7 @@ define([
|
||||
|
||||
describe('Navigation', function () {
|
||||
it('does not render breadcrumbs for the top level tabs', function() {
|
||||
var teamsTabView = createTeamsTabView();
|
||||
var teamsTabView = createTeamsTabView(this);
|
||||
teamsTabView.router.navigate('#my-teams', {trigger: true});
|
||||
expect(teamsTabView.$('.breadcrumbs').length).toBe(0);
|
||||
teamsTabView.router.navigate('#browse', {trigger: true});
|
||||
@@ -47,21 +68,20 @@ define([
|
||||
});
|
||||
|
||||
it('does not interfere with anchor links to #content', function () {
|
||||
var teamsTabView = createTeamsTabView();
|
||||
var teamsTabView = createTeamsTabView(this);
|
||||
teamsTabView.router.navigate('#content', {trigger: true});
|
||||
expect(teamsTabView.$('.wrapper-msg')).toHaveClass('is-hidden');
|
||||
});
|
||||
|
||||
it('displays and focuses an error message when trying to navigate to a nonexistent page', function () {
|
||||
var teamsTabView = createTeamsTabView();
|
||||
var teamsTabView = createTeamsTabView(this);
|
||||
teamsTabView.router.navigate('no_such_page', {trigger: true});
|
||||
expectError(teamsTabView, 'The page "no_such_page" could not be found.');
|
||||
expectFocus(teamsTabView.$('.warning'));
|
||||
});
|
||||
|
||||
it('displays and focuses an error message when trying to navigate to a nonexistent topic', function () {
|
||||
var requests = AjaxHelpers.requests(this),
|
||||
teamsTabView = createTeamsTabView();
|
||||
var teamsTabView = createTeamsTabView(this);
|
||||
teamsTabView.router.navigate('topics/no_such_topic', {trigger: true});
|
||||
AjaxHelpers.expectRequest(requests, 'GET', '/api/team/v0/topics/no_such_topic,course/1', null);
|
||||
AjaxHelpers.respondWithError(requests, 404);
|
||||
@@ -70,8 +90,7 @@ define([
|
||||
});
|
||||
|
||||
it('displays and focuses an error message when trying to navigate to a nonexistent team', function () {
|
||||
var requests = AjaxHelpers.requests(this),
|
||||
teamsTabView = createTeamsTabView();
|
||||
var teamsTabView = createTeamsTabView(this);
|
||||
teamsTabView.router.navigate('teams/' + TeamSpecHelpers.testTopicID + '/no_such_team', {trigger: true});
|
||||
AjaxHelpers.expectRequest(requests, 'GET', '/api/team/v0/teams/no_such_team?expand=user', null);
|
||||
AjaxHelpers.respondWithError(requests, 404);
|
||||
@@ -80,8 +99,7 @@ define([
|
||||
});
|
||||
|
||||
it('displays and focuses an error message when it receives a 401 AJAX response', function () {
|
||||
var requests = AjaxHelpers.requests(this),
|
||||
teamsTabView = createTeamsTabView().render();
|
||||
var teamsTabView = createTeamsTabView(this).render();
|
||||
teamsTabView.router.navigate('topics/' + TeamSpecHelpers.testTopicID, {trigger: true});
|
||||
AjaxHelpers.respondWithError(requests, 401);
|
||||
expectError(teamsTabView, "Your request could not be completed. Reload the page and try again.");
|
||||
@@ -89,8 +107,7 @@ define([
|
||||
});
|
||||
|
||||
it('displays and focuses an error message when it receives a 500 AJAX response', function () {
|
||||
var requests = AjaxHelpers.requests(this),
|
||||
teamsTabView = createTeamsTabView().render();
|
||||
var teamsTabView = createTeamsTabView(this).render();
|
||||
teamsTabView.router.navigate('topics/' + TeamSpecHelpers.testTopicID, {trigger: true});
|
||||
AjaxHelpers.respondWithError(requests, 500);
|
||||
expectError(teamsTabView, "Your request could not be completed due to a server problem. Reload the page and try again. If the issue persists, click the Help tab to report the problem.");
|
||||
@@ -98,7 +115,7 @@ define([
|
||||
});
|
||||
|
||||
it('does not navigate to the topics page when syncing its collection if not on the search page', function () {
|
||||
var teamsTabView = createTeamsTabView(),
|
||||
var teamsTabView = createTeamsTabView(this),
|
||||
collection = TeamSpecHelpers.createMockTeams();
|
||||
teamsTabView.createTeamsListView({
|
||||
collection: collection,
|
||||
@@ -153,8 +170,7 @@ define([
|
||||
}
|
||||
]
|
||||
}, function (url, expectedEvent) {
|
||||
var requests = AjaxHelpers.requests(this),
|
||||
teamsTabView = createTeamsTabView({
|
||||
var teamsTabView = createTeamsTabView(this, {
|
||||
userInfo: TeamSpecHelpers.createMockUserInfo({staff: true})
|
||||
});
|
||||
teamsTabView.router.navigate(url, {trigger: true});
|
||||
@@ -167,9 +183,9 @@ define([
|
||||
|
||||
describe('Discussion privileges', function () {
|
||||
it('allows privileged access to any team', function () {
|
||||
var teamsTabView = createTeamsTabView({
|
||||
userInfo: TeamSpecHelpers.createMockUserInfo({privileged: true})
|
||||
});
|
||||
var teamsTabView = createTeamsTabView(this, {
|
||||
userInfo: TeamSpecHelpers.createMockUserInfo({privileged: true})
|
||||
});
|
||||
// Note: using `undefined` here to ensure that we
|
||||
// don't even look at the team when the user is
|
||||
// privileged
|
||||
@@ -177,12 +193,12 @@ define([
|
||||
});
|
||||
|
||||
it('allows access to a team which an unprivileged user is a member of', function () {
|
||||
var teamsTabView = createTeamsTabView({
|
||||
userInfo: TeamSpecHelpers.createMockUserInfo({
|
||||
username: TeamSpecHelpers.testUser,
|
||||
privileged: false
|
||||
})
|
||||
});
|
||||
var teamsTabView = createTeamsTabView(this, {
|
||||
userInfo: TeamSpecHelpers.createMockUserInfo({
|
||||
username: TeamSpecHelpers.testUser,
|
||||
privileged: false
|
||||
})
|
||||
});
|
||||
expect(teamsTabView.readOnlyDiscussion({
|
||||
attributes: {
|
||||
membership: [{
|
||||
@@ -195,9 +211,9 @@ define([
|
||||
});
|
||||
|
||||
it('does not allow access if the user is neither privileged nor a team member', function () {
|
||||
var teamsTabView = createTeamsTabView({
|
||||
userInfo: TeamSpecHelpers.createMockUserInfo({privileged: false, staff: true})
|
||||
});
|
||||
var teamsTabView = createTeamsTabView(this, {
|
||||
userInfo: TeamSpecHelpers.createMockUserInfo({privileged: false, staff: true})
|
||||
});
|
||||
expect(teamsTabView.readOnlyDiscussion({
|
||||
attributes: {membership: []}
|
||||
})).toBe(true);
|
||||
@@ -205,25 +221,10 @@ define([
|
||||
});
|
||||
|
||||
describe('Search', function () {
|
||||
var verifyTeamsRequest = function(requests, options) {
|
||||
AjaxHelpers.expectRequestURL(requests, TeamSpecHelpers.testContext.teamsUrl,
|
||||
_.extend(
|
||||
{
|
||||
topic_id: TeamSpecHelpers.testTopicID,
|
||||
expand: 'user',
|
||||
course_id: TeamSpecHelpers.testCourseID,
|
||||
order_by: '',
|
||||
page: '1',
|
||||
page_size: '10',
|
||||
text_search: ''
|
||||
},
|
||||
options
|
||||
));
|
||||
};
|
||||
var performSearch = function(requests, teamsTabView) {
|
||||
teamsTabView.$('.search-field').val('foo');
|
||||
teamsTabView.$('.action-search').click();
|
||||
verifyTeamsRequest(requests, {
|
||||
verifyTeamsRequest({
|
||||
order_by: '',
|
||||
text_search: 'foo'
|
||||
});
|
||||
@@ -231,11 +232,10 @@ define([
|
||||
};
|
||||
|
||||
it('can search teams', function () {
|
||||
var requests = AjaxHelpers.requests(this),
|
||||
teamsTabView = createTeamsTabView(),
|
||||
var teamsTabView = createTeamsTabView(this),
|
||||
requestCountBeforeSearch;
|
||||
teamsTabView.browseTopic(TeamSpecHelpers.testTopicID);
|
||||
verifyTeamsRequest(requests, {
|
||||
verifyTeamsRequest({
|
||||
order_by: 'last_activity_at',
|
||||
text_search: ''
|
||||
});
|
||||
@@ -250,11 +250,9 @@ define([
|
||||
});
|
||||
|
||||
it('can clear a search', function () {
|
||||
var requests = AjaxHelpers.requests(this),
|
||||
teamsTabView = createTeamsTabView();
|
||||
var teamsTabView = createTeamsTabView(this);
|
||||
teamsTabView.browseTopic(TeamSpecHelpers.testTopicID);
|
||||
AjaxHelpers.respondWithJson(requests, {});
|
||||
performSearch(requests, teamsTabView);
|
||||
|
||||
// Perform a search
|
||||
performSearch(requests, teamsTabView);
|
||||
@@ -262,7 +260,7 @@ define([
|
||||
// Clear the search and submit it again
|
||||
teamsTabView.$('.search-field').val('');
|
||||
teamsTabView.$('.action-search').click();
|
||||
verifyTeamsRequest(requests, {
|
||||
verifyTeamsRequest({
|
||||
order_by: 'last_activity_at',
|
||||
text_search: ''
|
||||
});
|
||||
@@ -272,8 +270,7 @@ define([
|
||||
});
|
||||
|
||||
it('can navigate back to all teams from a search', function () {
|
||||
var requests = AjaxHelpers.requests(this),
|
||||
teamsTabView = createTeamsTabView();
|
||||
var teamsTabView = createTeamsTabView(this);
|
||||
teamsTabView.browseTopic(TeamSpecHelpers.testTopicID);
|
||||
AjaxHelpers.respondWithJson(requests, {});
|
||||
|
||||
@@ -283,7 +280,7 @@ define([
|
||||
// Verify the breadcrumbs have a link back to the teams list, and click on it
|
||||
expect(teamsTabView.$('.breadcrumbs a').length).toBe(2);
|
||||
teamsTabView.$('.breadcrumbs a').last().click();
|
||||
verifyTeamsRequest(requests, {
|
||||
verifyTeamsRequest({
|
||||
order_by: 'last_activity_at',
|
||||
text_search: ''
|
||||
});
|
||||
@@ -293,8 +290,7 @@ define([
|
||||
});
|
||||
|
||||
it('does not switch to showing results when the search returns an error', function () {
|
||||
var requests = AjaxHelpers.requests(this),
|
||||
teamsTabView = createTeamsTabView();
|
||||
var teamsTabView = createTeamsTabView(this);
|
||||
teamsTabView.browseTopic(TeamSpecHelpers.testTopicID);
|
||||
AjaxHelpers.respondWithJson(requests, {});
|
||||
|
||||
|
||||
@@ -4,8 +4,10 @@ define([
|
||||
'teams/js/collections/team_membership',
|
||||
'teams/js/views/topic_teams',
|
||||
'teams/js/spec_helpers/team_spec_helpers',
|
||||
'common/js/spec_helpers/ajax_helpers'
|
||||
], function (Backbone, TeamCollection, TeamMembershipCollection, TopicTeamsView, TeamSpecHelpers, AjaxHelpers) {
|
||||
'common/js/spec_helpers/ajax_helpers',
|
||||
'common/js/spec_helpers/page_helpers'
|
||||
], function (Backbone, TeamCollection, TeamMembershipCollection, TopicTeamsView, TeamSpecHelpers,
|
||||
AjaxHelpers, PageHelpers) {
|
||||
'use strict';
|
||||
describe('Topic Teams View', function () {
|
||||
var createTopicTeamsView = function(options) {
|
||||
@@ -39,6 +41,7 @@ define([
|
||||
|
||||
beforeEach(function () {
|
||||
setFixtures('<div class="teams-container"></div>');
|
||||
PageHelpers.preventBackboneChangingUrl();
|
||||
});
|
||||
|
||||
it('can render itself', function () {
|
||||
|
||||
@@ -3,6 +3,7 @@ define([
|
||||
'backbone',
|
||||
'logger',
|
||||
'common/js/spec_helpers/ajax_helpers',
|
||||
'common/js/spec_helpers/page_helpers',
|
||||
'common/js/spec_helpers/template_helpers',
|
||||
'js/search/base/models/search_result',
|
||||
'js/search/base/collections/search_collection',
|
||||
@@ -20,6 +21,7 @@ define([
|
||||
Backbone,
|
||||
Logger,
|
||||
AjaxHelpers,
|
||||
PageHelpers,
|
||||
TemplateHelpers,
|
||||
SearchResult,
|
||||
SearchCollection,
|
||||
@@ -35,696 +37,534 @@ define([
|
||||
) {
|
||||
'use strict';
|
||||
|
||||
|
||||
describe('SearchResult', function () {
|
||||
|
||||
describe('Search', function() {
|
||||
beforeEach(function () {
|
||||
this.result = new SearchResult();
|
||||
PageHelpers.preventBackboneChangingUrl();
|
||||
});
|
||||
|
||||
it('has properties', function () {
|
||||
expect(this.result.get('location')).toBeDefined();
|
||||
expect(this.result.get('content_type')).toBeDefined();
|
||||
expect(this.result.get('excerpt')).toBeDefined();
|
||||
expect(this.result.get('url')).toBeDefined();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
describe('SearchCollection', function () {
|
||||
|
||||
beforeEach(function () {
|
||||
this.collection = new SearchCollection();
|
||||
|
||||
this.onSearch = jasmine.createSpy('onSearch');
|
||||
this.collection.on('search', this.onSearch);
|
||||
|
||||
this.onNext = jasmine.createSpy('onNext');
|
||||
this.collection.on('next', this.onNext);
|
||||
|
||||
this.onError = jasmine.createSpy('onError');
|
||||
this.collection.on('error', this.onError);
|
||||
});
|
||||
|
||||
it('sends a request without a course ID', function () {
|
||||
var collection = new SearchCollection([]);
|
||||
spyOn($, 'ajax');
|
||||
collection.performSearch('search string');
|
||||
expect($.ajax.mostRecentCall.args[0].url).toEqual('/search/');
|
||||
});
|
||||
|
||||
it('sends a request with course ID', function () {
|
||||
var collection = new SearchCollection([], { courseId: 'edx101' });
|
||||
spyOn($, 'ajax');
|
||||
collection.performSearch('search string');
|
||||
expect($.ajax.mostRecentCall.args[0].url).toEqual('/search/edx101');
|
||||
});
|
||||
|
||||
it('sends a request and parses the json result', function () {
|
||||
var requests = AjaxHelpers.requests(this);
|
||||
this.collection.performSearch('search string');
|
||||
var response = {
|
||||
total: 2,
|
||||
access_denied_count: 1,
|
||||
results: [{
|
||||
data: {
|
||||
location: ['section', 'subsection', 'unit'],
|
||||
url: '/some/url/to/content',
|
||||
content_type: 'text',
|
||||
excerpt: 'this is a short excerpt'
|
||||
}
|
||||
}]
|
||||
};
|
||||
AjaxHelpers.respondWithJson(requests, response);
|
||||
|
||||
expect(this.onSearch).toHaveBeenCalled();
|
||||
expect(this.collection.totalCount).toEqual(1);
|
||||
expect(this.collection.latestModelsCount).toEqual(1);
|
||||
expect(this.collection.accessDeniedCount).toEqual(1);
|
||||
expect(this.collection.page).toEqual(0);
|
||||
expect(this.collection.first().attributes).toEqual(response.results[0].data);
|
||||
});
|
||||
|
||||
it('handles errors', function () {
|
||||
var requests = AjaxHelpers.requests(this);
|
||||
this.collection.performSearch('search string');
|
||||
AjaxHelpers.respondWithError(requests, 500);
|
||||
expect(this.onSearch).not.toHaveBeenCalled();
|
||||
expect(this.onError).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('loads next page', function () {
|
||||
var requests = AjaxHelpers.requests(this);
|
||||
var response = { total: 35, results: [] };
|
||||
this.collection.loadNextPage();
|
||||
AjaxHelpers.respondWithJson(requests, response);
|
||||
expect(this.onNext).toHaveBeenCalled();
|
||||
expect(this.onError).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('sends correct paging parameters', function () {
|
||||
var requests = AjaxHelpers.requests(this);
|
||||
var searchString = 'search string';
|
||||
var response = { total: 52, results: [] };
|
||||
this.collection.performSearch(searchString);
|
||||
AjaxHelpers.respondWithJson(requests, response);
|
||||
this.collection.loadNextPage();
|
||||
AjaxHelpers.respondWithJson(requests, response);
|
||||
spyOn($, 'ajax');
|
||||
this.collection.loadNextPage();
|
||||
expect($.ajax.mostRecentCall.args[0].url).toEqual(this.collection.url);
|
||||
expect($.ajax.mostRecentCall.args[0].data.search_string).toEqual(searchString);
|
||||
expect($.ajax.mostRecentCall.args[0].data.page_size).toEqual(this.collection.pageSize);
|
||||
expect($.ajax.mostRecentCall.args[0].data.page_index).toEqual(2);
|
||||
});
|
||||
|
||||
it('has next page', function () {
|
||||
var requests = AjaxHelpers.requests(this);
|
||||
var response = { total: 35, access_denied_count: 5, results: [] };
|
||||
this.collection.performSearch('search string');
|
||||
AjaxHelpers.respondWithJson(requests, response);
|
||||
expect(this.collection.hasNextPage()).toEqual(true);
|
||||
this.collection.loadNextPage();
|
||||
AjaxHelpers.respondWithJson(requests, response);
|
||||
expect(this.collection.hasNextPage()).toEqual(false);
|
||||
});
|
||||
|
||||
it('aborts any previous request', function () {
|
||||
var requests = AjaxHelpers.requests(this);
|
||||
var response = { total: 35, results: [] };
|
||||
|
||||
this.collection.performSearch('old search');
|
||||
this.collection.performSearch('new search');
|
||||
AjaxHelpers.respondWithJson(requests, response);
|
||||
expect(this.onSearch.calls.length).toEqual(1);
|
||||
|
||||
this.collection.performSearch('old search');
|
||||
this.collection.cancelSearch();
|
||||
AjaxHelpers.respondWithJson(requests, response);
|
||||
expect(this.onSearch.calls.length).toEqual(1);
|
||||
|
||||
this.collection.loadNextPage();
|
||||
this.collection.loadNextPage();
|
||||
AjaxHelpers.respondWithJson(requests, response);
|
||||
expect(this.onNext.calls.length).toEqual(1);
|
||||
});
|
||||
|
||||
describe('reset state', function () {
|
||||
describe('SearchResult', function () {
|
||||
|
||||
beforeEach(function () {
|
||||
this.collection.page = 2;
|
||||
this.collection.totalCount = 35;
|
||||
this.collection.latestModelsCount = 5;
|
||||
this.result = new SearchResult();
|
||||
});
|
||||
|
||||
it('resets state when performing new search', function () {
|
||||
it('has properties', function () {
|
||||
expect(this.result.get('location')).toBeDefined();
|
||||
expect(this.result.get('content_type')).toBeDefined();
|
||||
expect(this.result.get('excerpt')).toBeDefined();
|
||||
expect(this.result.get('url')).toBeDefined();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
describe('SearchCollection', function () {
|
||||
|
||||
beforeEach(function () {
|
||||
this.collection = new SearchCollection();
|
||||
|
||||
this.onSearch = jasmine.createSpy('onSearch');
|
||||
this.collection.on('search', this.onSearch);
|
||||
|
||||
this.onNext = jasmine.createSpy('onNext');
|
||||
this.collection.on('next', this.onNext);
|
||||
|
||||
this.onError = jasmine.createSpy('onError');
|
||||
this.collection.on('error', this.onError);
|
||||
});
|
||||
|
||||
it('sends a request without a course ID', function () {
|
||||
var collection = new SearchCollection([]);
|
||||
spyOn($, 'ajax');
|
||||
collection.performSearch('search string');
|
||||
expect($.ajax.mostRecentCall.args[0].url).toEqual('/search/');
|
||||
});
|
||||
|
||||
it('sends a request with course ID', function () {
|
||||
var collection = new SearchCollection([], { courseId: 'edx101' });
|
||||
spyOn($, 'ajax');
|
||||
collection.performSearch('search string');
|
||||
expect($.ajax.mostRecentCall.args[0].url).toEqual('/search/edx101');
|
||||
});
|
||||
|
||||
it('sends a request and parses the json result', function () {
|
||||
var requests = AjaxHelpers.requests(this);
|
||||
this.collection.performSearch('search string');
|
||||
expect(this.collection.models.length).toEqual(0);
|
||||
var response = {
|
||||
total: 2,
|
||||
access_denied_count: 1,
|
||||
results: [{
|
||||
data: {
|
||||
location: ['section', 'subsection', 'unit'],
|
||||
url: '/some/url/to/content',
|
||||
content_type: 'text',
|
||||
excerpt: 'this is a short excerpt'
|
||||
}
|
||||
}]
|
||||
};
|
||||
AjaxHelpers.respondWithJson(requests, response);
|
||||
|
||||
expect(this.onSearch).toHaveBeenCalled();
|
||||
expect(this.collection.totalCount).toEqual(1);
|
||||
expect(this.collection.latestModelsCount).toEqual(1);
|
||||
expect(this.collection.accessDeniedCount).toEqual(1);
|
||||
expect(this.collection.page).toEqual(0);
|
||||
expect(this.collection.totalCount).toEqual(0);
|
||||
expect(this.collection.latestModelsCount).toEqual(0);
|
||||
expect(this.collection.first().attributes).toEqual(response.results[0].data);
|
||||
});
|
||||
|
||||
it('resets state when canceling a search', function () {
|
||||
it('handles errors', function () {
|
||||
var requests = AjaxHelpers.requests(this);
|
||||
this.collection.performSearch('search string');
|
||||
AjaxHelpers.respondWithError(requests, 500);
|
||||
expect(this.onSearch).not.toHaveBeenCalled();
|
||||
expect(this.onError).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('loads next page', function () {
|
||||
var requests = AjaxHelpers.requests(this);
|
||||
var response = { total: 35, results: [] };
|
||||
this.collection.loadNextPage();
|
||||
AjaxHelpers.respondWithJson(requests, response);
|
||||
expect(this.onNext).toHaveBeenCalled();
|
||||
expect(this.onError).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('sends correct paging parameters', function () {
|
||||
var requests = AjaxHelpers.requests(this);
|
||||
var searchString = 'search string';
|
||||
var response = { total: 52, results: [] };
|
||||
this.collection.performSearch(searchString);
|
||||
AjaxHelpers.respondWithJson(requests, response);
|
||||
this.collection.loadNextPage();
|
||||
AjaxHelpers.respondWithJson(requests, response);
|
||||
spyOn($, 'ajax');
|
||||
this.collection.loadNextPage();
|
||||
expect($.ajax.mostRecentCall.args[0].url).toEqual(this.collection.url);
|
||||
expect($.ajax.mostRecentCall.args[0].data.search_string).toEqual(searchString);
|
||||
expect($.ajax.mostRecentCall.args[0].data.page_size).toEqual(this.collection.pageSize);
|
||||
expect($.ajax.mostRecentCall.args[0].data.page_index).toEqual(2);
|
||||
});
|
||||
|
||||
it('has next page', function () {
|
||||
var requests = AjaxHelpers.requests(this);
|
||||
var response = { total: 35, access_denied_count: 5, results: [] };
|
||||
this.collection.performSearch('search string');
|
||||
AjaxHelpers.respondWithJson(requests, response);
|
||||
expect(this.collection.hasNextPage()).toEqual(true);
|
||||
this.collection.loadNextPage();
|
||||
AjaxHelpers.respondWithJson(requests, response);
|
||||
expect(this.collection.hasNextPage()).toEqual(false);
|
||||
});
|
||||
|
||||
it('aborts any previous request', function () {
|
||||
var requests = AjaxHelpers.requests(this);
|
||||
var response = { total: 35, results: [] };
|
||||
|
||||
this.collection.performSearch('old search');
|
||||
this.collection.performSearch('new search');
|
||||
AjaxHelpers.respondWithJson(requests, response);
|
||||
expect(this.onSearch.calls.length).toEqual(1);
|
||||
|
||||
this.collection.performSearch('old search');
|
||||
this.collection.cancelSearch();
|
||||
expect(this.collection.models.length).toEqual(0);
|
||||
expect(this.collection.page).toEqual(0);
|
||||
expect(this.collection.totalCount).toEqual(0);
|
||||
expect(this.collection.latestModelsCount).toEqual(0);
|
||||
AjaxHelpers.respondWithJson(requests, response);
|
||||
expect(this.onSearch.calls.length).toEqual(1);
|
||||
|
||||
this.collection.loadNextPage();
|
||||
this.collection.loadNextPage();
|
||||
AjaxHelpers.respondWithJson(requests, response);
|
||||
expect(this.onNext.calls.length).toEqual(1);
|
||||
});
|
||||
|
||||
describe('reset state', function () {
|
||||
|
||||
beforeEach(function () {
|
||||
this.collection.page = 2;
|
||||
this.collection.totalCount = 35;
|
||||
this.collection.latestModelsCount = 5;
|
||||
});
|
||||
|
||||
it('resets state when performing new search', function () {
|
||||
this.collection.performSearch('search string');
|
||||
expect(this.collection.models.length).toEqual(0);
|
||||
expect(this.collection.page).toEqual(0);
|
||||
expect(this.collection.totalCount).toEqual(0);
|
||||
expect(this.collection.latestModelsCount).toEqual(0);
|
||||
});
|
||||
|
||||
it('resets state when canceling a search', function () {
|
||||
this.collection.cancelSearch();
|
||||
expect(this.collection.models.length).toEqual(0);
|
||||
expect(this.collection.page).toEqual(0);
|
||||
expect(this.collection.totalCount).toEqual(0);
|
||||
expect(this.collection.latestModelsCount).toEqual(0);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('SearchRouter', function () {
|
||||
|
||||
describe('SearchRouter', function () {
|
||||
|
||||
beforeEach(function () {
|
||||
this.router = new SearchRouter();
|
||||
this.onSearch = jasmine.createSpy('onSearch');
|
||||
this.router.on('search', this.onSearch);
|
||||
});
|
||||
|
||||
it ('has a search route', function () {
|
||||
expect(this.router.routes['search/:query']).toEqual('search');
|
||||
});
|
||||
|
||||
it ('triggers a search event', function () {
|
||||
var query = 'mercury';
|
||||
this.router.search(query);
|
||||
expect(this.onSearch).toHaveBeenCalledWith(query);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
describe('SearchItemView', function () {
|
||||
|
||||
function beforeEachHelper(SearchItemView) {
|
||||
TemplateHelpers.installTemplates([
|
||||
'templates/search/course_search_item',
|
||||
'templates/search/dashboard_search_item'
|
||||
]);
|
||||
|
||||
this.model = new SearchResult({
|
||||
location: ['section', 'subsection', 'unit'],
|
||||
content_type: 'Video',
|
||||
course_name: 'Course Name',
|
||||
excerpt: 'A short excerpt.',
|
||||
url: 'path/to/content'
|
||||
});
|
||||
|
||||
this.seqModel = new SearchResult({
|
||||
location: ['section', 'subsection'],
|
||||
content_type: 'Sequence',
|
||||
course_name: 'Course Name',
|
||||
excerpt: 'A short excerpt.',
|
||||
url: 'path/to/content'
|
||||
});
|
||||
|
||||
this.item = new SearchItemView({ model: this.model });
|
||||
this.item.render();
|
||||
this.seqItem = new SearchItemView({ model: this.seqModel });
|
||||
this.seqItem.render();
|
||||
}
|
||||
|
||||
function rendersItem() {
|
||||
expect(this.item.$el).toHaveAttr('role', 'region');
|
||||
expect(this.item.$el).toHaveAttr('aria-label', 'search result');
|
||||
expect(this.item.$el).toContain('a[href="' + this.model.get('url') + '"]');
|
||||
expect(this.item.$el.find('.result-type')).toContainHtml(this.model.get('content_type'));
|
||||
expect(this.item.$el.find('.result-excerpt')).toContainHtml(this.model.get('excerpt'));
|
||||
expect(this.item.$el.find('.result-location')).toContainHtml('section ▸ subsection ▸ unit');
|
||||
}
|
||||
|
||||
function rendersSequentialItem() {
|
||||
expect(this.seqItem.$el).toHaveAttr('role', 'region');
|
||||
expect(this.seqItem.$el).toHaveAttr('aria-label', 'search result');
|
||||
expect(this.seqItem.$el).toContain('a[href="' + this.seqModel.get('url') + '"]');
|
||||
expect(this.seqItem.$el.find('.result-type')).toBeEmpty();
|
||||
expect(this.seqItem.$el.find('.result-excerpt')).toBeEmpty();
|
||||
expect(this.seqItem.$el.find('.result-location')).toContainHtml('section ▸ subsection');
|
||||
}
|
||||
|
||||
function logsSearchItemViewEvent() {
|
||||
this.model.collection = new SearchCollection([this.model], { course_id: 'edx101' });
|
||||
this.item.render();
|
||||
// Mock the redirect call
|
||||
spyOn(this.item, 'redirect').andCallFake( function() {} );
|
||||
spyOn(Logger, 'log').andReturn($.Deferred().resolve());
|
||||
this.item.$el.find('a').trigger('click');
|
||||
expect(this.item.redirect).toHaveBeenCalled();
|
||||
this.item.$el.trigger('click');
|
||||
expect(this.item.redirect).toHaveBeenCalled();
|
||||
}
|
||||
|
||||
describe('CourseSearchItemView', function () {
|
||||
beforeEach(function () {
|
||||
beforeEachHelper.call(this, CourseSearchItemView);
|
||||
});
|
||||
it('renders items correctly', rendersItem);
|
||||
it('renders Sequence items correctly', rendersSequentialItem);
|
||||
it('logs view event', logsSearchItemViewEvent);
|
||||
});
|
||||
|
||||
describe('DashSearchItemView', function () {
|
||||
beforeEach(function () {
|
||||
beforeEachHelper.call(this, DashSearchItemView);
|
||||
});
|
||||
it('renders items correctly', rendersItem);
|
||||
it('renders Sequence items correctly', rendersSequentialItem);
|
||||
it('displays course name in breadcrumbs', function () {
|
||||
expect(this.seqItem.$el.find('.result-course-name')).toContainHtml(this.model.get('course_name'));
|
||||
});
|
||||
it('logs view event', logsSearchItemViewEvent);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
describe('SearchForm', function () {
|
||||
|
||||
function trimsInputString() {
|
||||
var term = ' search string ';
|
||||
$('.search-field').val(term);
|
||||
$('form').trigger('submit');
|
||||
expect(this.onSearch).toHaveBeenCalledWith($.trim(term));
|
||||
}
|
||||
|
||||
function doesSearch() {
|
||||
var term = ' search string ';
|
||||
$('.search-field').val(term);
|
||||
this.form.doSearch(term);
|
||||
expect(this.onSearch).toHaveBeenCalledWith($.trim(term));
|
||||
expect($('.search-field').val()).toEqual(term);
|
||||
expect($('.search-field')).toHaveClass('is-active');
|
||||
expect($('.search-button')).toBeHidden();
|
||||
expect($('.cancel-button')).toBeVisible();
|
||||
}
|
||||
|
||||
function triggersSearchEvent() {
|
||||
var term = 'search string';
|
||||
$('.search-field').val(term);
|
||||
$('form').trigger('submit');
|
||||
expect(this.onSearch).toHaveBeenCalledWith(term);
|
||||
expect($('.search-field')).toHaveClass('is-active');
|
||||
expect($('.search-button')).toBeHidden();
|
||||
expect($('.cancel-button')).toBeVisible();
|
||||
}
|
||||
|
||||
function clearsSearchOnCancel() {
|
||||
$('.search-field').val('search string');
|
||||
$('.search-button').trigger('click');
|
||||
$('.cancel-button').trigger('click');
|
||||
expect($('.search-field')).not.toHaveClass('is-active');
|
||||
expect($('.search-button')).toBeVisible();
|
||||
expect($('.cancel-button')).toBeHidden();
|
||||
expect($('.search-field')).toHaveValue('');
|
||||
}
|
||||
|
||||
function clearsSearchOnEmpty() {
|
||||
$('.search-field').val('');
|
||||
$('form').trigger('submit');
|
||||
expect(this.onClear).toHaveBeenCalled();
|
||||
expect($('.search-field')).not.toHaveClass('is-active');
|
||||
expect($('.cancel-button')).toBeHidden();
|
||||
expect($('.search-button')).toBeVisible();
|
||||
}
|
||||
|
||||
describe('CourseSearchForm', function () {
|
||||
beforeEach(function () {
|
||||
loadFixtures('js/fixtures/search/course_search_form.html');
|
||||
this.form = new CourseSearchForm();
|
||||
this.onClear = jasmine.createSpy('onClear');
|
||||
this.router = new SearchRouter();
|
||||
this.onSearch = jasmine.createSpy('onSearch');
|
||||
this.form.on('clear', this.onClear);
|
||||
this.form.on('search', this.onSearch);
|
||||
this.router.on('search', this.onSearch);
|
||||
});
|
||||
it('trims input string', trimsInputString);
|
||||
it('handles calls to doSearch', doesSearch);
|
||||
it('triggers a search event and changes to active state', triggersSearchEvent);
|
||||
it('clears search when clicking on cancel button', clearsSearchOnCancel);
|
||||
it('clears search when search box is empty', clearsSearchOnEmpty);
|
||||
|
||||
it ('has a search route', function () {
|
||||
expect(this.router.routes['search/:query']).toEqual('search');
|
||||
});
|
||||
|
||||
it ('triggers a search event', function () {
|
||||
var query = 'mercury';
|
||||
this.router.search(query);
|
||||
expect(this.onSearch).toHaveBeenCalledWith(query);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('DashSearchForm', function () {
|
||||
beforeEach(function () {
|
||||
loadFixtures('js/fixtures/search/dashboard_search_form.html');
|
||||
this.form = new DashSearchForm();
|
||||
this.onClear = jasmine.createSpy('onClear');
|
||||
this.onSearch = jasmine.createSpy('onSearch');
|
||||
this.form.on('clear', this.onClear);
|
||||
this.form.on('search', this.onSearch);
|
||||
|
||||
describe('SearchItemView', function () {
|
||||
|
||||
function beforeEachHelper(SearchItemView) {
|
||||
TemplateHelpers.installTemplates([
|
||||
'templates/search/course_search_item',
|
||||
'templates/search/dashboard_search_item'
|
||||
]);
|
||||
|
||||
this.model = new SearchResult({
|
||||
location: ['section', 'subsection', 'unit'],
|
||||
content_type: 'Video',
|
||||
course_name: 'Course Name',
|
||||
excerpt: 'A short excerpt.',
|
||||
url: 'path/to/content'
|
||||
});
|
||||
|
||||
this.seqModel = new SearchResult({
|
||||
location: ['section', 'subsection'],
|
||||
content_type: 'Sequence',
|
||||
course_name: 'Course Name',
|
||||
excerpt: 'A short excerpt.',
|
||||
url: 'path/to/content'
|
||||
});
|
||||
|
||||
this.item = new SearchItemView({ model: this.model });
|
||||
this.item.render();
|
||||
this.seqItem = new SearchItemView({ model: this.seqModel });
|
||||
this.seqItem.render();
|
||||
}
|
||||
|
||||
function rendersItem() {
|
||||
expect(this.item.$el).toHaveAttr('role', 'region');
|
||||
expect(this.item.$el).toHaveAttr('aria-label', 'search result');
|
||||
expect(this.item.$el).toContain('a[href="' + this.model.get('url') + '"]');
|
||||
expect(this.item.$el.find('.result-type')).toContainHtml(this.model.get('content_type'));
|
||||
expect(this.item.$el.find('.result-excerpt')).toContainHtml(this.model.get('excerpt'));
|
||||
expect(this.item.$el.find('.result-location')).toContainHtml('section ▸ subsection ▸ unit');
|
||||
}
|
||||
|
||||
function rendersSequentialItem() {
|
||||
expect(this.seqItem.$el).toHaveAttr('role', 'region');
|
||||
expect(this.seqItem.$el).toHaveAttr('aria-label', 'search result');
|
||||
expect(this.seqItem.$el).toContain('a[href="' + this.seqModel.get('url') + '"]');
|
||||
expect(this.seqItem.$el.find('.result-type')).toBeEmpty();
|
||||
expect(this.seqItem.$el.find('.result-excerpt')).toBeEmpty();
|
||||
expect(this.seqItem.$el.find('.result-location')).toContainHtml('section ▸ subsection');
|
||||
}
|
||||
|
||||
function logsSearchItemViewEvent() {
|
||||
this.model.collection = new SearchCollection([this.model], { course_id: 'edx101' });
|
||||
this.item.render();
|
||||
// Mock the redirect call
|
||||
spyOn(this.item, 'redirect').andCallFake( function() {} );
|
||||
spyOn(Logger, 'log').andReturn($.Deferred().resolve());
|
||||
this.item.$el.find('a').trigger('click');
|
||||
expect(this.item.redirect).toHaveBeenCalled();
|
||||
this.item.$el.trigger('click');
|
||||
expect(this.item.redirect).toHaveBeenCalled();
|
||||
}
|
||||
|
||||
describe('CourseSearchItemView', function () {
|
||||
beforeEach(function () {
|
||||
beforeEachHelper.call(this, CourseSearchItemView);
|
||||
});
|
||||
it('renders items correctly', rendersItem);
|
||||
it('renders Sequence items correctly', rendersSequentialItem);
|
||||
it('logs view event', logsSearchItemViewEvent);
|
||||
});
|
||||
it('trims input string', trimsInputString);
|
||||
it('handles calls to doSearch', doesSearch);
|
||||
it('triggers a search event and changes to active state', triggersSearchEvent);
|
||||
it('clears search when clicking on cancel button', clearsSearchOnCancel);
|
||||
it('clears search when search box is empty', clearsSearchOnEmpty);
|
||||
|
||||
describe('DashSearchItemView', function () {
|
||||
beforeEach(function () {
|
||||
beforeEachHelper.call(this, DashSearchItemView);
|
||||
});
|
||||
it('renders items correctly', rendersItem);
|
||||
it('renders Sequence items correctly', rendersSequentialItem);
|
||||
it('displays course name in breadcrumbs', function () {
|
||||
expect(this.seqItem.$el.find('.result-course-name')).toContainHtml(this.model.get('course_name'));
|
||||
});
|
||||
it('logs view event', logsSearchItemViewEvent);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('SearchForm', function () {
|
||||
|
||||
describe('SearchResultsView', function () {
|
||||
function trimsInputString() {
|
||||
var term = ' search string ';
|
||||
$('.search-field').val(term);
|
||||
$('form').trigger('submit');
|
||||
expect(this.onSearch).toHaveBeenCalledWith($.trim(term));
|
||||
}
|
||||
|
||||
function showsLoadingMessage () {
|
||||
this.resultsView.showLoadingMessage();
|
||||
expect(this.resultsView.$contentElement).toBeHidden();
|
||||
expect(this.resultsView.$el).toBeVisible();
|
||||
expect(this.resultsView.$el).not.toBeEmpty();
|
||||
}
|
||||
function doesSearch() {
|
||||
var term = ' search string ';
|
||||
$('.search-field').val(term);
|
||||
this.form.doSearch(term);
|
||||
expect(this.onSearch).toHaveBeenCalledWith($.trim(term));
|
||||
expect($('.search-field').val()).toEqual(term);
|
||||
expect($('.search-field')).toHaveClass('is-active');
|
||||
expect($('.search-button')).toBeHidden();
|
||||
expect($('.cancel-button')).toBeVisible();
|
||||
}
|
||||
|
||||
function showsErrorMessage () {
|
||||
this.resultsView.showErrorMessage();
|
||||
expect(this.resultsView.$contentElement).toBeHidden();
|
||||
expect(this.resultsView.$el).toBeVisible();
|
||||
expect(this.resultsView.$el).not.toBeEmpty();
|
||||
}
|
||||
function triggersSearchEvent() {
|
||||
var term = 'search string';
|
||||
$('.search-field').val(term);
|
||||
$('form').trigger('submit');
|
||||
expect(this.onSearch).toHaveBeenCalledWith(term);
|
||||
expect($('.search-field')).toHaveClass('is-active');
|
||||
expect($('.search-button')).toBeHidden();
|
||||
expect($('.cancel-button')).toBeVisible();
|
||||
}
|
||||
|
||||
function returnsToContent () {
|
||||
this.resultsView.clear();
|
||||
expect(this.resultsView.$contentElement).toBeVisible();
|
||||
expect(this.resultsView.$el).toBeHidden();
|
||||
expect(this.resultsView.$el).toBeEmpty();
|
||||
}
|
||||
function clearsSearchOnCancel() {
|
||||
$('.search-field').val('search string');
|
||||
$('.search-button').trigger('click');
|
||||
$('.cancel-button').trigger('click');
|
||||
expect($('.search-field')).not.toHaveClass('is-active');
|
||||
expect($('.search-button')).toBeVisible();
|
||||
expect($('.cancel-button')).toBeHidden();
|
||||
expect($('.search-field')).toHaveValue('');
|
||||
}
|
||||
|
||||
function showsNoResultsMessage() {
|
||||
this.collection.reset();
|
||||
this.resultsView.render();
|
||||
expect(this.resultsView.$el).toContainHtml('no results');
|
||||
expect(this.resultsView.$el.find('ol')).not.toExist();
|
||||
}
|
||||
function clearsSearchOnEmpty() {
|
||||
$('.search-field').val('');
|
||||
$('form').trigger('submit');
|
||||
expect(this.onClear).toHaveBeenCalled();
|
||||
expect($('.search-field')).not.toHaveClass('is-active');
|
||||
expect($('.cancel-button')).toBeHidden();
|
||||
expect($('.search-button')).toBeVisible();
|
||||
}
|
||||
|
||||
function rendersSearchResults () {
|
||||
var searchResults = [{
|
||||
location: ['section', 'subsection', 'unit'],
|
||||
url: '/some/url/to/content',
|
||||
content_type: 'text',
|
||||
course_name: '',
|
||||
excerpt: 'this is a short excerpt'
|
||||
}];
|
||||
this.collection.set(searchResults);
|
||||
this.collection.latestModelsCount = 1;
|
||||
this.collection.totalCount = 1;
|
||||
|
||||
this.resultsView.render();
|
||||
expect(this.resultsView.$el.find('ol')[0]).toExist();
|
||||
expect(this.resultsView.$el.find('li').length).toEqual(1);
|
||||
expect(this.resultsView.$el).toContainHtml('Search Results');
|
||||
expect(this.resultsView.$el).toContainHtml('this is a short excerpt');
|
||||
|
||||
this.collection.set(searchResults);
|
||||
this.collection.totalCount = 2;
|
||||
this.resultsView.renderNext();
|
||||
expect(this.resultsView.$el.find('.search-count')).toContainHtml('2');
|
||||
expect(this.resultsView.$el.find('li').length).toEqual(2);
|
||||
}
|
||||
|
||||
function showsMoreResultsLink () {
|
||||
this.collection.totalCount = 123;
|
||||
this.collection.hasNextPage = function () { return true; };
|
||||
this.resultsView.render();
|
||||
expect(this.resultsView.$el.find('a.search-load-next')[0]).toExist();
|
||||
|
||||
this.collection.totalCount = 123;
|
||||
this.collection.hasNextPage = function () { return false; };
|
||||
this.resultsView.render();
|
||||
expect(this.resultsView.$el.find('a.search-load-next')[0]).not.toExist();
|
||||
}
|
||||
|
||||
function triggersNextPageEvent () {
|
||||
var onNext = jasmine.createSpy('onNext');
|
||||
this.resultsView.on('next', onNext);
|
||||
this.collection.totalCount = 123;
|
||||
this.collection.hasNextPage = function () { return true; };
|
||||
this.resultsView.render();
|
||||
this.resultsView.$el.find('a.search-load-next').click();
|
||||
expect(onNext).toHaveBeenCalled();
|
||||
}
|
||||
|
||||
function showsLoadMoreSpinner () {
|
||||
this.collection.totalCount = 123;
|
||||
this.collection.hasNextPage = function () { return true; };
|
||||
this.resultsView.render();
|
||||
expect(this.resultsView.$el.find('a.search-load-next .icon')).toBeHidden();
|
||||
this.resultsView.loadNext();
|
||||
// toBeVisible does not work with inline
|
||||
expect(this.resultsView.$el.find('a.search-load-next .icon')).toHaveCss({ 'display': 'inline' });
|
||||
this.resultsView.renderNext();
|
||||
expect(this.resultsView.$el.find('a.search-load-next .icon')).toBeHidden();
|
||||
}
|
||||
|
||||
function beforeEachHelper(SearchResultsView) {
|
||||
appendSetFixtures(
|
||||
'<section id="courseware-search-results"></section>' +
|
||||
'<section id="course-content"></section>' +
|
||||
'<section id="dashboard-search-results"></section>' +
|
||||
'<section id="my-courses"></section>'
|
||||
);
|
||||
|
||||
TemplateHelpers.installTemplates([
|
||||
'templates/search/course_search_item',
|
||||
'templates/search/dashboard_search_item',
|
||||
'templates/search/course_search_results',
|
||||
'templates/search/dashboard_search_results',
|
||||
'templates/search/search_list',
|
||||
'templates/search/search_loading',
|
||||
'templates/search/search_error'
|
||||
]);
|
||||
|
||||
var MockCollection = Backbone.Collection.extend({
|
||||
hasNextPage: function () {},
|
||||
latestModelsCount: 0,
|
||||
pageSize: 20,
|
||||
latestModels: function () {
|
||||
return SearchCollection.prototype.latestModels.apply(this, arguments);
|
||||
}
|
||||
describe('CourseSearchForm', function () {
|
||||
beforeEach(function () {
|
||||
loadFixtures('js/fixtures/search/course_search_form.html');
|
||||
this.form = new CourseSearchForm();
|
||||
this.onClear = jasmine.createSpy('onClear');
|
||||
this.onSearch = jasmine.createSpy('onSearch');
|
||||
this.form.on('clear', this.onClear);
|
||||
this.form.on('search', this.onSearch);
|
||||
});
|
||||
it('trims input string', trimsInputString);
|
||||
it('handles calls to doSearch', doesSearch);
|
||||
it('triggers a search event and changes to active state', triggersSearchEvent);
|
||||
it('clears search when clicking on cancel button', clearsSearchOnCancel);
|
||||
it('clears search when search box is empty', clearsSearchOnEmpty);
|
||||
});
|
||||
this.collection = new MockCollection();
|
||||
this.resultsView = new SearchResultsView({ collection: this.collection });
|
||||
}
|
||||
|
||||
describe('CourseSearchResultsView', function () {
|
||||
beforeEach(function() {
|
||||
beforeEachHelper.call(this, CourseSearchResultsView);
|
||||
describe('DashSearchForm', function () {
|
||||
beforeEach(function () {
|
||||
loadFixtures('js/fixtures/search/dashboard_search_form.html');
|
||||
this.form = new DashSearchForm();
|
||||
this.onClear = jasmine.createSpy('onClear');
|
||||
this.onSearch = jasmine.createSpy('onSearch');
|
||||
this.form.on('clear', this.onClear);
|
||||
this.form.on('search', this.onSearch);
|
||||
});
|
||||
it('trims input string', trimsInputString);
|
||||
it('handles calls to doSearch', doesSearch);
|
||||
it('triggers a search event and changes to active state', triggersSearchEvent);
|
||||
it('clears search when clicking on cancel button', clearsSearchOnCancel);
|
||||
it('clears search when search box is empty', clearsSearchOnEmpty);
|
||||
});
|
||||
it('shows loading message', showsLoadingMessage);
|
||||
it('shows error message', showsErrorMessage);
|
||||
it('returns to content', returnsToContent);
|
||||
it('shows a message when there are no results', showsNoResultsMessage);
|
||||
it('renders search results', rendersSearchResults);
|
||||
it('shows a link to load more results', showsMoreResultsLink);
|
||||
it('triggers an event for next page', triggersNextPageEvent);
|
||||
it('shows a spinner when loading more results', showsLoadMoreSpinner);
|
||||
|
||||
});
|
||||
|
||||
describe('DashSearchResultsView', function () {
|
||||
beforeEach(function() {
|
||||
beforeEachHelper.call(this, DashSearchResultsView);
|
||||
});
|
||||
it('shows loading message', showsLoadingMessage);
|
||||
it('shows error message', showsErrorMessage);
|
||||
it('returns to content', returnsToContent);
|
||||
it('shows a message when there are no results', showsNoResultsMessage);
|
||||
it('renders search results', rendersSearchResults);
|
||||
it('shows a link to load more results', showsMoreResultsLink);
|
||||
it('triggers an event for next page', triggersNextPageEvent);
|
||||
it('shows a spinner when loading more results', showsLoadMoreSpinner);
|
||||
it('returns back to courses', function () {
|
||||
var onReset = jasmine.createSpy('onReset');
|
||||
this.resultsView.on('reset', onReset);
|
||||
this.resultsView.render();
|
||||
expect(this.resultsView.$el.find('a.search-back-to-courses')).toExist();
|
||||
this.resultsView.$el.find('.search-back-to-courses').click();
|
||||
expect(onReset).toHaveBeenCalled();
|
||||
|
||||
describe('SearchResultsView', function () {
|
||||
|
||||
function showsLoadingMessage () {
|
||||
this.resultsView.showLoadingMessage();
|
||||
expect(this.resultsView.$contentElement).toBeHidden();
|
||||
expect(this.resultsView.$el).toBeVisible();
|
||||
expect(this.resultsView.$el).not.toBeEmpty();
|
||||
}
|
||||
|
||||
function showsErrorMessage () {
|
||||
this.resultsView.showErrorMessage();
|
||||
expect(this.resultsView.$contentElement).toBeHidden();
|
||||
expect(this.resultsView.$el).toBeVisible();
|
||||
expect(this.resultsView.$el).not.toBeEmpty();
|
||||
}
|
||||
|
||||
function returnsToContent () {
|
||||
this.resultsView.clear();
|
||||
expect(this.resultsView.$contentElement).toBeVisible();
|
||||
expect(this.resultsView.$el).toBeHidden();
|
||||
});
|
||||
});
|
||||
expect(this.resultsView.$el).toBeEmpty();
|
||||
}
|
||||
|
||||
});
|
||||
function showsNoResultsMessage() {
|
||||
this.collection.reset();
|
||||
this.resultsView.render();
|
||||
expect(this.resultsView.$el).toContainHtml('no results');
|
||||
expect(this.resultsView.$el.find('ol')).not.toExist();
|
||||
}
|
||||
|
||||
function rendersSearchResults () {
|
||||
var searchResults = [{
|
||||
location: ['section', 'subsection', 'unit'],
|
||||
url: '/some/url/to/content',
|
||||
content_type: 'text',
|
||||
course_name: '',
|
||||
excerpt: 'this is a short excerpt'
|
||||
}];
|
||||
this.collection.set(searchResults);
|
||||
this.collection.latestModelsCount = 1;
|
||||
this.collection.totalCount = 1;
|
||||
|
||||
describe('SearchApp', function () {
|
||||
this.resultsView.render();
|
||||
expect(this.resultsView.$el.find('ol')[0]).toExist();
|
||||
expect(this.resultsView.$el.find('li').length).toEqual(1);
|
||||
expect(this.resultsView.$el).toContainHtml('Search Results');
|
||||
expect(this.resultsView.$el).toContainHtml('this is a short excerpt');
|
||||
|
||||
function showsLoadingMessage () {
|
||||
$('.search-field').val('search string');
|
||||
$('.search-button').trigger('click');
|
||||
expect(this.$contentElement).toBeHidden();
|
||||
expect(this.$searchResults).toBeVisible();
|
||||
expect(this.$searchResults).not.toBeEmpty();
|
||||
}
|
||||
this.collection.set(searchResults);
|
||||
this.collection.totalCount = 2;
|
||||
this.resultsView.renderNext();
|
||||
expect(this.resultsView.$el.find('.search-count')).toContainHtml('2');
|
||||
expect(this.resultsView.$el.find('li').length).toEqual(2);
|
||||
}
|
||||
|
||||
function performsSearch () {
|
||||
var requests = AjaxHelpers.requests(this);
|
||||
$('.search-field').val('search string');
|
||||
$('.search-button').trigger('click');
|
||||
AjaxHelpers.respondWithJson(requests, {
|
||||
total: 1337,
|
||||
access_denied_count: 12,
|
||||
results: [{
|
||||
data: {
|
||||
location: ['section', 'subsection', 'unit'],
|
||||
url: '/some/url/to/content',
|
||||
content_type: 'text',
|
||||
excerpt: 'this is a short excerpt',
|
||||
course_name: ''
|
||||
}
|
||||
}]
|
||||
});
|
||||
expect($('.search-info')).toExist();
|
||||
expect($('.search-result-list')).toBeVisible();
|
||||
expect(this.$searchResults.find('li').length).toEqual(1);
|
||||
}
|
||||
function showsMoreResultsLink () {
|
||||
this.collection.totalCount = 123;
|
||||
this.collection.hasNextPage = function () { return true; };
|
||||
this.resultsView.render();
|
||||
expect(this.resultsView.$el.find('a.search-load-next')[0]).toExist();
|
||||
|
||||
function showsErrorMessage () {
|
||||
var requests = AjaxHelpers.requests(this);
|
||||
$('.search-field').val('search string');
|
||||
$('.search-button').trigger('click');
|
||||
AjaxHelpers.respondWithError(requests, 500, {});
|
||||
expect(this.$searchResults).toContainHtml('There was an error');
|
||||
}
|
||||
this.collection.totalCount = 123;
|
||||
this.collection.hasNextPage = function () { return false; };
|
||||
this.resultsView.render();
|
||||
expect(this.resultsView.$el.find('a.search-load-next')[0]).not.toExist();
|
||||
}
|
||||
|
||||
function updatesNavigationHistory () {
|
||||
$('.search-field').val('edx');
|
||||
$('.search-button').trigger('click');
|
||||
expect(Backbone.history.navigate.calls[0].args).toContain('search/edx');
|
||||
$('.cancel-button').trigger('click');
|
||||
expect(Backbone.history.navigate.calls[1].args).toContain('');
|
||||
}
|
||||
function triggersNextPageEvent () {
|
||||
var onNext = jasmine.createSpy('onNext');
|
||||
this.resultsView.on('next', onNext);
|
||||
this.collection.totalCount = 123;
|
||||
this.collection.hasNextPage = function () { return true; };
|
||||
this.resultsView.render();
|
||||
this.resultsView.$el.find('a.search-load-next').click();
|
||||
expect(onNext).toHaveBeenCalled();
|
||||
}
|
||||
|
||||
function cancelsSearchRequest () {
|
||||
var requests = AjaxHelpers.requests(this);
|
||||
// send search request to server
|
||||
$('.search-field').val('search string');
|
||||
$('.search-button').trigger('click');
|
||||
// cancel search
|
||||
$('.cancel-button').trigger('click');
|
||||
AjaxHelpers.respondWithJson(requests, {
|
||||
total: 1337,
|
||||
access_denied_count: 12,
|
||||
results: [{
|
||||
data: {
|
||||
location: ['section', 'subsection', 'unit'],
|
||||
url: '/some/url/to/content',
|
||||
content_type: 'text',
|
||||
excerpt: 'this is a short excerpt',
|
||||
course_name: ''
|
||||
}
|
||||
}]
|
||||
});
|
||||
// there should be no results
|
||||
expect(this.$contentElement).toBeVisible();
|
||||
expect(this.$searchResults).toBeHidden();
|
||||
}
|
||||
function showsLoadMoreSpinner () {
|
||||
this.collection.totalCount = 123;
|
||||
this.collection.hasNextPage = function () { return true; };
|
||||
this.resultsView.render();
|
||||
expect(this.resultsView.$el.find('a.search-load-next .icon')).toBeHidden();
|
||||
this.resultsView.loadNext();
|
||||
// toBeVisible does not work with inline
|
||||
expect(this.resultsView.$el.find('a.search-load-next .icon')).toHaveCss({ 'display': 'inline' });
|
||||
this.resultsView.renderNext();
|
||||
expect(this.resultsView.$el.find('a.search-load-next .icon')).toBeHidden();
|
||||
}
|
||||
|
||||
function clearsResults () {
|
||||
$('.cancel-button').trigger('click');
|
||||
expect(this.$contentElement).toBeVisible();
|
||||
expect(this.$searchResults).toBeHidden();
|
||||
}
|
||||
|
||||
function loadsNextPage () {
|
||||
var requests = AjaxHelpers.requests(this);
|
||||
var response = {
|
||||
total: 1337,
|
||||
access_denied_count: 12,
|
||||
results: [{
|
||||
data: {
|
||||
location: ['section', 'subsection', 'unit'],
|
||||
url: '/some/url/to/content',
|
||||
content_type: 'text',
|
||||
excerpt: 'this is a short excerpt',
|
||||
course_name: ''
|
||||
}
|
||||
}]
|
||||
};
|
||||
$('.search-field').val('query');
|
||||
$('.search-button').trigger('click');
|
||||
AjaxHelpers.respondWithJson(requests, response);
|
||||
expect(this.$searchResults.find('li').length).toEqual(1);
|
||||
expect($('.search-load-next')).toBeVisible();
|
||||
$('.search-load-next').trigger('click');
|
||||
var body = requests[1].requestBody;
|
||||
expect(body).toContain('search_string=query');
|
||||
expect(body).toContain('page_index=1');
|
||||
AjaxHelpers.respondWithJson(requests, response);
|
||||
expect(this.$searchResults.find('li').length).toEqual(2);
|
||||
}
|
||||
|
||||
function navigatesToSearch () {
|
||||
var requests = AjaxHelpers.requests(this);
|
||||
Backbone.history.loadUrl('search/query');
|
||||
expect(requests[0].requestBody).toContain('search_string=query');
|
||||
}
|
||||
|
||||
function loadTemplates () {
|
||||
TemplateHelpers.installTemplates([
|
||||
'templates/search/course_search_item',
|
||||
'templates/search/dashboard_search_item',
|
||||
'templates/search/search_loading',
|
||||
'templates/search/search_error',
|
||||
'templates/search/course_search_results',
|
||||
'templates/search/dashboard_search_results'
|
||||
]);
|
||||
}
|
||||
|
||||
describe('CourseSearchApp', function () {
|
||||
|
||||
beforeEach(function () {
|
||||
loadFixtures('js/fixtures/search/course_search_form.html');
|
||||
function beforeEachHelper(SearchResultsView) {
|
||||
appendSetFixtures(
|
||||
'<section id="courseware-search-results"></section>' +
|
||||
'<section id="course-content"></section>'
|
||||
);
|
||||
loadTemplates.call(this);
|
||||
|
||||
var courseId = 'a/b/c';
|
||||
CourseSearchFactory(courseId);
|
||||
spyOn(Backbone.history, 'navigate');
|
||||
this.$contentElement = $('#course-content');
|
||||
this.$searchResults = $('#courseware-search-results');
|
||||
});
|
||||
|
||||
it('shows loading message on search', showsLoadingMessage);
|
||||
it('performs search', performsSearch);
|
||||
it('shows an error message', showsErrorMessage);
|
||||
it('updates navigation history', updatesNavigationHistory);
|
||||
it('cancels search request', cancelsSearchRequest);
|
||||
it('clears results', clearsResults);
|
||||
it('loads next page', loadsNextPage);
|
||||
it('navigates to search', navigatesToSearch);
|
||||
|
||||
});
|
||||
|
||||
describe('DashSearchApp', function () {
|
||||
|
||||
beforeEach(function () {
|
||||
loadFixtures('js/fixtures/search/dashboard_search_form.html');
|
||||
appendSetFixtures(
|
||||
'<section id="course-content"></section>' +
|
||||
'<section id="dashboard-search-results"></section>' +
|
||||
'<section id="my-courses"></section>'
|
||||
);
|
||||
loadTemplates.call(this);
|
||||
DashboardSearchFactory();
|
||||
|
||||
spyOn(Backbone.history, 'navigate');
|
||||
this.$contentElement = $('#my-courses');
|
||||
this.$searchResults = $('#dashboard-search-results');
|
||||
TemplateHelpers.installTemplates([
|
||||
'templates/search/course_search_item',
|
||||
'templates/search/dashboard_search_item',
|
||||
'templates/search/course_search_results',
|
||||
'templates/search/dashboard_search_results',
|
||||
'templates/search/search_list',
|
||||
'templates/search/search_loading',
|
||||
'templates/search/search_error'
|
||||
]);
|
||||
|
||||
var MockCollection = Backbone.Collection.extend({
|
||||
hasNextPage: function () {},
|
||||
latestModelsCount: 0,
|
||||
pageSize: 20,
|
||||
latestModels: function () {
|
||||
return SearchCollection.prototype.latestModels.apply(this, arguments);
|
||||
}
|
||||
});
|
||||
this.collection = new MockCollection();
|
||||
this.resultsView = new SearchResultsView({ collection: this.collection });
|
||||
}
|
||||
|
||||
describe('CourseSearchResultsView', function () {
|
||||
beforeEach(function() {
|
||||
beforeEachHelper.call(this, CourseSearchResultsView);
|
||||
});
|
||||
it('shows loading message', showsLoadingMessage);
|
||||
it('shows error message', showsErrorMessage);
|
||||
it('returns to content', returnsToContent);
|
||||
it('shows a message when there are no results', showsNoResultsMessage);
|
||||
it('renders search results', rendersSearchResults);
|
||||
it('shows a link to load more results', showsMoreResultsLink);
|
||||
it('triggers an event for next page', triggersNextPageEvent);
|
||||
it('shows a spinner when loading more results', showsLoadMoreSpinner);
|
||||
});
|
||||
|
||||
it('shows loading message on search', showsLoadingMessage);
|
||||
it('performs search', performsSearch);
|
||||
it('shows an error message', showsErrorMessage);
|
||||
it('updates navigation history', updatesNavigationHistory);
|
||||
it('cancels search request', cancelsSearchRequest);
|
||||
it('clears results', clearsResults);
|
||||
it('loads next page', loadsNextPage);
|
||||
it('navigates to search', navigatesToSearch);
|
||||
it('returns to course list', function () {
|
||||
describe('DashSearchResultsView', function () {
|
||||
beforeEach(function() {
|
||||
beforeEachHelper.call(this, DashSearchResultsView);
|
||||
});
|
||||
it('shows loading message', showsLoadingMessage);
|
||||
it('shows error message', showsErrorMessage);
|
||||
it('returns to content', returnsToContent);
|
||||
it('shows a message when there are no results', showsNoResultsMessage);
|
||||
it('renders search results', rendersSearchResults);
|
||||
it('shows a link to load more results', showsMoreResultsLink);
|
||||
it('triggers an event for next page', triggersNextPageEvent);
|
||||
it('shows a spinner when loading more results', showsLoadMoreSpinner);
|
||||
it('returns back to courses', function () {
|
||||
var onReset = jasmine.createSpy('onReset');
|
||||
this.resultsView.on('reset', onReset);
|
||||
this.resultsView.render();
|
||||
expect(this.resultsView.$el.find('a.search-back-to-courses')).toExist();
|
||||
this.resultsView.$el.find('.search-back-to-courses').click();
|
||||
expect(onReset).toHaveBeenCalled();
|
||||
expect(this.resultsView.$contentElement).toBeVisible();
|
||||
expect(this.resultsView.$el).toBeHidden();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
describe('SearchApp', function () {
|
||||
|
||||
function showsLoadingMessage () {
|
||||
$('.search-field').val('search string');
|
||||
$('.search-button').trigger('click');
|
||||
expect(this.$contentElement).toBeHidden();
|
||||
expect(this.$searchResults).toBeVisible();
|
||||
expect(this.$searchResults).not.toBeEmpty();
|
||||
}
|
||||
|
||||
function performsSearch () {
|
||||
var requests = AjaxHelpers.requests(this);
|
||||
$('.search-field').val('search string');
|
||||
$('.search-button').trigger('click');
|
||||
@@ -741,15 +581,182 @@ define([
|
||||
}
|
||||
}]
|
||||
});
|
||||
expect($('.search-back-to-courses')).toExist();
|
||||
$('.search-back-to-courses').trigger('click');
|
||||
expect($('.search-info')).toExist();
|
||||
expect($('.search-result-list')).toBeVisible();
|
||||
expect(this.$searchResults.find('li').length).toEqual(1);
|
||||
}
|
||||
|
||||
function showsErrorMessage () {
|
||||
var requests = AjaxHelpers.requests(this);
|
||||
$('.search-field').val('search string');
|
||||
$('.search-button').trigger('click');
|
||||
AjaxHelpers.respondWithError(requests, 500, {});
|
||||
expect(this.$searchResults).toContainHtml('There was an error');
|
||||
}
|
||||
|
||||
function updatesNavigationHistory () {
|
||||
$('.search-field').val('edx');
|
||||
$('.search-button').trigger('click');
|
||||
expect(Backbone.history.navigate.calls[0].args).toContain('search/edx');
|
||||
$('.cancel-button').trigger('click');
|
||||
expect(Backbone.history.navigate.calls[1].args).toContain('');
|
||||
}
|
||||
|
||||
function cancelsSearchRequest () {
|
||||
var requests = AjaxHelpers.requests(this);
|
||||
// send search request to server
|
||||
$('.search-field').val('search string');
|
||||
$('.search-button').trigger('click');
|
||||
// cancel search
|
||||
$('.cancel-button').trigger('click');
|
||||
AjaxHelpers.respondWithJson(requests, {
|
||||
total: 1337,
|
||||
access_denied_count: 12,
|
||||
results: [{
|
||||
data: {
|
||||
location: ['section', 'subsection', 'unit'],
|
||||
url: '/some/url/to/content',
|
||||
content_type: 'text',
|
||||
excerpt: 'this is a short excerpt',
|
||||
course_name: ''
|
||||
}
|
||||
}]
|
||||
});
|
||||
// there should be no results
|
||||
expect(this.$contentElement).toBeVisible();
|
||||
expect(this.$searchResults).toBeHidden();
|
||||
expect(this.$searchResults).toBeEmpty();
|
||||
}
|
||||
|
||||
function clearsResults () {
|
||||
$('.cancel-button').trigger('click');
|
||||
expect(this.$contentElement).toBeVisible();
|
||||
expect(this.$searchResults).toBeHidden();
|
||||
}
|
||||
|
||||
function loadsNextPage () {
|
||||
var requests = AjaxHelpers.requests(this);
|
||||
var response = {
|
||||
total: 1337,
|
||||
access_denied_count: 12,
|
||||
results: [{
|
||||
data: {
|
||||
location: ['section', 'subsection', 'unit'],
|
||||
url: '/some/url/to/content',
|
||||
content_type: 'text',
|
||||
excerpt: 'this is a short excerpt',
|
||||
course_name: ''
|
||||
}
|
||||
}]
|
||||
};
|
||||
$('.search-field').val('query');
|
||||
$('.search-button').trigger('click');
|
||||
AjaxHelpers.respondWithJson(requests, response);
|
||||
expect(this.$searchResults.find('li').length).toEqual(1);
|
||||
expect($('.search-load-next')).toBeVisible();
|
||||
$('.search-load-next').trigger('click');
|
||||
var body = requests[1].requestBody;
|
||||
expect(body).toContain('search_string=query');
|
||||
expect(body).toContain('page_index=1');
|
||||
AjaxHelpers.respondWithJson(requests, response);
|
||||
expect(this.$searchResults.find('li').length).toEqual(2);
|
||||
}
|
||||
|
||||
function navigatesToSearch () {
|
||||
var requests = AjaxHelpers.requests(this);
|
||||
Backbone.history.loadUrl('search/query');
|
||||
expect(requests[0].requestBody).toContain('search_string=query');
|
||||
}
|
||||
|
||||
function loadTemplates () {
|
||||
TemplateHelpers.installTemplates([
|
||||
'templates/search/course_search_item',
|
||||
'templates/search/dashboard_search_item',
|
||||
'templates/search/search_loading',
|
||||
'templates/search/search_error',
|
||||
'templates/search/course_search_results',
|
||||
'templates/search/dashboard_search_results'
|
||||
]);
|
||||
}
|
||||
|
||||
describe('CourseSearchApp', function () {
|
||||
|
||||
beforeEach(function () {
|
||||
loadFixtures('js/fixtures/search/course_search_form.html');
|
||||
appendSetFixtures(
|
||||
'<section id="courseware-search-results"></section>' +
|
||||
'<section id="course-content"></section>'
|
||||
);
|
||||
loadTemplates.call(this);
|
||||
|
||||
var courseId = 'a/b/c';
|
||||
CourseSearchFactory(courseId);
|
||||
spyOn(Backbone.history, 'navigate');
|
||||
this.$contentElement = $('#course-content');
|
||||
this.$searchResults = $('#courseware-search-results');
|
||||
});
|
||||
|
||||
it('shows loading message on search', showsLoadingMessage);
|
||||
it('performs search', performsSearch);
|
||||
it('shows an error message', showsErrorMessage);
|
||||
it('updates navigation history', updatesNavigationHistory);
|
||||
it('cancels search request', cancelsSearchRequest);
|
||||
it('clears results', clearsResults);
|
||||
it('loads next page', loadsNextPage);
|
||||
it('navigates to search', navigatesToSearch);
|
||||
|
||||
});
|
||||
|
||||
describe('DashSearchApp', function () {
|
||||
|
||||
beforeEach(function () {
|
||||
loadFixtures('js/fixtures/search/dashboard_search_form.html');
|
||||
appendSetFixtures(
|
||||
'<section id="dashboard-search-results"></section>' +
|
||||
'<section id="my-courses"></section>'
|
||||
);
|
||||
loadTemplates.call(this);
|
||||
DashboardSearchFactory();
|
||||
|
||||
spyOn(Backbone.history, 'navigate');
|
||||
this.$contentElement = $('#my-courses');
|
||||
this.$searchResults = $('#dashboard-search-results');
|
||||
});
|
||||
|
||||
it('shows loading message on search', showsLoadingMessage);
|
||||
it('performs search', performsSearch);
|
||||
it('shows an error message', showsErrorMessage);
|
||||
it('updates navigation history', updatesNavigationHistory);
|
||||
it('cancels search request', cancelsSearchRequest);
|
||||
it('clears results', clearsResults);
|
||||
it('loads next page', loadsNextPage);
|
||||
it('navigates to search', navigatesToSearch);
|
||||
it('returns to course list', function () {
|
||||
var requests = AjaxHelpers.requests(this);
|
||||
$('.search-field').val('search string');
|
||||
$('.search-button').trigger('click');
|
||||
AjaxHelpers.respondWithJson(requests, {
|
||||
total: 1337,
|
||||
access_denied_count: 12,
|
||||
results: [{
|
||||
data: {
|
||||
location: ['section', 'subsection', 'unit'],
|
||||
url: '/some/url/to/content',
|
||||
content_type: 'text',
|
||||
excerpt: 'this is a short excerpt',
|
||||
course_name: ''
|
||||
}
|
||||
}]
|
||||
});
|
||||
expect($('.search-back-to-courses')).toExist();
|
||||
$('.search-back-to-courses').trigger('click');
|
||||
expect(this.$contentElement).toBeVisible();
|
||||
expect(this.$searchResults).toBeHidden();
|
||||
expect(this.$searchResults).toBeEmpty();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user