6bada521 by Adam Heath

Reorganized the spec layout, now they are stored alongside the files

they test.  Facets is close to full coverage.
1 parent e3b61d72
...@@ -60,13 +60,29 @@ module.exports = function(grunt) { ...@@ -60,13 +60,29 @@ module.exports = function(grunt) {
60 60
61 var _ = require('lodash'); 61 var _ = require('lodash');
62 62
63 var jasmineRequirejsTemplateOptions = function(withInstanbul) { 63 function genJasmineConfig(withCoverage, options) {
64 /* global requirejs */ 64 var template, templateOptions;
65 var callback; 65 var src = [
66 if (withInstanbul) { 66 'src/scripts/{,**/}*.js',
67 callback = function() { 67 '!src/scripts/main.js',
68 ];
69 var specs = [
70 'src/scripts/**/*.spec.js',
71 ];
72 var template = require('grunt-template-jasmine-requirejs');
73 var templateOptions = {
74 requireConfigFile: 'src/scripts/config.js',
75 requireConfig: {
76 baseUrl: 'src/scripts',
77 },
78 };
79
80 if (withCoverage) {
81 /* global requirejs */
82 templateOptions.requireConfig.callback = function() {
68 var oldLoad = requirejs.load; 83 var oldLoad = requirejs.load;
69 requirejs.load = function (context, moduleName, url) { 84 requirejs.load = function (context, moduleName, url) {
85 var origUrl = url;
70 //console.log('context=' + JSON.stringify(arguments), 'moduleName=' + moduleName, 'url=' + url); 86 //console.log('context=' + JSON.stringify(arguments), 'moduleName=' + moduleName, 'url=' + url);
71 var parts = url.split('/'); 87 var parts = url.split('/');
72 for (var i = 0; i < parts.length; ) { 88 for (var i = 0; i < parts.length; ) {
...@@ -87,58 +103,55 @@ module.exports = function(grunt) { ...@@ -87,58 +103,55 @@ module.exports = function(grunt) {
87 } 103 }
88 } 104 }
89 url = parts.join('/'); 105 url = parts.join('/');
90 if (url.indexOf('src/scripts/') === 0) { 106 if (url.match(/^src\/scripts\/(.*?\/)?[^\/]+\.spec\.js$/)) {
107 url = './.grunt/grunt-contrib-jasmine/' + url;
108 } else if (url.match(/^src\/scripts\/(.*?\/)?[^\/]+\.js$/)) {
91 url = './.grunt/grunt-contrib-jasmine/' + url; 109 url = './.grunt/grunt-contrib-jasmine/' + url;
92 } 110 }
93 if (url.indexOf('test/specs/') === 0) { 111 if (url.indexOf('test/specs/') === 0) {
94 url = './.grunt/grunt-contrib-jasmine/' + url; 112 url = './.grunt/grunt-contrib-jasmine/' + url;
95 } 113 }
96 //console.log('url=' + url); 114 //console.log('url[' + origUrl + ']=' + url);
97 return oldLoad.apply(this, [context, moduleName, url]); 115 return oldLoad.apply(this, [context, moduleName, url]);
98 }; 116 };
99 }; 117 };
100 }
101 return {
102 requireConfigFile: 'src/scripts/config.js',
103 requireConfig: {
104 baseUrl: 'src/scripts',
105 callback: callback
106 }
107 };
108 };
109 118
110 var jasmineInstanbulTemplateOptions = function(template, nestedOptions) { 119 var foo = _.extend({}, template);
111 return { 120 var bar = template.process;
112 coverage: 'bin/coverage/coverage.json', 121 foo.process = function process(grunt, task, context) {
113 report: 'bin/coverage', 122 var src = [];
114 replace: false, 123 context.scripts.src.forEach(function(file) {
115 template: template, 124 if (!grunt.file.isMatch(specs, file)) {
116 templateOptions: nestedOptions 125 src.push(file);
117 }; 126 }
118 }; 127 });
128 context.scripts.src = src;
129 return bar.apply(this, arguments);
130 };
119 131
120 var jasmineOptions = function(withCoverage, options) { 132 templateOptions = {
121 var defaultOptions = {}; 133 coverage: 'bin/coverage/coverage.json',
122 defaultOptions.template = require('grunt-template-jasmine-requirejs'); 134 report: 'bin/coverage',
123 defaultOptions.templateOptions = jasmineRequirejsTemplateOptions(withCoverage); 135 replace: false,
124 if (withCoverage) { 136 template: foo,
125 defaultOptions.templateOptions = jasmineInstanbulTemplateOptions(defaultOptions.template, defaultOptions.templateOptions); 137 templateOptions: templateOptions,
126 defaultOptions.template = require('grunt-template-jasmine-istanbul'); 138 files: _.concat([], src, specs),
139 };
140 template = require('grunt-template-jasmine-istanbul');
127 } 141 }
128 return _.extend(defaultOptions, options); 142 var jasmineConfig = {
129 }; 143 src: _.concat([],
130 144 src,
131 grunt.initConfig({ 145 specs
132 jasmine: { 146 ),
133 all: { 147 options: {
134 src: [ 148 specs: specs,
135 'src/scripts/{,**/}*.js', 149 template: template,
136 '!src/scripts/main.js', 150 templateOptions: templateOptions,
137 'test/specs/**/*.js',
138 ],
139 options: jasmineOptions(false, null),
140 }, 151 },
141 }, 152 }
153 return jasmineConfig;
154 }
142 155
143 }); 156 grunt.config.set(['jasmine', 'all'], genJasmineConfig(true));
144 }; 157 };
......
...@@ -194,10 +194,6 @@ define(function(require) { ...@@ -194,10 +194,6 @@ define(function(require) {
194 queryField: 'value_d', 194 queryField: 'value_d',
195 facetType: 'year', 195 facetType: 'year',
196 facetStats: true, 196 facetStats: true,
197 formatter: function(item) {
198 var value = parseInt(item.get('key'));
199 return '$' + value + ' - $' + (value + 1000);
200 },
201 }; 197 };
202 var pojoItems = [ 198 var pojoItems = [
203 {key: '2005', value: 500}, 199 {key: '2005', value: 500},
...@@ -247,10 +243,6 @@ define(function(require) { ...@@ -247,10 +243,6 @@ define(function(require) {
247 queryField: 'value_d', 243 queryField: 'value_d',
248 facetType: 'year', 244 facetType: 'year',
249 facetStats: true, 245 facetStats: true,
250 formatter: function(item) {
251 var value = parseInt(item.get('key'));
252 return '$' + value + ' - $' + (value + 1000);
253 },
254 }; 246 };
255 if (hasBefore) { 247 if (hasBefore) {
256 if (hasAfter) { 248 if (hasAfter) {
...@@ -330,4 +322,5 @@ define(function(require) { ...@@ -330,4 +322,5 @@ define(function(require) {
330 rangeSupportHelper(false, true); 322 rangeSupportHelper(false, true);
331 }); 323 });
332 }); 324 });
325 return {};
333 }); 326 });
......
...@@ -17,7 +17,8 @@ define(function(require) { ...@@ -17,7 +17,8 @@ define(function(require) {
17 var Facets = NestedModels.mixin(Backbone.Model.extend({ 17 var Facets = NestedModels.mixin(Backbone.Model.extend({
18 initialize: function(data, options) { 18 initialize: function(data, options) {
19 this.url = function() { 19 this.url = function() {
20 return options.search.url(); 20 var url = options.search.url;
21 return _.isFunction(url) ? url.call() : url;
21 }; 22 };
22 _.each(this.keys(), _.bind(function(facetName) { 23 _.each(this.keys(), _.bind(function(facetName) {
23 var facet = this.get(facetName); 24 var facet = this.get(facetName);
...@@ -28,6 +29,7 @@ define(function(require) { ...@@ -28,6 +29,7 @@ define(function(require) {
28 'change:queryMax': 'item-change', 29 'change:queryMax': 'item-change',
29 }, function(eventValue, eventKey) { 30 }, function(eventValue, eventKey) {
30 facet.on(eventKey, function(model, value, options) { 31 facet.on(eventKey, function(model, value, options) {
32 console.log('trigger', facet.get('formName'), eventValue);
31 this.trigger(eventValue, facet, null, options); 33 this.trigger(eventValue, facet, null, options);
32 }, this); 34 }, this);
33 }, this); 35 }, this);
...@@ -88,7 +90,8 @@ define(function(require) { ...@@ -88,7 +90,8 @@ define(function(require) {
88 } 90 }
89 }); 91 });
90 facet.set('suggestions', suggestions); 92 facet.set('suggestions', suggestions);
91 if (!!options.facetSuggestions && options.childFacet === facet) { 93 //if (!!options.facetSuggestions && options.childFacet === facet) {
94 if (!!options.facetSuggestions) {
92 return; 95 return;
93 } 96 }
94 97
...@@ -126,10 +129,6 @@ define(function(require) { ...@@ -126,10 +129,6 @@ define(function(require) {
126 item.set({hidden: value === 0, value: value}); 129 item.set({hidden: value === 0, value: value});
127 } else { 130 } else {
128 item = new Facet.Item({key: key, value: value}); 131 item = new Facet.Item({key: key, value: value});
129 item.on('change:checked', function() {
130 this.trigger('item-change');
131 facet.trigger('item-change');
132 }, this);
133 } 132 }
134 newItems.push(item); 133 newItems.push(item);
135 }, this); 134 }, this);
...@@ -200,7 +199,7 @@ define(function(require) { ...@@ -200,7 +199,7 @@ define(function(require) {
200 var key = item.get('key'); 199 var key = item.get('key');
201 var fromDate, toDate; 200 var fromDate, toDate;
202 if (key === 'before') { 201 if (key === 'before') {
203 return rangeFormatter('*', facet.rangeStart + '-1SECOND'); 202 return '[* TO ' + facet.rangeStart + '-1SECOND]';
204 } 203 }
205 fromDate = new Date(key); 204 fromDate = new Date(key);
206 toDate = new Date(key); 205 toDate = new Date(key);
......
1 define(function(require) {
2 'use strict';
3 var _ = require('underscore');
4 var Backbone = require('backbone');
5 var Facets = require('solr/model/Facets');
6
7 function setData(obj, key, value) {
8 return obj[key] = value;
9 }
10
11 function getData(obj, key) {
12 return obj[key];
13 }
14
15 function createSolrResponse(has) {
16 var solrData = {};
17 var facetCounts = setData(solrData, 'facet_counts', {});
18 var facetIntervals = setData(facetCounts, 'facet_intervals', {});
19 var facetRanges = setData(facetCounts, 'facet_ranges', {});
20 var facetFields = setData(facetCounts, 'facet_fields', {});
21 var facetQueries = setData(facetCounts, 'facet_queries', {});
22 if (has.stats) {
23 solrData.stats = {};
24 setData(solrData.stats, 'stats_fields', {});
25 }
26 return solrData;
27 }
28
29 function makeSolrResponseMixedCase(solrData) {
30 var facetCounts = getData(solrData, 'facet_counts');
31 return {
32 facetCounts: facetCounts,
33 facetRanges: getData(facetCounts, 'facet_ranges'),
34 facetFields: getData(facetCounts, 'facet_fields'),
35 facetQueries: getData(facetCounts, 'facet_queries'),
36 statsFields: getData(solrData.stats, 'stats_fields'),
37 };
38 }
39
40 describe('Facets', function() {
41 it('loads', function() {
42 expect(Facets).toBeDefined();
43 });
44
45 describe('foo', function() {
46 var f;
47 var formData = [];
48 var solrData = [];
49 var origNow;
50 var onItemChange;
51 beforeEach(function() {
52 jasmine.clock().install();
53 jasmine.clock().mockDate();
54 origNow = _.now;
55 _.now = function() { return new Date().getTime(); };
56 spyOn(Backbone, 'ajax');
57 var facets = {
58 model: new Facets.Facet({
59 formName: 'model',
60 label: 'Model',
61 }, {
62 queryField: 'model_s',
63 facetType: 'field',
64 bins: {
65 misc: ['saturn', 'jeep'],
66 startsWithB: ['buick'],
67 },
68 }),
69 year: new Facets.Facet({
70 formName: 'year',
71 label: 'Year',
72 }, {
73 queryField: 'year_d',
74 comparator: Facets.Sort.date,
75 facetType: 'year',
76 facetStats: true,
77 }),
78 dateOfBirth: new Facets.Facet({
79 formName: 'dateOfBirth',
80 label: 'Birthday',
81 }, {
82 queryField: 'dateOfBirth_d',
83 comparator: Facets.Sort.date,
84 facetType: 'year',
85 facetStats: true,
86 other: 'before',
87 start: 'NOW/YEAR-25YEAR',
88 }),
89 price: new Facets.Facet({
90 formName: 'price',
91 label: 'Price',
92 }, {
93 queryField: 'price_i',
94 comparator: Facets.Sort.number,
95 facetType: 'field',
96 facetStats: true,
97 }),
98 };
99 onItemChange = jasmine.createSpy('onItemChange');
100 f = new Facets(facets, {search: {url: '/'}});
101 f.on('item-change', onItemChange);
102 });
103 afterEach(function() {
104 jasmine.clock().uninstall();
105 _.now = origNow;
106 });
107 describe('initial settings', function() {
108 it('foo', function() {
109 expect(true).toBe(true);
110 });
111 });
112 describe('step 1', function() {
113 beforeEach(function() {
114 formData.push(f.getFacetFormData());
115 });
116 function expectItem(item, key, value, checked) {
117 expect(item.get('key')).toEqual(key);
118 expect(item.get('value')).toEqual(value);
119 expect(item.get('checked')).toEqual(checked);
120 }
121
122 describe('facets', function() {
123 var modelFacet, modelItems;
124 var yearFacet, yearItems;
125 var dobFacet, dobItems;
126 var priceFacet, priceItems;
127 beforeEach(function() {
128 var solrResponse = createSolrResponse({stats: true});
129 var solrData = makeSolrResponseMixedCase(solrResponse);
130 //console.log('solrData', JSON.stringify(solrResponse));
131 solrData.facetRanges.year = {
132 counts: [
133 '2000-01-01T00:00:00.000Z', 1,
134 '2001-01-01T00:00:00.000Z', 4,
135 '2002-01-01T00:00:00.000Z', 0,
136 '2003-01-01T00:00:00.000Z', 3,
137 '2004-01-01T00:00:00.000Z', 0,
138 '2005-01-01T00:00:00.000Z', 0,
139 '2006-01-01T00:00:00.000Z', 0,
140 '2007-01-01T00:00:00.000Z', 0,
141 '2008-01-01T00:00:00.000Z', 7,
142 '2009-01-01T00:00:00.000Z', 0,
143 '2010-01-01T00:00:00.000Z', 1,
144 ],
145 };
146 solrData.facetRanges.dateOfBirth = {
147 counts: [
148 '1974-01-01T00:00:00.000Z', 1,
149 '1972-01-01T00:00:00.000Z', 1,
150 '1970-01-01T00:00:00.000Z', 1,
151 ],
152 before: 5,
153 };
154 solrData.facetFields.model = [
155 'ford', 23,
156 'chevy', 18,
157 'toyota', 5,
158 'saturn', 7, // keep here to test the bin/exclude feature
159 'jeep', 19, // keep here to test the bin/exclude feature
160 'buick', 0, // keep here to test the bin/exclude feature
161 'dodge', 0,
162 ];
163 solrData.facetFields.price = [
164 '23456', 1,
165 '5678', 2,
166 '1234', 3,
167 ];
168 solrData.facetQueries['model:misc'] = 26;
169 solrData.facetQueries['model:startsWithB'] = 0;
170 solrData.statsFields.year = {min: '2000', max: '2010'};
171 solrData.statsFields.dateOfBirth = {min: '2000', max: '2010'};
172 solrData.statsFields.price = {min: '1234', max: '23456'};
173 f.applyFacetResults(solrResponse);
174 modelFacet = f.get('model');
175 modelItems = modelFacet.get('items');
176 yearFacet = f.get('year');
177 yearItems = yearFacet.get('items');
178 dobFacet = f.get('dateOfBirth');
179 dobItems = dobFacet.get('items');
180 priceFacet = f.get('price');
181 priceItems = priceFacet.get('items');
182 });
183 it('initial', function() {
184 //console.log(JSON.stringify(yearItems));
185 expect(yearItems.length).toBe(5);
186 expectItem(yearItems.at(0), '2000-01-01T00:00:00.000Z', 1, false);
187 expectItem(yearItems.at(1), '2001-01-01T00:00:00.000Z', 4, false);
188 expectItem(yearItems.at(2), '2003-01-01T00:00:00.000Z', 3, false);
189 expectItem(yearItems.at(3), '2008-01-01T00:00:00.000Z', 7, false);
190 expectItem(yearItems.at(4), '2010-01-01T00:00:00.000Z', 1, false);
191 expect(modelItems.length).toBe(4);
192 expectItem(modelItems.at(0), 'chevy', 18, false);
193 expectItem(modelItems.at(1), 'ford', 23, false);
194 expectItem(modelItems.at(2), 'misc', 26, false);
195 expectItem(modelItems.at(3), 'toyota', 5, false);
196 expect(dobItems.length).toBe(4);
197 expectItem(dobItems.at(0), 'before', 5, false);
198 expectItem(dobItems.at(1), '1970-01-01T00:00:00.000Z', 1, false);
199 expectItem(dobItems.at(2), '1972-01-01T00:00:00.000Z', 1, false);
200 expectItem(dobItems.at(3), '1974-01-01T00:00:00.000Z', 1, false);
201 expect(priceItems.length).toBe(3);
202 expectItem(priceItems.at(0), '1234', 3, false);
203 expectItem(priceItems.at(1), '5678', 2, false);
204 expectItem(priceItems.at(2), '23456', 1, false);
205 expect(Backbone.ajax).not.toHaveBeenCalled();
206 expect(onItemChange).not.toHaveBeenCalled();
207 });
208 describe('click', function() {
209 beforeEach(function() {
210 modelItems.get('ford').set('checked', true);
211 modelItems.get('toyota').set('checked', true);
212 yearItems.get('2003-01-01T00:00:00.000Z').set('checked', true);
213 dobItems.get('before').set('checked', true);
214 priceFacet.set('queryMin', 1234);
215 priceFacet.set('queryMax', 6000);
216 });
217 it('result', function() {
218 expect(Backbone.ajax).not.toHaveBeenCalled();
219 expect(onItemChange).toHaveBeenCalled();
220 expect(onItemChange.calls.count()).toEqual(6);
221 console.log(JSON.stringify(onItemChange.calls.allArgs(), null, 1));
222 var facetFormData = f.getFacetFormData();
223 console.log(JSON.stringify(facetFormData, null, 1));
224 expect(facetFormData.facet).toBe(true);
225 expect(facetFormData.stats).toBe(true);
226 expect(facetFormData['facet.missing']).toBe(true);
227 expect(facetFormData.fq).toEqual([
228 "{!tag=model}model_s:(\"ford\" OR \"toyota\")",
229 "{!tag=year}year_d:([2003-01-01T00:00:00.000Z TO 2004-01-01T00:00:00.000Z])",
230 "{!tag=dateOfBirth}dateOfBirth_d:([* TO NOW/YEAR-25YEAR-1SECOND])",
231 "{!tag=price}price_i:([1234 TO 6000])"
232 ]);
233 });
234 });
235 });
236 describe('suggestions', function() {
237 beforeEach(function() {
238 f.get('model').set('query', 'fo');
239 });
240 it('initial', function() {
241 expect(true).toBe(true);
242 expect(Backbone.ajax).not.toHaveBeenCalled();
243 });
244 describe('call solr', function() {
245 beforeEach(function() {
246 jasmine.clock().tick(300);
247 });
248 it('ajax called with', function() {
249 expect(Backbone.ajax).toHaveBeenCalled();
250 expect(Backbone.ajax.calls.count()).toBe(1);
251 var ajaxData = Backbone.ajax.calls.argsFor(0);
252 //console.log(JSON.stringify(ajaxData, null, 1));
253 expect(ajaxData.length).toBe(1);
254 var arg0 = ajaxData[0];
255 expect(arg0.facetSuggestions).toBe(true);
256 expect(arg0.childFacet).toBe(f.get('model'));
257 var data = arg0.data;
258 expect(data.rows).toBe(0);
259 });
260 describe('result', function() {
261 var wantedSuggestions;
262 beforeEach(function() {
263 var solrResponse = createSolrResponse({stats: true});
264 var solrData = makeSolrResponseMixedCase(solrResponse);
265 //console.log('solrData', JSON.stringify(solrData));
266 solrData.facetFields['suggestions:model'] = [
267 'toyota', 5,
268 'ford', 23,
269 'chevy', 18,
270 'nissan', 0,
271 ];
272
273 var ajaxData = Backbone.ajax.calls.argsFor(0);
274 var arg0 = ajaxData[0];
275 arg0.success(solrResponse, arg0);
276 wantedSuggestions = [
277 {key: 'toyota', value: 5},
278 {key: 'ford', value: 23},
279 {key: 'chevy', value: 18},
280 ];
281 });
282 it('applied', function() {
283 expect(f.get('model').get('suggestions')).toEqual(wantedSuggestions);
284 });
285 describe('reset suggestions', function() {
286 beforeEach(function() {
287 f.get('model').set('query', '');
288 });
289 it('foo', function() {
290 expect(Backbone.ajax).toHaveBeenCalled();
291 expect(Backbone.ajax.calls.count()).toBe(1);
292 expect(f.get('model').get('suggestions')).toEqual(wantedSuggestions);
293 });
294 describe('call solr', function() {
295 beforeEach(function() {
296 jasmine.clock().tick(300);
297 });
298 it('foo', function() {
299 expect(Backbone.ajax).toHaveBeenCalled();
300 expect(Backbone.ajax.calls.count()).toBe(1);
301 expect(f.get('model').get('suggestions')).toEqual([]);
302 });
303 });
304 });
305 });
306
307 });
308 });
309 });
310 });
311 });
312 });
1 define(function(require) {
2 'use strict';
3 var _ = require('underscore');
4 var Backbone = require('backbone');
5 var Facets = require('solr/model/Facets');
6
7 describe('Facets', function() {
8 it('loads', function() {
9 expect(Facets).toBeDefined();
10 });
11 });
12 });