[Search] use service for filters, add spec
Add a spec for the SearchController, and use the SearchService to execute filters by supplying a filterPredicate.
This commit is contained in:
@@ -4,12 +4,12 @@
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* 'License'); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* distributed under the License is distributed on an 'AS IS' BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
@@ -24,185 +24,215 @@
|
||||
/**
|
||||
* SearchSpec. Created by shale on 07/31/2015.
|
||||
*/
|
||||
define(
|
||||
["../../src/controllers/SearchController"],
|
||||
function (SearchController) {
|
||||
"use strict";
|
||||
define([
|
||||
'../../src/controllers/SearchController'
|
||||
], function (
|
||||
SearchController
|
||||
) {
|
||||
'use strict';
|
||||
|
||||
// These should be the same as the ones on the top of the search controller
|
||||
var INITIAL_LOAD_NUMBER = 20,
|
||||
LOAD_INCREMENT = 20;
|
||||
|
||||
describe("The search controller", function () {
|
||||
var mockScope,
|
||||
mockSearchService,
|
||||
mockPromise,
|
||||
mockSearchResult,
|
||||
mockDomainObject,
|
||||
mockTypes,
|
||||
controller;
|
||||
describe('The search controller', function () {
|
||||
var mockScope,
|
||||
mockSearchService,
|
||||
mockPromise,
|
||||
mockSearchResult,
|
||||
mockDomainObject,
|
||||
mockTypes,
|
||||
controller;
|
||||
|
||||
function bigArray(size) {
|
||||
var array = [],
|
||||
i;
|
||||
for (i = 0; i < size; i += 1) {
|
||||
array.push(mockSearchResult);
|
||||
}
|
||||
return array;
|
||||
function bigArray(size) {
|
||||
var array = [],
|
||||
i;
|
||||
for (i = 0; i < size; i += 1) {
|
||||
array.push(mockSearchResult);
|
||||
}
|
||||
|
||||
|
||||
beforeEach(function () {
|
||||
mockScope = jasmine.createSpyObj(
|
||||
"$scope",
|
||||
[ "$watch" ]
|
||||
);
|
||||
mockScope.ngModel = {};
|
||||
mockScope.ngModel.input = "test input";
|
||||
mockScope.ngModel.checked = {};
|
||||
mockScope.ngModel.checked['mock.type'] = true;
|
||||
return array;
|
||||
}
|
||||
|
||||
|
||||
beforeEach(function () {
|
||||
mockScope = jasmine.createSpyObj(
|
||||
'$scope',
|
||||
[ '$watch' ]
|
||||
);
|
||||
mockScope.ngModel = {};
|
||||
mockScope.ngModel.input = 'test input';
|
||||
mockScope.ngModel.checked = {};
|
||||
mockScope.ngModel.checked['mock.type'] = true;
|
||||
mockScope.ngModel.checkAll = true;
|
||||
|
||||
mockSearchService = jasmine.createSpyObj(
|
||||
'searchService',
|
||||
[ 'query' ]
|
||||
);
|
||||
mockPromise = jasmine.createSpyObj(
|
||||
'promise',
|
||||
[ 'then' ]
|
||||
);
|
||||
mockSearchService.query.andReturn(mockPromise);
|
||||
|
||||
mockTypes = [{key: 'mock.type', name: 'Mock Type', glyph: '?'}];
|
||||
|
||||
mockSearchResult = jasmine.createSpyObj(
|
||||
'searchResult',
|
||||
[ '' ]
|
||||
);
|
||||
mockDomainObject = jasmine.createSpyObj(
|
||||
'domainObject',
|
||||
[ 'getModel' ]
|
||||
);
|
||||
mockSearchResult.object = mockDomainObject;
|
||||
mockDomainObject.getModel.andReturn({name: 'Mock Object', type: 'mock.type'});
|
||||
|
||||
controller = new SearchController(mockScope, mockSearchService, mockTypes);
|
||||
controller.search();
|
||||
});
|
||||
|
||||
it('has a default number of results per page', function () {
|
||||
expect(controller.RESULTS_PER_PAGE).toBe(20);
|
||||
});
|
||||
|
||||
it('sends queries to the search service', function () {
|
||||
expect(mockSearchService.query).toHaveBeenCalledWith(
|
||||
'test input',
|
||||
controller.RESULTS_PER_PAGE,
|
||||
jasmine.any(Function)
|
||||
);
|
||||
});
|
||||
|
||||
describe('filter query function', function () {
|
||||
it('returns true when all types allowed', function () {
|
||||
mockScope.ngModel.checkAll = true;
|
||||
|
||||
mockSearchService = jasmine.createSpyObj(
|
||||
"searchService",
|
||||
[ "query" ]
|
||||
);
|
||||
mockPromise = jasmine.createSpyObj(
|
||||
"promise",
|
||||
[ "then" ]
|
||||
);
|
||||
mockSearchService.query.andReturn(mockPromise);
|
||||
|
||||
mockTypes = [{key: 'mock.type', name: 'Mock Type', glyph: '?'}];
|
||||
|
||||
mockSearchResult = jasmine.createSpyObj(
|
||||
"searchResult",
|
||||
[ "" ]
|
||||
);
|
||||
mockDomainObject = jasmine.createSpyObj(
|
||||
"domainObject",
|
||||
[ "getModel" ]
|
||||
);
|
||||
mockSearchResult.object = mockDomainObject;
|
||||
mockDomainObject.getModel.andReturn({name: 'Mock Object', type: 'mock.type'});
|
||||
|
||||
controller = new SearchController(mockScope, mockSearchService, mockTypes);
|
||||
controller.search();
|
||||
});
|
||||
|
||||
it("sends queries to the search service", function () {
|
||||
expect(mockSearchService.query).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("populates the results with results from the search service", function () {
|
||||
expect(mockPromise.then).toHaveBeenCalledWith(jasmine.any(Function));
|
||||
mockPromise.then.mostRecentCall.args[0]({hits: []});
|
||||
|
||||
expect(mockScope.results).toBeDefined();
|
||||
});
|
||||
|
||||
it("is loading until the service's promise fufills", function () {
|
||||
// Send query
|
||||
controller.search();
|
||||
expect(mockScope.loading).toBeTruthy();
|
||||
|
||||
// Then resolve the promises
|
||||
mockPromise.then.mostRecentCall.args[0]({hits: []});
|
||||
expect(mockScope.loading).toBeFalsy();
|
||||
controller.onFilterChange();
|
||||
var filterFn = mockSearchService.query.mostRecentCall.args[2];
|
||||
expect(filterFn('askbfa')).toBe(true);
|
||||
});
|
||||
|
||||
|
||||
it("displays only some results when there are many", function () {
|
||||
expect(mockPromise.then).toHaveBeenCalledWith(jasmine.any(Function));
|
||||
mockPromise.then.mostRecentCall.args[0]({hits: bigArray(100)});
|
||||
|
||||
expect(mockScope.results).toBeDefined();
|
||||
expect(mockScope.results.length).toBeLessThan(100);
|
||||
});
|
||||
|
||||
it("detects when there are more results", function () {
|
||||
it('returns true only for matching checked types', function () {
|
||||
mockScope.ngModel.checkAll = false;
|
||||
|
||||
expect(mockPromise.then).toHaveBeenCalledWith(jasmine.any(Function));
|
||||
mockPromise.then.mostRecentCall.args[0]({
|
||||
hits: bigArray(INITIAL_LOAD_NUMBER + 5),
|
||||
total: INITIAL_LOAD_NUMBER + 5
|
||||
});
|
||||
// bigArray gives searchResults of type 'mock.type'
|
||||
mockScope.ngModel.checked['mock.type'] = false;
|
||||
mockScope.ngModel.checked['mock.type.2'] = true;
|
||||
|
||||
expect(controller.areMore()).toBeFalsy();
|
||||
|
||||
mockScope.ngModel.checked['mock.type'] = true;
|
||||
|
||||
expect(controller.areMore()).toBeTruthy();
|
||||
});
|
||||
|
||||
it("can load more results", function () {
|
||||
var oldSize;
|
||||
|
||||
expect(mockPromise.then).toHaveBeenCalled();
|
||||
mockPromise.then.mostRecentCall.args[0]({
|
||||
hits: bigArray(INITIAL_LOAD_NUMBER + LOAD_INCREMENT + 1),
|
||||
total: INITIAL_LOAD_NUMBER + LOAD_INCREMENT + 1
|
||||
});
|
||||
// These hits and total lengths are the case where the controller
|
||||
// DOES NOT have to re-search to load more results
|
||||
oldSize = mockScope.results.length;
|
||||
|
||||
expect(controller.areMore()).toBeTruthy();
|
||||
|
||||
controller.loadMore();
|
||||
expect(mockScope.results.length).toBeGreaterThan(oldSize);
|
||||
});
|
||||
|
||||
it("can re-search to load more results", function () {
|
||||
var oldSize,
|
||||
oldCallCount;
|
||||
|
||||
expect(mockPromise.then).toHaveBeenCalled();
|
||||
mockPromise.then.mostRecentCall.args[0]({
|
||||
hits: bigArray(INITIAL_LOAD_NUMBER + LOAD_INCREMENT - 1),
|
||||
total: INITIAL_LOAD_NUMBER + LOAD_INCREMENT + 1
|
||||
});
|
||||
// These hits and total lengths are the case where the controller
|
||||
// DOES have to re-search to load more results
|
||||
oldSize = mockScope.results.length;
|
||||
oldCallCount = mockPromise.then.callCount;
|
||||
expect(controller.areMore()).toBeTruthy();
|
||||
|
||||
controller.loadMore();
|
||||
expect(mockPromise.then).toHaveBeenCalled();
|
||||
// Make sure that a NEW call to search has been made
|
||||
expect(oldCallCount).toBeLessThan(mockPromise.then.callCount);
|
||||
mockPromise.then.mostRecentCall.args[0]({
|
||||
hits: bigArray(INITIAL_LOAD_NUMBER + LOAD_INCREMENT + 1),
|
||||
total: INITIAL_LOAD_NUMBER + LOAD_INCREMENT + 1
|
||||
});
|
||||
expect(mockScope.results.length).toBeGreaterThan(oldSize);
|
||||
});
|
||||
|
||||
it("sets the ngModel.search flag", function () {
|
||||
// Flag should be true with nonempty input
|
||||
expect(mockScope.ngModel.search).toEqual(true);
|
||||
|
||||
// Flag should be flase with empty input
|
||||
mockScope.ngModel.input = "";
|
||||
controller.search();
|
||||
mockPromise.then.mostRecentCall.args[0]({hits: [], total: 0});
|
||||
expect(mockScope.ngModel.search).toEqual(false);
|
||||
|
||||
// Both the empty string and undefined should be 'empty input'
|
||||
mockScope.ngModel.input = undefined;
|
||||
controller.search();
|
||||
mockPromise.then.mostRecentCall.args[0]({hits: [], total: 0});
|
||||
expect(mockScope.ngModel.search).toEqual(false);
|
||||
});
|
||||
|
||||
it("has a default results list to filter from", function () {
|
||||
expect(mockScope.ngModel.filter()).toBeDefined();
|
||||
controller.onFilterChange();
|
||||
var filterFn = mockSearchService.query.mostRecentCall.args[2];
|
||||
expect(filterFn({type: 'mock.type'})).toBe(true);
|
||||
expect(filterFn({type: 'other.type'})).toBe(false);
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
it('populates the results with results from the search service', function () {
|
||||
expect(mockPromise.then).toHaveBeenCalledWith(jasmine.any(Function));
|
||||
mockPromise.then.mostRecentCall.args[0]({hits: ['a']});
|
||||
|
||||
expect(mockScope.results.length).toBe(1);
|
||||
expect(mockScope.results).toContain('a');
|
||||
});
|
||||
|
||||
it('is loading until the service\'s promise fufills', function () {
|
||||
expect(mockScope.loading).toBeTruthy();
|
||||
|
||||
// Then resolve the promises
|
||||
mockPromise.then.mostRecentCall.args[0]({hits: []});
|
||||
expect(mockScope.loading).toBeFalsy();
|
||||
});
|
||||
|
||||
|
||||
xit('displays only some results when there are many', function () {
|
||||
expect(mockPromise.then).toHaveBeenCalledWith(jasmine.any(Function));
|
||||
mockPromise.then.mostRecentCall.args[0]({hits: bigArray(100)});
|
||||
|
||||
expect(mockScope.results).toBeDefined();
|
||||
expect(mockScope.results.length).toBeLessThan(100);
|
||||
});
|
||||
|
||||
it('detects when there are more results', function () {
|
||||
mockPromise.then.mostRecentCall.args[0]({
|
||||
hits: bigArray(controller.RESULTS_PER_PAGE),
|
||||
total: controller.RESULTS_PER_PAGE + 5
|
||||
});
|
||||
|
||||
expect(mockScope.results.length).toBe(controller.RESULTS_PER_PAGE);
|
||||
expect(controller.areMore()).toBeTruthy;
|
||||
|
||||
controller.loadMore();
|
||||
|
||||
expect(mockSearchService.query).toHaveBeenCalledWith(
|
||||
'test input',
|
||||
controller.RESULTS_PER_PAGE * 2,
|
||||
jasmine.any(Function)
|
||||
);
|
||||
|
||||
mockPromise.then.mostRecentCall.args[0]({
|
||||
hits: bigArray(controller.RESULTS_PER_PAGE + 5),
|
||||
total: controller.RESULTS_PER_PAGE + 5
|
||||
});
|
||||
|
||||
expect(mockScope.results.length)
|
||||
.toBe(controller.RESULTS_PER_PAGE + 5);
|
||||
|
||||
expect(controller.areMore()).toBe(false);
|
||||
});
|
||||
|
||||
xit('can load more results', function () {
|
||||
var oldSize;
|
||||
|
||||
expect(mockPromise.then).toHaveBeenCalled();
|
||||
mockPromise.then.mostRecentCall.args[0]({
|
||||
hits: bigArray(INITIAL_LOAD_NUMBER + LOAD_INCREMENT + 1),
|
||||
total: INITIAL_LOAD_NUMBER + LOAD_INCREMENT + 1
|
||||
});
|
||||
// These hits and total lengths are the case where the controller
|
||||
// DOES NOT have to re-search to load more results
|
||||
oldSize = mockScope.results.length;
|
||||
|
||||
expect(controller.areMore()).toBeTruthy();
|
||||
|
||||
controller.loadMore();
|
||||
expect(mockScope.results.length).toBeGreaterThan(oldSize);
|
||||
});
|
||||
|
||||
xit('can re-search to load more results', function () {
|
||||
var oldSize,
|
||||
oldCallCount;
|
||||
|
||||
expect(mockPromise.then).toHaveBeenCalled();
|
||||
mockPromise.then.mostRecentCall.args[0]({
|
||||
hits: bigArray(INITIAL_LOAD_NUMBER + LOAD_INCREMENT - 1),
|
||||
total: INITIAL_LOAD_NUMBER + LOAD_INCREMENT + 1
|
||||
});
|
||||
// These hits and total lengths are the case where the controller
|
||||
// DOES have to re-search to load more results
|
||||
oldSize = mockScope.results.length;
|
||||
oldCallCount = mockPromise.then.callCount;
|
||||
expect(controller.areMore()).toBeTruthy();
|
||||
|
||||
controller.loadMore();
|
||||
expect(mockPromise.then).toHaveBeenCalled();
|
||||
// Make sure that a NEW call to search has been made
|
||||
expect(oldCallCount).toBeLessThan(mockPromise.then.callCount);
|
||||
mockPromise.then.mostRecentCall.args[0]({
|
||||
hits: bigArray(INITIAL_LOAD_NUMBER + LOAD_INCREMENT + 1),
|
||||
total: INITIAL_LOAD_NUMBER + LOAD_INCREMENT + 1
|
||||
});
|
||||
expect(mockScope.results.length).toBeGreaterThan(oldSize);
|
||||
});
|
||||
|
||||
it('sets the ngModel.search flag', function () {
|
||||
// Flag should be true with nonempty input
|
||||
expect(mockScope.ngModel.search).toEqual(true);
|
||||
|
||||
// Flag should be flase with empty input
|
||||
mockScope.ngModel.input = '';
|
||||
controller.search();
|
||||
mockPromise.then.mostRecentCall.args[0]({hits: [], total: 0});
|
||||
expect(mockScope.ngModel.search).toEqual(false);
|
||||
|
||||
// Both the empty string and undefined should be 'empty input'
|
||||
mockScope.ngModel.input = undefined;
|
||||
controller.search();
|
||||
mockPromise.then.mostRecentCall.args[0]({hits: [], total: 0});
|
||||
expect(mockScope.ngModel.search).toEqual(false);
|
||||
});
|
||||
|
||||
it('attaches a filter function to scope', function () {
|
||||
expect(mockScope.ngModel.filter).toEqual(jasmine.any(Function));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user