From ad16f9f968fd2a0d8a144759c88d8d45d60e38d2 Mon Sep 17 00:00:00 2001 From: cahrens <christina@edx.org> Date: Thu, 2 Jul 2015 09:20:27 -0400 Subject: [PATCH] Optimize search usages. --- lms/envs/common.py | 17 - lms/static/js/discovery/app.js | 71 -- lms/static/js/discovery/discovery_factory.js | 73 ++ lms/static/js/discovery/main.js | 22 - .../js/search/course/course_search_factory.js | 52 ++ lms/static/js/search/course/main.js | 22 - lms/static/js/search/course/search_app.js | 50 -- .../dashboard/dashboard_search_factory.js | 56 ++ lms/static/js/search/dashboard/main.js | 19 - lms/static/js/search/dashboard/search_app.js | 54 -- .../discovery/course_discovery_meanings.js | 19 - .../js/spec/discovery/discovery_spec.js | 835 +++++++++--------- lms/static/js/spec/main.js | 4 +- lms/static/js/spec/search/search_spec.js | 23 +- lms/static/lms/js/build.js | 5 +- lms/templates/courseware/courses.html | 24 +- lms/templates/courseware/courseware.html | 5 +- lms/templates/dashboard.html | 4 +- 18 files changed, 635 insertions(+), 720 deletions(-) delete mode 100644 lms/static/js/discovery/app.js create mode 100644 lms/static/js/discovery/discovery_factory.js delete mode 100644 lms/static/js/discovery/main.js create mode 100644 lms/static/js/search/course/course_search_factory.js delete mode 100644 lms/static/js/search/course/main.js delete mode 100644 lms/static/js/search/course/search_app.js create mode 100644 lms/static/js/search/dashboard/dashboard_search_factory.js delete mode 100644 lms/static/js/search/dashboard/main.js delete mode 100644 lms/static/js/search/dashboard/search_app.js delete mode 100644 lms/static/js/spec/discovery/course_discovery_meanings.js diff --git a/lms/envs/common.py b/lms/envs/common.py index 510b97eb263..0189b7dbc75 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -1212,8 +1212,6 @@ courseware_js = ( sorted(rooted_glob(PROJECT_ROOT / 'static', 'coffee/src/modules/**/*.js')) ) -courseware_search_js = ['js/search/course/main.js'] - # Before a student accesses courseware, we do not # need many of the JS dependencies. This includes @@ -1252,7 +1250,6 @@ base_application_js = [ dashboard_js = ( sorted(rooted_glob(PROJECT_ROOT / 'static', 'js/dashboard/**/*.js')) ) -dashboard_search_js = ['js/search/dashboard/main.js'] discussion_js = sorted(rooted_glob(COMMON_ROOT / 'static', 'coffee/src/discussion/**/*.js')) staff_grading_js = sorted(rooted_glob(PROJECT_ROOT / 'static', 'coffee/src/staff_grading/**/*.js')) open_ended_js = sorted(rooted_glob(PROJECT_ROOT / 'static', 'coffee/src/open_ended/**/*.js')) @@ -1338,8 +1335,6 @@ incourse_reverify_js = [ ccx_js = sorted(rooted_glob(PROJECT_ROOT / 'static', 'js/ccx/**/*.js')) -discovery_js = ['js/discovery/main.js'] - certificates_web_view_js = [ 'js/vendor/jquery.min.js', 'js/vendor/jquery.cookie.js', @@ -1504,10 +1499,6 @@ PIPELINE_JS = { 'source_filenames': courseware_js, 'output_filename': 'js/lms-courseware.js', }, - 'courseware_search': { - 'source_filenames': courseware_search_js, - 'output_filename': 'js/lms-courseware-search.js', - }, 'base_vendor': { 'source_filenames': base_vendor_js, 'output_filename': 'js/lms-base-vendor.js', @@ -1548,10 +1539,6 @@ PIPELINE_JS = { 'source_filenames': dashboard_js, 'output_filename': 'js/dashboard.js' }, - 'dashboard_search': { - 'source_filenames': dashboard_search_js, - 'output_filename': 'js/dashboard-search.js', - }, 'student_account': { 'source_filenames': student_account_js, 'output_filename': 'js/student_account.js' @@ -1576,10 +1563,6 @@ PIPELINE_JS = { 'source_filenames': ['js/footer-edx.js'], 'output_filename': 'js/footer-edx.js' }, - 'discovery': { - 'source_filenames': discovery_js, - 'output_filename': 'js/discovery.js' - }, 'certificates_wv': { 'source_filenames': certificates_web_view_js, 'output_filename': 'js/certificates/web_view.js' diff --git a/lms/static/js/discovery/app.js b/lms/static/js/discovery/app.js deleted file mode 100644 index 7e9a89ac59a..00000000000 --- a/lms/static/js/discovery/app.js +++ /dev/null @@ -1,71 +0,0 @@ -;(function (define) { - -define(['backbone', 'course_discovery_meanings'], function(Backbone, meanings) { - 'use strict'; - - return function (Collection, Form, ResultListView, FilterBarView, FacetsBarView, searchQuery) { - //facet types configuration - set default display names - var facetsTypes = meanings; - - var collection = new Collection([]); - var results = new ResultListView({ collection: collection }); - var dispatcher = _.clone(Backbone.Events); - var form = new Form(); - var filters = new FilterBarView(); - var facetsBarView = new FacetsBarView(facetsTypes); - - dispatcher.listenTo(form, 'search', function (query) { - form.showLoadingIndicator(); - filters.changeQueryFilter(query); - }); - - dispatcher.listenTo(filters, 'search', function (searchTerm, facets) { - collection.performSearch(searchTerm, facets); - form.showLoadingIndicator(); - }); - - dispatcher.listenTo(filters, 'clear', function () { - form.clearSearch(); - collection.performSearch(); - filters.hideClearAllButton(); - }); - - dispatcher.listenTo(results, 'next', function () { - collection.loadNextPage(); - form.showLoadingIndicator(); - }); - - dispatcher.listenTo(collection, 'search', function () { - if (collection.length > 0) { - form.showFoundMessage(collection.totalCount); - results.render(); - } - else { - form.showNotFoundMessage(collection.searchTerm); - } - facetsBarView.renderFacets(collection.facets); - form.hideLoadingIndicator(); - }); - - dispatcher.listenTo(collection, 'next', function () { - results.renderNext(); - form.hideLoadingIndicator(); - }); - - dispatcher.listenTo(collection, 'error', function () { - form.showErrorMessage(); - form.hideLoadingIndicator(); - }); - - dispatcher.listenTo(facetsBarView, 'addFilter', function (data) { - filters.addFilter(data); - }); - - // kick off search on page refresh - form.doSearch(searchQuery); - - }; - -}); - -})(define || RequireJS.define); diff --git a/lms/static/js/discovery/discovery_factory.js b/lms/static/js/discovery/discovery_factory.js new file mode 100644 index 00000000000..adfd8d08a6f --- /dev/null +++ b/lms/static/js/discovery/discovery_factory.js @@ -0,0 +1,73 @@ +;(function (define) { + 'use strict'; + + define(['backbone', 'js/discovery/collection', 'js/discovery/form', 'js/discovery/result_list_view', + 'js/discovery/filter_bar_view', 'js/discovery/search_facets_view'], + function(Backbone, Collection, Form, ResultListView, FilterBarView, FacetsBarView) { + + return function (meanings, searchQuery) { + //facet types configuration - set default display names + var facetsTypes = meanings; + + var collection = new Collection([]); + var results = new ResultListView({ collection: collection }); + var dispatcher = _.clone(Backbone.Events); + var form = new Form(); + var filters = new FilterBarView(); + var facetsBarView = new FacetsBarView(facetsTypes); + + dispatcher.listenTo(form, 'search', function (query) { + form.showLoadingIndicator(); + filters.changeQueryFilter(query); + }); + + dispatcher.listenTo(filters, 'search', function (searchTerm, facets) { + collection.performSearch(searchTerm, facets); + form.showLoadingIndicator(); + }); + + dispatcher.listenTo(filters, 'clear', function () { + form.clearSearch(); + collection.performSearch(); + filters.hideClearAllButton(); + }); + + dispatcher.listenTo(results, 'next', function () { + collection.loadNextPage(); + form.showLoadingIndicator(); + }); + + dispatcher.listenTo(collection, 'search', function () { + if (collection.length > 0) { + form.showFoundMessage(collection.totalCount); + results.render(); + } + else { + form.showNotFoundMessage(collection.searchTerm); + } + facetsBarView.renderFacets(collection.facets); + form.hideLoadingIndicator(); + }); + + dispatcher.listenTo(collection, 'next', function () { + results.renderNext(); + form.hideLoadingIndicator(); + }); + + dispatcher.listenTo(collection, 'error', function () { + form.showErrorMessage(); + form.hideLoadingIndicator(); + }); + + dispatcher.listenTo(facetsBarView, 'addFilter', function (data) { + filters.addFilter(data); + }); + + // kick off search on page refresh + form.doSearch(searchQuery); + + }; + + }); + +})(define || RequireJS.define); diff --git a/lms/static/js/discovery/main.js b/lms/static/js/discovery/main.js deleted file mode 100644 index 7325c215689..00000000000 --- a/lms/static/js/discovery/main.js +++ /dev/null @@ -1,22 +0,0 @@ -RequireJS.require([ - 'jquery', - 'backbone', - 'js/discovery/app', - 'js/discovery/collection', - 'js/discovery/form', - 'js/discovery/result_list_view', - 'js/discovery/filter_bar_view', - 'js/discovery/search_facets_view' -], function ($, Backbone, App, Collection, DiscoveryForm, ResultListView, FilterBarView, FacetsBarView) { - 'use strict'; - - var app = new App( - Collection, - DiscoveryForm, - ResultListView, - FilterBarView, - FacetsBarView, - getParameterByName('search_query') - ); - -}); diff --git a/lms/static/js/search/course/course_search_factory.js b/lms/static/js/search/course/course_search_factory.js new file mode 100644 index 00000000000..4f2a68d9167 --- /dev/null +++ b/lms/static/js/search/course/course_search_factory.js @@ -0,0 +1,52 @@ +;(function (define) { + 'use strict'; + + define(['backbone', 'js/search/base/routers/search_router', 'js/search/course/views/search_form', + 'js/search/base/collections/search_collection', 'js/search/course/views/search_results_view'], + function(Backbone, SearchRouter, CourseSearchForm, SearchCollection, SearchResultsView) { + + return function (courseId) { + + var router = new SearchRouter(); + var form = new CourseSearchForm(); + var collection = new SearchCollection([], { courseId: courseId }); + var results = new SearchResultsView({ collection: collection }); + var dispatcher = _.clone(Backbone.Events); + + dispatcher.listenTo(router, 'search', function (query) { + form.doSearch(query); + }); + + dispatcher.listenTo(form, 'search', function (query) { + results.showLoadingMessage(); + collection.performSearch(query); + router.navigate('search/' + query, { replace: true }); + }); + + dispatcher.listenTo(form, 'clear', function () { + collection.cancelSearch(); + results.clear(); + router.navigate(''); + }); + + dispatcher.listenTo(results, 'next', function () { + collection.loadNextPage(); + }); + + dispatcher.listenTo(collection, 'search', function () { + results.render(); + }); + + dispatcher.listenTo(collection, 'next', function () { + results.renderNext(); + }); + + dispatcher.listenTo(collection, 'error', function () { + results.showErrorMessage(); + }); + + }; + + }); + +})(define || RequireJS.define); diff --git a/lms/static/js/search/course/main.js b/lms/static/js/search/course/main.js deleted file mode 100644 index 9d8bd2759ca..00000000000 --- a/lms/static/js/search/course/main.js +++ /dev/null @@ -1,22 +0,0 @@ -RequireJS.require([ - 'jquery', - 'backbone', - 'js/search/course/search_app', - 'js/search/base/routers/search_router', - 'js/search/course/views/search_form', - 'js/search/base/collections/search_collection', - 'js/search/course/views/search_results_view' -], function ($, Backbone, SearchApp, SearchRouter, CourseSearchForm, SearchCollection, CourseSearchResultsView) { - 'use strict'; - - var courseId = $('#courseware-search-results').data('courseId'); - var app = new SearchApp( - courseId, - SearchRouter, - CourseSearchForm, - SearchCollection, - CourseSearchResultsView - ); - Backbone.history.start(); - -}); diff --git a/lms/static/js/search/course/search_app.js b/lms/static/js/search/course/search_app.js deleted file mode 100644 index 992c5fdf560..00000000000 --- a/lms/static/js/search/course/search_app.js +++ /dev/null @@ -1,50 +0,0 @@ -;(function (define) { - -define(['backbone'], function(Backbone) { - 'use strict'; - - return function (courseId, SearchRouter, SearchForm, SearchCollection, SearchListView) { - - var router = new SearchRouter(); - var form = new SearchForm(); - var collection = new SearchCollection([], { courseId: courseId }); - var results = new SearchListView({ collection: collection }); - var dispatcher = _.clone(Backbone.Events); - - dispatcher.listenTo(router, 'search', function (query) { - form.doSearch(query); - }); - - dispatcher.listenTo(form, 'search', function (query) { - results.showLoadingMessage(); - collection.performSearch(query); - router.navigate('search/' + query, { replace: true }); - }); - - dispatcher.listenTo(form, 'clear', function () { - collection.cancelSearch(); - results.clear(); - router.navigate(''); - }); - - dispatcher.listenTo(results, 'next', function () { - collection.loadNextPage(); - }); - - dispatcher.listenTo(collection, 'search', function () { - results.render(); - }); - - dispatcher.listenTo(collection, 'next', function () { - results.renderNext(); - }); - - dispatcher.listenTo(collection, 'error', function () { - results.showErrorMessage(); - }); - - }; - -}); - -})(define || RequireJS.define); diff --git a/lms/static/js/search/dashboard/dashboard_search_factory.js b/lms/static/js/search/dashboard/dashboard_search_factory.js new file mode 100644 index 00000000000..f44215c416c --- /dev/null +++ b/lms/static/js/search/dashboard/dashboard_search_factory.js @@ -0,0 +1,56 @@ +;(function (define) { + 'use strict'; + + define(['backbone', 'js/search/base/routers/search_router', 'js/search/dashboard/views/search_form', + 'js/search/base/collections/search_collection', 'js/search/dashboard/views/search_results_view'], + function(Backbone, SearchRouter, SearchForm, SearchCollection, SearchListView) { + + return function () { + + var router = new SearchRouter(); + var form = new SearchForm(); + var collection = new SearchCollection([]); + var results = new SearchListView({ collection: collection }); + var dispatcher = _.clone(Backbone.Events); + + dispatcher.listenTo(router, 'search', function (query) { + form.doSearch(query); + }); + + dispatcher.listenTo(form, 'search', function (query) { + results.showLoadingMessage(); + collection.performSearch(query); + router.navigate('search/' + query, { replace: true }); + }); + + dispatcher.listenTo(form, 'clear', function () { + collection.cancelSearch(); + results.clear(); + router.navigate(''); + }); + + dispatcher.listenTo(results, 'next', function () { + collection.loadNextPage(); + }); + + dispatcher.listenTo(results, 'reset', function () { + form.resetSearchForm(); + }); + + dispatcher.listenTo(collection, 'search', function () { + results.render(); + }); + + dispatcher.listenTo(collection, 'next', function () { + results.renderNext(); + }); + + dispatcher.listenTo(collection, 'error', function () { + results.showErrorMessage(); + }); + + }; + + }); + +})(define || RequireJS.define); diff --git a/lms/static/js/search/dashboard/main.js b/lms/static/js/search/dashboard/main.js deleted file mode 100644 index 0a6574caa04..00000000000 --- a/lms/static/js/search/dashboard/main.js +++ /dev/null @@ -1,19 +0,0 @@ -RequireJS.require([ - 'backbone', - 'js/search/dashboard/search_app', - 'js/search/base/routers/search_router', - 'js/search/dashboard/views/search_form', - 'js/search/base/collections/search_collection', - 'js/search/dashboard/views/search_results_view' -], function (Backbone, SearchApp, SearchRouter, DashSearchForm, SearchCollection, DashSearchResultsView) { - 'use strict'; - - var app = new SearchApp( - SearchRouter, - DashSearchForm, - SearchCollection, - DashSearchResultsView - ); - Backbone.history.start(); - -}); diff --git a/lms/static/js/search/dashboard/search_app.js b/lms/static/js/search/dashboard/search_app.js deleted file mode 100644 index d60d6047502..00000000000 --- a/lms/static/js/search/dashboard/search_app.js +++ /dev/null @@ -1,54 +0,0 @@ -;(function (define) { - -define(['backbone'], function(Backbone) { - 'use strict'; - - return function (SearchRouter, SearchForm, SearchCollection, SearchListView) { - - var router = new SearchRouter(); - var form = new SearchForm(); - var collection = new SearchCollection([]); - var results = new SearchListView({ collection: collection }); - var dispatcher = _.clone(Backbone.Events); - - dispatcher.listenTo(router, 'search', function (query) { - form.doSearch(query); - }); - - dispatcher.listenTo(form, 'search', function (query) { - results.showLoadingMessage(); - collection.performSearch(query); - router.navigate('search/' + query, { replace: true }); - }); - - dispatcher.listenTo(form, 'clear', function () { - collection.cancelSearch(); - results.clear(); - router.navigate(''); - }); - - dispatcher.listenTo(results, 'next', function () { - collection.loadNextPage(); - }); - - dispatcher.listenTo(results, 'reset', function () { - form.resetSearchForm(); - }); - - dispatcher.listenTo(collection, 'search', function () { - results.render(); - }); - - dispatcher.listenTo(collection, 'next', function () { - results.renderNext(); - }); - - dispatcher.listenTo(collection, 'error', function () { - results.showErrorMessage(); - }); - - }; - -}); - -})(define || RequireJS.define); diff --git a/lms/static/js/spec/discovery/course_discovery_meanings.js b/lms/static/js/spec/discovery/course_discovery_meanings.js deleted file mode 100644 index e468d553a77..00000000000 --- a/lms/static/js/spec/discovery/course_discovery_meanings.js +++ /dev/null @@ -1,19 +0,0 @@ -define({ - org: { - name: 'Organization', - terms: { - edX1: "edX_1" - } - }, - modes: { - name: 'Course Type', - terms: { - honor: 'Honor', - verified: 'Verified' - } - }, - language: { - en: 'English', - hr: 'Croatian' - } -}); diff --git a/lms/static/js/spec/discovery/discovery_spec.js b/lms/static/js/spec/discovery/discovery_spec.js index be06997d4cd..ccbe8b7ee61 100644 --- a/lms/static/js/spec/discovery/discovery_spec.js +++ b/lms/static/js/spec/discovery/discovery_spec.js @@ -4,7 +4,7 @@ define([ 'logger', 'common/js/spec_helpers/ajax_helpers', 'common/js/spec_helpers/template_helpers', - 'js/discovery/app', + 'js/discovery/discovery_factory', 'js/discovery/collection', 'js/discovery/form', 'js/discovery/result', @@ -14,16 +14,14 @@ define([ 'js/discovery/filters', 'js/discovery/filter_bar_view', 'js/discovery/filter_view', - 'js/discovery/search_facets_view', - 'js/discovery/facet_view', - 'js/discovery/facets_view' + 'js/discovery/search_facets_view' ], function( $, Backbone, Logger, AjaxHelpers, TemplateHelpers, - App, + DiscoveryFactory, Collection, DiscoveryForm, ResultItem, @@ -33,9 +31,7 @@ define([ FiltersCollection, FiltersBarView, FilterView, - SearchFacetView, - FacetView, - FacetsView + SearchFacetView ) { 'use strict'; @@ -113,126 +109,116 @@ define([ var SEARCH_FILTER = {"type": "search_string", "query": "search3"}; - describe('Collection', function () { + describe('Course Discovery', function () { - beforeEach(function () { - this.collection = new Collection(); + describe('Collection', function () { - this.onSearch = jasmine.createSpy('onSearch'); - this.collection.on('search', this.onSearch); + beforeEach(function () { + this.collection = new Collection(); - this.onNext = jasmine.createSpy('onNext'); - this.collection.on('next', this.onNext); + this.onSearch = jasmine.createSpy('onSearch'); + this.collection.on('search', this.onSearch); - this.onError = jasmine.createSpy('onError'); - this.collection.on('error', this.onError); - }); - - it('sends a request and parses the json result', function () { - var requests = AjaxHelpers.requests(this); - this.collection.performSearch('search string'); - AjaxHelpers.respondWithJson(requests, JSON_RESPONSE); - expect(this.onSearch).toHaveBeenCalled(); - expect(this.collection.totalCount).toEqual(365); - expect(this.collection.latestModels()[0].attributes).toEqual(JSON_RESPONSE.results[0].data); - expect(this.collection.page).toEqual(0); - }); + this.onNext = jasmine.createSpy('onNext'); + this.collection.on('next', this.onNext); - it('handles errors', function () { - var requests = AjaxHelpers.requests(this); - this.collection.performSearch('search string'); - AjaxHelpers.respondWithError(requests); - expect(this.onSearch).not.toHaveBeenCalled(); - expect(this.onError).toHaveBeenCalled(); - this.collection.loadNextPage(); - AjaxHelpers.respondWithError(requests); - 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 response = { total: 52, results: [] }; - this.collection.performSearch('search string'); - 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).toEqual({ - search_string : 'search string', - page_size : this.collection.pageSize, - page_index : 2 + this.onError = jasmine.createSpy('onError'); + this.collection.on('error', this.onError); }); - }); - 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('sends a request and parses the json result', function () { + var requests = AjaxHelpers.requests(this); + this.collection.performSearch('search string'); + AjaxHelpers.respondWithJson(requests, JSON_RESPONSE); + expect(this.onSearch).toHaveBeenCalled(); + expect(this.collection.totalCount).toEqual(365); + expect(this.collection.latestModels()[0].attributes).toEqual(JSON_RESPONSE.results[0].data); + expect(this.collection.page).toEqual(0); + }); - it('resets state when performing new search', function () { - this.collection.add(new ResultItem()); - expect(this.collection.length).toEqual(1); - this.collection.performSearch('search string'); - expect(this.collection.length).toEqual(0); - expect(this.collection.page).toEqual(0); - expect(this.collection.totalCount).toEqual(0); - expect(this.collection.latestModelsCount).toEqual(0); - }); + it('handles errors', function () { + var requests = AjaxHelpers.requests(this); + this.collection.performSearch('search string'); + AjaxHelpers.respondWithError(requests); + expect(this.onSearch).not.toHaveBeenCalled(); + expect(this.onError).toHaveBeenCalled(); + this.collection.loadNextPage(); + AjaxHelpers.respondWithError(requests); + 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 response = { total: 52, results: [] }; + this.collection.performSearch('search string'); + 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).toEqual({ + search_string : 'search string', + page_size : this.collection.pageSize, + page_index : 2 + }); + }); - describe('ResultItem', function () { + 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); + }); - beforeEach(function () { - this.result = new ResultItem(); - }); + it('resets state when performing new search', function () { + this.collection.add(new ResultItem()); + expect(this.collection.length).toEqual(1); + this.collection.performSearch('search string'); + expect(this.collection.length).toEqual(0); + expect(this.collection.page).toEqual(0); + expect(this.collection.totalCount).toEqual(0); + expect(this.collection.latestModelsCount).toEqual(0); + }); - it('has properties', function () { - expect(this.result.get('modes')).toBeDefined(); - expect(this.result.get('course')).toBeDefined(); - expect(this.result.get('enrollment_start')).toBeDefined(); - expect(this.result.get('number')).toBeDefined(); - expect(this.result.get('content')).toEqual({ - display_name: '', - number: '', - overview: '' - }); - expect(this.result.get('start')).toBeDefined(); - expect(this.result.get('image_url')).toBeDefined(); - expect(this.result.get('org')).toBeDefined(); - expect(this.result.get('id')).toBeDefined(); }); - }); + describe('ResultItem', function () { - describe('ResultItemView', function () { + beforeEach(function () { + this.result = new ResultItem(); + }); - beforeEach(function () { - TemplateHelpers.installTemplate('templates/discovery/result_item'); - this.item = new ResultItemView({ - model: new ResultItem(JSON_RESPONSE.results[0].data) + it('has properties', function () { + expect(this.result.get('modes')).toBeDefined(); + expect(this.result.get('course')).toBeDefined(); + expect(this.result.get('enrollment_start')).toBeDefined(); + expect(this.result.get('number')).toBeDefined(); + expect(this.result.get('content')).toEqual({ + display_name: '', + number: '', + overview: '' + }); + expect(this.result.get('start')).toBeDefined(); + expect(this.result.get('image_url')).toBeDefined(); + expect(this.result.get('org')).toBeDefined(); + expect(this.result.get('id')).toBeDefined(); }); - }); it('renders correctly', function () { var data = this.item.model.attributes; @@ -246,350 +232,383 @@ define([ expect(this.item.$el.find('.course-date')).toContainHtml('Jan 01, 1970'); }); - }); + describe('ResultItemView', function () { - describe('DiscoveryForm', function () { + beforeEach(function () { + TemplateHelpers.installTemplate('templates/discovery/result_item'); + this.item = new ResultItemView({ + model: new ResultItem(JSON_RESPONSE.results[0].data) + }); + }); - beforeEach(function () { - loadFixtures('js/fixtures/discovery.html'); - this.form = new DiscoveryForm(); - this.onSearch = jasmine.createSpy('onSearch'); - this.form.on('search', this.onSearch); - }); + it('renders correctly', function () { + var data = this.item.model.attributes; + this.item.render(); + expect(this.item.$el).toContainHtml(data.content.display_name); + expect(this.item.$el).toContain('a[href="/courses/' + data.course + '/info"]'); + expect(this.item.$el).toContain('img[src="' + data.image_url + '"]'); + expect(this.item.$el.find('.course-name')).toContainHtml(data.org); + expect(this.item.$el.find('.course-name')).toContainHtml(data.content.number); + expect(this.item.$el.find('.course-name')).toContainHtml(data.content.display_name); + expect(this.item.$el.find('.course-date')).toContainHtml('Jan 01, 1970'); + }); - it('trims input string', function () { - var term = ' search string '; - $('.discovery-input').val(term); - $('form').trigger('submit'); - expect(this.onSearch).toHaveBeenCalledWith($.trim(term)); }); - it('handles calls to doSearch', function () { - var term = ' search string '; - $('.discovery-input').val(term); - this.form.doSearch(term); - expect(this.onSearch).toHaveBeenCalledWith($.trim(term)); - expect($('.discovery-input').val()).toEqual(term); - expect($('#discovery-message')).toBeEmpty(); - }); - it('clears search', function () { - $('.discovery-input').val('somethig'); - this.form.clearSearch(); - expect($('.discovery-input').val()).toEqual(''); - }); + describe('DiscoveryForm', function () { - it('shows/hides loading indicator', function () { - this.form.showLoadingIndicator(); - expect($('#loading-indicator')).not.toHaveClass('hidden'); - this.form.hideLoadingIndicator(); - expect($('#loading-indicator')).toHaveClass('hidden'); - }); + beforeEach(function () { + loadFixtures('js/fixtures/discovery.html'); + this.form = new DiscoveryForm(); + this.onSearch = jasmine.createSpy('onSearch'); + this.form.on('search', this.onSearch); + }); - it('shows messages', function () { - this.form.showNotFoundMessage(); - expect($('#discovery-message')).not.toBeEmpty(); - this.form.showErrorMessage(); - expect($('#discovery-message')).not.toBeEmpty(); - }); + it('trims input string', function () { + var term = ' search string '; + $('.discovery-input').val(term); + $('form').trigger('submit'); + expect(this.onSearch).toHaveBeenCalledWith($.trim(term)); + }); - }); + it('handles calls to doSearch', function () { + var term = ' search string '; + $('.discovery-input').val(term); + this.form.doSearch(term); + expect(this.onSearch).toHaveBeenCalledWith($.trim(term)); + expect($('.discovery-input').val()).toEqual(term); + expect($('#discovery-message')).toBeEmpty(); + }); - describe('FilterBarView', function () { - beforeEach(function () { - loadFixtures('js/fixtures/discovery.html'); - TemplateHelpers.installTemplates( - ['templates/discovery/filter_bar', - 'templates/discovery/filter'] - ); - this.filterBar = new FiltersBarView(); - this.onClear = jasmine.createSpy('onClear'); - this.filterBar.on('clear', this.onClear); - }); + it('clears search', function () { + $('.discovery-input').val('somethig'); + this.form.clearSearch(); + expect($('.discovery-input').val()).toEqual(''); + }); - it('view searches for sent facet object', function () { - expect(this.filterBar.$el.length).toBe(1); - this.filterBar.addFilter(FACET_LIST[0]); - expect(this.filterBar.$el.find('#clear-all-filters')).toBeVisible(); - }); + it('shows/hides loading indicator', function () { + this.form.showLoadingIndicator(); + expect($('#loading-indicator')).not.toHaveClass('hidden'); + this.form.hideLoadingIndicator(); + expect($('#loading-indicator')).toHaveClass('hidden'); + }); - it('view searches for entered search string', function () { - spyOn(this.filterBar, 'addFilter').andCallThrough(); - expect(this.filterBar.$el.length).toBe(1); - this.filterBar.changeQueryFilter(SEARCH_FILTER.query); - expect(this.filterBar.$el.find('#clear-all-filters')).toBeVisible(); - expect(this.filterBar.addFilter).toHaveBeenCalledWith(SEARCH_FILTER); - }); + it('shows messages', function () { + this.form.showNotFoundMessage(); + expect($('#discovery-message')).not.toBeEmpty(); + this.form.showErrorMessage(); + expect($('#discovery-message')).not.toBeEmpty(); + }); - it('model cleans view on destruction correctly', function () { - this.filterBar.addFilter(SEARCH_FILTER); - var model = this.filterBar.collection.findWhere(SEARCH_FILTER); - expect(this.filterBar.$el.find('.active-filter').length).toBe(1); - model.cleanModelView(); - expect(this.filterBar.$el.find('.active-filter').length).toBe(0); }); - it('view removes all filters and hides bar if clear all', function () { - spyOn(this.filterBar, 'clearAll').andCallThrough(); - this.filterBar.delegateEvents(); - this.filterBar.addFilter(SEARCH_FILTER); - var clearAll = this.filterBar.$el.find('#clear-all-filters'); - expect(clearAll).toBeVisible(); - clearAll.trigger('click'); - expect(this.filterBar.clearAll).toHaveBeenCalled(); - expect(this.onClear).toHaveBeenCalled(); - }); + describe('FilterBarView', function () { + beforeEach(function () { + loadFixtures('js/fixtures/discovery.html'); + TemplateHelpers.installTemplates( + ['templates/discovery/filter_bar', + 'templates/discovery/filter'] + ); + this.filterBar = new FiltersBarView(); + this.onClear = jasmine.createSpy('onClear'); + this.filterBar.on('clear', this.onClear); + }); - it('view hides bar if all filters removed', function () { - spyOn(this.filterBar, 'clearFilter').andCallThrough(); - this.filterBar.delegateEvents(); - this.filterBar.addFilter(SEARCH_FILTER); - var clearAll = this.filterBar.$el.find('#clear-all-filters'); - expect(clearAll).toBeVisible(); - var filter = this.filterBar.$el.find('li .discovery-button'); - filter.trigger('click'); - expect(this.filterBar.clearFilter).toHaveBeenCalled(); - expect(this.onClear).toHaveBeenCalled(); - }); + it('view searches for sent facet object', function () { + expect(this.filterBar.$el.length).toBe(1); + this.filterBar.addFilter(FACET_LIST[0]); + expect(this.filterBar.$el.find('#clear-all-filters')).toBeVisible(); + }); - it('view changes query filter', function () { - this.filterBar.addFilter(SEARCH_FILTER); - var filter = $(this.filterBar.$el.find('li .discovery-button')[0]); - expect(filter.text().trim()).toBe(SEARCH_FILTER.query); - // Have to explicitly remove model because events not dispatched - var model = this.filterBar.collection.findWhere(SEARCH_FILTER); - model.cleanModelView(); - this.filterBar.changeQueryFilter(SEARCH_FILTER.query + '2'); - filter = $(this.filterBar.$el.find('li .discovery-button')[0]); - expect(filter.text().trim()).toBe(SEARCH_FILTER.query + '2'); - }); + it('view searches for entered search string', function () { + spyOn(this.filterBar, 'addFilter').andCallThrough(); + expect(this.filterBar.$el.length).toBe(1); + this.filterBar.changeQueryFilter(SEARCH_FILTER.query); + expect(this.filterBar.$el.find('#clear-all-filters')).toBeVisible(); + expect(this.filterBar.addFilter).toHaveBeenCalledWith(SEARCH_FILTER); + }); - it('view returns correct search term', function () { - this.filterBar.addFilter(SEARCH_FILTER); - expect(this.filterBar.getSearchTerm()).toBe(SEARCH_FILTER.query); - }); + it('model cleans view on destruction correctly', function () { + this.filterBar.addFilter(SEARCH_FILTER); + var model = this.filterBar.collection.findWhere(SEARCH_FILTER); + expect(this.filterBar.$el.find('.active-filter').length).toBe(1); + model.cleanModelView(); + expect(this.filterBar.$el.find('.active-filter').length).toBe(0); + }); - }); + it('view removes all filters and hides bar if clear all', function () { + spyOn(this.filterBar, 'clearAll').andCallThrough(); + this.filterBar.delegateEvents(); + this.filterBar.addFilter(SEARCH_FILTER); + var clearAll = this.filterBar.$el.find('#clear-all-filters'); + expect(clearAll).toBeVisible(); + clearAll.trigger('click'); + expect(this.filterBar.clearAll).toHaveBeenCalled(); + expect(this.onClear).toHaveBeenCalled(); + }); - describe('SearchFacetView', function () { - beforeEach(function () { - loadFixtures('js/fixtures/discovery.html'); - TemplateHelpers.installTemplates([ - 'templates/discovery/search_facet', - 'templates/discovery/search_facets_section', - 'templates/discovery/search_facets_list', - 'templates/discovery/more_less_links' - ]); - var facetsTypes = {org: 'Organization', modes: 'Course Type'}; - this.searchFacetView = new SearchFacetView(facetsTypes); - this.searchFacetView.renderFacets(JSON_RESPONSE.facets); - this.onAddFilter = jasmine.createSpy('onAddFilter'); - this.searchFacetView.on('addFilter', this.onAddFilter); - }); + it('view hides bar if all filters removed', function () { + spyOn(this.filterBar, 'clearFilter').andCallThrough(); + this.filterBar.delegateEvents(); + this.filterBar.addFilter(SEARCH_FILTER); + var clearAll = this.filterBar.$el.find('#clear-all-filters'); + expect(clearAll).toBeVisible(); + var filter = this.filterBar.$el.find('li .discovery-button'); + filter.trigger('click'); + expect(this.filterBar.clearFilter).toHaveBeenCalled(); + expect(this.onClear).toHaveBeenCalled(); + }); - it('view expands more content on show more click', function () { - var $showMore = this.searchFacetView.$el.find('.show-more'); - var $showLess = this.searchFacetView.$el.find('.show-less'); - var $ul = $showMore.parent('div').siblings('ul'); - expect($showMore).not.toHaveClass('hidden'); - expect($showLess).toHaveClass('hidden'); - expect($ul).toHaveClass('collapse'); - $showMore.trigger('click'); - expect($showMore).toHaveClass('hidden'); - expect($showLess).not.toHaveClass('hidden'); - expect($ul).not.toHaveClass('collapse'); - }); + it('view changes query filter', function () { + this.filterBar.addFilter(SEARCH_FILTER); + var filter = $(this.filterBar.$el.find('li .discovery-button')[0]); + expect(filter.text().trim()).toBe(SEARCH_FILTER.query); + // Have to explicitly remove model because events not dispatched + var model = this.filterBar.collection.findWhere(SEARCH_FILTER); + model.cleanModelView(); + this.filterBar.changeQueryFilter(SEARCH_FILTER.query + '2'); + filter = $(this.filterBar.$el.find('li .discovery-button')[0]); + expect(filter.text().trim()).toBe(SEARCH_FILTER.query + '2'); + }); - it('view collapses content on show less click', function () { - var $showMore = this.searchFacetView.$el.find('.show-more'); - var $showLess = this.searchFacetView.$el.find('.show-less'); - var $ul = $showMore.parent('div').siblings('ul'); - $showMore.trigger('click'); - expect($showMore).toHaveClass('hidden'); - expect($showLess).not.toHaveClass('hidden'); - expect($ul).not.toHaveClass('collapse'); - $showLess.trigger('click'); - expect($showMore).not.toHaveClass('hidden'); - expect($showLess).toHaveClass('hidden'); - expect($ul).toHaveClass('collapse'); - }); + it('view returns correct search term', function () { + this.filterBar.addFilter(SEARCH_FILTER); + expect(this.filterBar.getSearchTerm()).toBe(SEARCH_FILTER.query); + }); - it('view triggers addFilter event if facet is clicked', function () { - this.searchFacetView.delegateEvents(); - var $facetLink = this.searchFacetView.$el.find('li [data-value="edX1"]'); - var $facet = $facetLink.parent('li'); - $facet.trigger('click'); - expect(this.onAddFilter).toHaveBeenCalledWith( - { - type: $facet.data('facet'), - query: $facetLink.data('value'), - name : $facetLink.data('text') - } - ); }); - it('re-render facets on second click', function () { - // First search - this.searchFacetView.delegateEvents(); - this.searchFacetView.renderFacets(JSON_RESPONSE.facets); - expect(this.searchFacetView.facetViews.length).toBe(2); - // Setup spy - var customView = this.searchFacetView.facetViews[0]; - spyOn(customView, 'remove').andCallThrough(); - // Second search - this.searchFacetView.renderFacets(JSON_RESPONSE.facets); - expect(this.searchFacetView.facetViews.length).toBe(2); - expect(customView.remove).toHaveBeenCalled(); - }); + describe('SearchFacetView', function () { + beforeEach(function () { + loadFixtures('js/fixtures/discovery.html'); + TemplateHelpers.installTemplates([ + 'templates/discovery/search_facet', + 'templates/discovery/search_facets_section', + 'templates/discovery/search_facets_list', + 'templates/discovery/more_less_links' + ]); + var facetsTypes = {org: 'Organization', modes: 'Course Type'}; + this.searchFacetView = new SearchFacetView(facetsTypes); + this.searchFacetView.renderFacets(JSON_RESPONSE.facets); + this.onAddFilter = jasmine.createSpy('onAddFilter'); + this.searchFacetView.on('addFilter', this.onAddFilter); + }); - }); + it('view expands more content on show more click', function () { + var $showMore = this.searchFacetView.$el.find('.show-more'); + var $showLess = this.searchFacetView.$el.find('.show-less'); + var $ul = $showMore.parent('div').siblings('ul'); + expect($showMore).not.toHaveClass('hidden'); + expect($showLess).toHaveClass('hidden'); + expect($ul).toHaveClass('collapse'); + $showMore.trigger('click'); + expect($showMore).toHaveClass('hidden'); + expect($showLess).not.toHaveClass('hidden'); + expect($ul).not.toHaveClass('collapse'); + }); - describe('ResultListView', function () { + it('view collapses content on show less click', function () { + var $showMore = this.searchFacetView.$el.find('.show-more'); + var $showLess = this.searchFacetView.$el.find('.show-less'); + var $ul = $showMore.parent('div').siblings('ul'); + $showMore.trigger('click'); + expect($showMore).toHaveClass('hidden'); + expect($showLess).not.toHaveClass('hidden'); + expect($ul).not.toHaveClass('collapse'); + $showLess.trigger('click'); + expect($showMore).not.toHaveClass('hidden'); + expect($showLess).toHaveClass('hidden'); + expect($ul).toHaveClass('collapse'); + }); - beforeEach(function () { - jasmine.Clock.useMock(); - loadFixtures('js/fixtures/discovery.html'); - TemplateHelpers.installTemplate('templates/discovery/result_item'); - var collection = new Collection([JSON_RESPONSE.results[0].data]); - collection.latestModelsCount = 1; - this.view = new ResultListView({ collection: collection }); - }); + it('view triggers addFilter event if facet is clicked', function () { + this.searchFacetView.delegateEvents(); + var $facetLink = this.searchFacetView.$el.find('li [data-value="edX1"]'); + var $facet = $facetLink.parent('li'); + $facet.trigger('click'); + expect(this.onAddFilter).toHaveBeenCalledWith( + { + type: $facet.data('facet'), + query: $facetLink.data('value'), + name : $facetLink.data('text') + } + ); + }); - it('renders search results', function () { - this.view.render(); - expect($('.courses-listing article').length).toEqual(1); - expect($('.courses-listing .course-title')).toContainHtml('edX Demonstration Course'); - this.view.renderNext(); - expect($('.courses-listing article').length).toEqual(2); - }); + it('re-render facets on second click', function () { + // First search + this.searchFacetView.delegateEvents(); + this.searchFacetView.renderFacets(JSON_RESPONSE.facets); + expect(this.searchFacetView.facetViews.length).toBe(2); + // Setup spy + var customView = this.searchFacetView.facetViews[0]; + spyOn(customView, 'remove').andCallThrough(); + // Second search + this.searchFacetView.renderFacets(JSON_RESPONSE.facets); + expect(this.searchFacetView.facetViews.length).toBe(2); + expect(customView.remove).toHaveBeenCalled(); + }); - it('scrolling triggers an event for next page', function () { - this.onNext = jasmine.createSpy('onNext'); - this.view.on('next', this.onNext); - spyOn(this.view.collection, 'hasNextPage').andCallFake(function () { - return true; - }); - this.view.render(); - window.scroll(0, $(document).height()); - $(window).trigger('scroll'); - jasmine.Clock.tick(500); - expect(this.onNext).toHaveBeenCalled(); - - // should not be triggered again (while it is loading) - $(window).trigger('scroll'); - jasmine.Clock.tick(500); - expect(this.onNext.calls.length).toEqual(1); }); - }); + describe('ResultListView', function () { + beforeEach(function () { + jasmine.Clock.useMock(); + loadFixtures('js/fixtures/discovery.html'); + TemplateHelpers.installTemplate('templates/discovery/result_item'); + var collection = new Collection([JSON_RESPONSE.results[0].data]); + collection.latestModelsCount = 1; + this.view = new ResultListView({ collection: collection }); + }); - describe('Discovery App', function () { - - beforeEach(function () { - loadFixtures('js/fixtures/discovery.html'); - TemplateHelpers.installTemplates([ - 'templates/discovery/result_item', - 'templates/discovery/filter', - 'templates/discovery/filter_bar', - 'templates/discovery/search_facet', - 'templates/discovery/search_facets_section', - 'templates/discovery/search_facets_list', - 'templates/discovery/more_less_links' - ]); - - this.app = new App( - Collection, - DiscoveryForm, - ResultListView, - FiltersBarView, - SearchFacetView - ); - }); + it('renders search results', function () { + this.view.render(); + expect($('.courses-listing article').length).toEqual(1); + expect($('.courses-listing .course-title')).toContainHtml('edX Demonstration Course'); + this.view.renderNext(); + expect($('.courses-listing article').length).toEqual(2); + }); - it('performs search', function () { - var requests = AjaxHelpers.requests(this); - $('.discovery-input').val('test'); - $('.discovery-submit').trigger('click'); - AjaxHelpers.respondWithJson(requests, JSON_RESPONSE); - expect($('.courses-listing article').length).toEqual(1); - expect($('.courses-listing .course-title')).toContainHtml('edX Demonstration Course'); - expect($('.active-filter').length).toBe(1); - }); + it('scrolling triggers an event for next page', function () { + this.onNext = jasmine.createSpy('onNext'); + this.view.on('next', this.onNext); + spyOn(this.view.collection, 'hasNextPage').andCallFake(function () { + return true; + }); + this.view.render(); + window.scroll(0, $(document).height()); + $(window).trigger('scroll'); + jasmine.Clock.tick(500); + expect(this.onNext).toHaveBeenCalled(); + + // should not be triggered again (while it is loading) + $(window).trigger('scroll'); + jasmine.Clock.tick(500); + expect(this.onNext.calls.length).toEqual(1); + }); - it('loads more', function () { - var requests = AjaxHelpers.requests(this); - jasmine.Clock.useMock(); - $('.discovery-input').val('test'); - $('.discovery-submit').trigger('click'); - AjaxHelpers.respondWithJson(requests, JSON_RESPONSE); - expect($('.courses-listing article').length).toEqual(1); - expect($('.courses-listing .course-title')).toContainHtml('edX Demonstration Course'); - window.scroll(0, $(document).height()); - $(window).trigger('scroll'); - jasmine.Clock.tick(500); - AjaxHelpers.respondWithJson(requests, JSON_RESPONSE); - expect($('.courses-listing article').length).toEqual(2); }); - it('displays not found message', function () { - var requests = AjaxHelpers.requests(this); - $('.discovery-input').val('asdfasdf'); - $('.discovery-submit').trigger('click'); - AjaxHelpers.respondWithJson(requests, {}); - expect($('#discovery-message')).not.toBeEmpty(); - expect($('.courses-listing')).toBeEmpty(); - }); - it('displays error message', function () { - var requests = AjaxHelpers.requests(this); - $('.discovery-input').val('asdfasdf'); - $('.discovery-submit').trigger('click'); - AjaxHelpers.respondWithError(requests, 404); - expect($('#discovery-message')).not.toBeEmpty(); - expect($('.courses-listing')).toBeEmpty(); - }); + describe('Discovery App', function () { + + beforeEach(function () { + loadFixtures('js/fixtures/discovery.html'); + TemplateHelpers.installTemplates([ + 'templates/discovery/result_item', + 'templates/discovery/filter', + 'templates/discovery/filter_bar', + 'templates/discovery/search_facet', + 'templates/discovery/search_facets_section', + 'templates/discovery/search_facets_list', + 'templates/discovery/more_less_links' + ]); + + DiscoveryFactory( + { + org: { + name: 'Organization', + terms: { + edX1: "edX_1" + } + }, + modes: { + name: 'Course Type', + terms: { + honor: 'Honor', + verified: 'Verified' + } + }, + language: { + en: 'English', + hr: 'Croatian' + } + } + ); + }); - it('check filters and bar removed on clear all', function () { - var requests = AjaxHelpers.requests(this); - $('.discovery-input').val('test'); - $('.discovery-submit').trigger('click'); - AjaxHelpers.respondWithJson(requests, JSON_RESPONSE); - expect($('.active-filter').length).toBe(1); - expect($('#filter-bar')).not.toHaveClass('hidden'); - $('#clear-all-filters').trigger('click'); - expect($('.active-filter').length).toBe(0); - expect($('#filter-bar')).toHaveClass('hidden'); - }); + it('performs search', function () { + var requests = AjaxHelpers.requests(this); + $('.discovery-input').val('test'); + $('.discovery-submit').trigger('click'); + AjaxHelpers.respondWithJson(requests, JSON_RESPONSE); + expect($('.courses-listing article').length).toEqual(1); + expect($('.courses-listing .course-title')).toContainHtml('edX Demonstration Course'); + expect($('.active-filter').length).toBe(1); + }); - it('check filters and bar removed on last filter cleared', function () { - var requests = AjaxHelpers.requests(this); - $('.discovery-input').val('test'); - $('.discovery-submit').trigger('click'); - AjaxHelpers.respondWithJson(requests, JSON_RESPONSE); - expect($('.active-filter').length).toBe(1); - var $filter = $('.active-filter'); - $filter.find('.discovery-button').trigger('click'); - expect($('.active-filter').length).toBe(0); - }); + it('loads more', function () { + var requests = AjaxHelpers.requests(this); + jasmine.Clock.useMock(); + $('.discovery-input').val('test'); + $('.discovery-submit').trigger('click'); + AjaxHelpers.respondWithJson(requests, JSON_RESPONSE); + expect($('.courses-listing article').length).toEqual(1); + expect($('.courses-listing .course-title')).toContainHtml('edX Demonstration Course'); + window.scroll(0, $(document).height()); + $(window).trigger('scroll'); + jasmine.Clock.tick(500); + AjaxHelpers.respondWithJson(requests, JSON_RESPONSE); + expect($('.courses-listing article').length).toEqual(2); + }); - it('filter results by named facet', function () { - var requests = AjaxHelpers.requests(this); - $('.discovery-input').val('test'); - $('.discovery-submit').trigger('click'); - AjaxHelpers.respondWithJson(requests, JSON_RESPONSE); - expect($('.active-filter').length).toBe(1); - var $facetLink = $('.search-facets li [data-value="edX1"]'); - var $facet = $facetLink.parent('li'); - $facet.trigger('click'); - expect($('.active-filter').length).toBe(2); - expect($('.active-filter [data-value="edX1"]').length).toBe(1); - expect($('.active-filter [data-value="edX1"]').text().trim()).toBe("edX_1"); - }); + it('displays not found message', function () { + var requests = AjaxHelpers.requests(this); + $('.discovery-input').val('asdfasdf'); + $('.discovery-submit').trigger('click'); + AjaxHelpers.respondWithJson(requests, {}); + expect($('#discovery-message')).not.toBeEmpty(); + expect($('.courses-listing')).toBeEmpty(); + }); - }); + it('displays error message', function () { + var requests = AjaxHelpers.requests(this); + $('.discovery-input').val('asdfasdf'); + $('.discovery-submit').trigger('click'); + AjaxHelpers.respondWithError(requests, 404); + expect($('#discovery-message')).not.toBeEmpty(); + expect($('.courses-listing')).toBeEmpty(); + }); + it('check filters and bar removed on clear all', function () { + var requests = AjaxHelpers.requests(this); + $('.discovery-input').val('test'); + $('.discovery-submit').trigger('click'); + AjaxHelpers.respondWithJson(requests, JSON_RESPONSE); + expect($('.active-filter').length).toBe(1); + expect($('#filter-bar')).not.toHaveClass('hidden'); + $('#clear-all-filters').trigger('click'); + expect($('.active-filter').length).toBe(0); + expect($('#filter-bar')).toHaveClass('hidden'); + }); + it('check filters and bar removed on last filter cleared', function () { + var requests = AjaxHelpers.requests(this); + $('.discovery-input').val('test'); + $('.discovery-submit').trigger('click'); + AjaxHelpers.respondWithJson(requests, JSON_RESPONSE); + expect($('.active-filter').length).toBe(1); + var $filter = $('.active-filter'); + $filter.find('.discovery-button').trigger('click'); + expect($('.active-filter').length).toBe(0); + }); + it('filter results by named facet', function () { + var requests = AjaxHelpers.requests(this); + $('.discovery-input').val('test'); + $('.discovery-submit').trigger('click'); + AjaxHelpers.respondWithJson(requests, JSON_RESPONSE); + expect($('.active-filter').length).toBe(1); + var $facetLink = $('.search-facets li [data-value="edX1"]'); + var $facet = $facetLink.parent('li'); + $facet.trigger('click'); + expect($('.active-filter').length).toBe(2); + expect($('.active-filter [data-value="edX1"]').length).toBe(1); + expect($('.active-filter [data-value="edX1"]').text().trim()).toBe("edX_1"); + }); + }); + }); }); diff --git a/lms/static/js/spec/main.js b/lms/static/js/spec/main.js index 4ce54d5c53f..2532e53f9e8 100644 --- a/lms/static/js/spec/main.js +++ b/lms/static/js/spec/main.js @@ -84,9 +84,7 @@ 'js/ccx/schedule': 'js/ccx/schedule', // edxnotes - 'annotator_1.2.9': 'xmodule_js/common_static/js/vendor/edxnotes/annotator-full.min', - - 'course_discovery_meanings': 'js/spec/discovery/course_discovery_meanings' + 'annotator_1.2.9': 'xmodule_js/common_static/js/vendor/edxnotes/annotator-full.min' }, shim: { 'gettext': { diff --git a/lms/static/js/spec/search/search_spec.js b/lms/static/js/spec/search/search_spec.js index 411c7ba405e..6dce51fe99f 100644 --- a/lms/static/js/spec/search/search_spec.js +++ b/lms/static/js/spec/search/search_spec.js @@ -13,8 +13,8 @@ define([ 'js/search/dashboard/views/search_form', 'js/search/course/views/search_results_view', 'js/search/dashboard/views/search_results_view', - 'js/search/course/search_app', - 'js/search/dashboard/search_app' + 'js/search/course/course_search_factory', + 'js/search/dashboard/dashboard_search_factory' ], function( $, Sinon, @@ -30,8 +30,8 @@ define([ DashSearchForm, CourseSearchResultsView, DashSearchResultsView, - CourseSearchApp, - DashSearchApp + CourseSearchFactory, + DashboardSearchFactory ) { 'use strict'; @@ -681,13 +681,7 @@ define([ this.server = Sinon.fakeServer.create(); var courseId = 'a/b/c'; - this.app = new CourseSearchApp( - courseId, - SearchRouter, - CourseSearchForm, - SearchCollection, - CourseSearchResultsView - ); + CourseSearchFactory(courseId); spyOn(Backbone.history, 'navigate'); this.$contentElement = $('#course-content'); this.$searchResults = $('#courseware-search-results'); @@ -718,12 +712,7 @@ define([ loadTemplates.call(this); this.server = Sinon.fakeServer.create(); - this.app = new DashSearchApp( - SearchRouter, - DashSearchForm, - SearchCollection, - DashSearchResultsView - ); + DashboardSearchFactory(); spyOn(Backbone.history, 'navigate'); this.$contentElement = $('#my-courses'); diff --git a/lms/static/lms/js/build.js b/lms/static/lms/js/build.js index 75b7be52be9..f02c4e070ca 100644 --- a/lms/static/lms/js/build.js +++ b/lms/static/lms/js/build.js @@ -18,7 +18,10 @@ * done. */ modules: getModulesList([ + 'js/discovery/discovery_factory', 'js/groups/views/cohorts_dashboard_factory', + 'js/search/course/course_search_factory', + 'js/search/dashboard/dashboard_search_factory', 'js/student_account/views/account_settings_factory', 'js/student_account/views/finish_auth_factory', 'js/student_profile/views/learner_profile_factory', @@ -57,7 +60,7 @@ 'underscore': 'empty:', 'logger': 'empty:', 'utility': 'empty:', - 'URI': 'empty:' + 'URI': 'empty:', }, /** diff --git a/lms/templates/courseware/courses.html b/lms/templates/courseware/courses.html index 671fe360d92..171a4edd646 100644 --- a/lms/templates/courseware/courses.html +++ b/lms/templates/courseware/courses.html @@ -2,33 +2,27 @@ import json from django.utils.translation import ugettext as _ from microsite_configuration import microsite + from openedx.core.lib.json_utils import EscapedEdxJSONEncoder %> <%inherit file="../main.html" /> <%namespace name='static' file='../static_content.html'/> +% if settings.FEATURES.get('ENABLE_COURSE_DISCOVERY'): <%block name="header_extras"> - % if settings.FEATURES.get('ENABLE_COURSE_DISCOVERY'): % for template_name in ["result_item", "filter_bar", "filter", "search_facets_list", "search_facets_section", "search_facet", "more_less_links"]: <script type="text/template" id="${template_name}-tpl"> <%static:include path="discovery/${template_name}.underscore" /> </script> % endfor - <script type="text/javascript">;(function (define) {{ - define('course_discovery_meanings', function() {{ - 'use strict'; - return ${json.dumps(course_discovery_meanings)}; - }}); - }})(define || RequireJS.define); - </script> - % endif -</%block> - -<%block name="js_extra"> - % if settings.FEATURES.get('ENABLE_COURSE_DISCOVERY'): - <%static:js group='discovery'/> - % endif + <%static:require_module module_name="js/discovery/discovery_factory" class_name="DiscoveryFactory"> + DiscoveryFactory( + ${json.dumps(course_discovery_meanings, cls=EscapedEdxJSONEncoder)}, + getParameterByName('search_query') + ); + </%static:require_module> </%block> +% endif <%block name="pagetitle">${_("Courses")}</%block> <% diff --git a/lms/templates/courseware/courseware.html b/lms/templates/courseware/courseware.html index 7e3e3862c0e..b4c8e5d1653 100644 --- a/lms/templates/courseware/courseware.html +++ b/lms/templates/courseware/courseware.html @@ -66,7 +66,10 @@ ${page_title_breadcrumbs(course_name())} <%static:js group='courseware'/> <%static:js group='discussion'/> % if settings.FEATURES.get('ENABLE_COURSEWARE_SEARCH'): - <%static:js group='courseware_search'/> + <%static:require_module module_name="js/search/course/course_search_factory" class_name="CourseSearchFactory"> + var courseId = $('#courseware-search-results').data('courseId'); + CourseSearchFactory(courseId); + </%static:require_module> % endif <%include file="../discussion/_js_body_dependencies.html" /> diff --git a/lms/templates/dashboard.html b/lms/templates/dashboard.html index 5d1ffc4c887..07181b65d57 100644 --- a/lms/templates/dashboard.html +++ b/lms/templates/dashboard.html @@ -45,7 +45,9 @@ from django.core.urlresolvers import reverse }); </script> % if settings.FEATURES.get('ENABLE_DASHBOARD_SEARCH'): - <%static:js group='dashboard_search'/> + <%static:require_module module_name="js/search/dashboard/dashboard_search_factory" class_name="DashboardSearchFactory"> + DashboardSearchFactory(); + </%static:require_module> % endif </%block> -- GitLab