]> git.proxmox.com Git - extjs.git/blame - extjs/classic/classic/test/specs/grid/feature/GroupingSummary.js
add extjs 6.0.1 sources
[extjs.git] / extjs / classic / classic / test / specs / grid / feature / GroupingSummary.js
CommitLineData
6527f429
DM
1describe('Ext.grid.feature.GroupingSummary', function () {\r
2 var data, grid, store, groupingSummary, columns, params, selector,\r
3 synchronousLoad = true,\r
4 proxyStoreLoad = Ext.data.ProxyStore.prototype.load,\r
5 loadStore;\r
6\r
7 function createGrid(gridCfg, groupingSummaryCfg, columns, storeCfg) {\r
8 data = [{\r
9 student: 'Student 1',\r
10 subject: 'Math',\r
11 mark: 84,\r
12 allowance: 15.50\r
13 },{\r
14 student: 'Student 1',\r
15 subject: 'Science',\r
16 mark: 72,\r
17 allowance: 10.75\r
18 },{\r
19 student: 'Student 2',\r
20 subject: 'Math',\r
21 mark: 96,\r
22 allowance: 100.75\r
23 },{\r
24 student: 'Student 2',\r
25 subject: 'Science',\r
26 mark: 68,\r
27 allowance: 1.55\r
28 }];\r
29\r
30 Ext.define('spec.GroupingSummary', {\r
31 extend: 'Ext.data.Model',\r
32 fields: [\r
33 'student',\r
34 'subject',\r
35 {\r
36 name: 'mark',\r
37 type: 'int'\r
38 },\r
39 {\r
40 name: 'allowance',\r
41 type: 'float'\r
42 }\r
43 ]\r
44 });\r
45\r
46 storeCfg = Ext.apply({\r
47 model: 'spec.GroupingSummary',\r
48 data: data,\r
49 autoDestroy: true\r
50 }, storeCfg);\r
51\r
52 if (!storeCfg.grouper && !storeCfg.hasOwnProperty('groupField')) {\r
53 storeCfg.groupField = 'subject';\r
54 }\r
55\r
56 store = new Ext.data.Store(storeCfg);\r
57\r
58 groupingSummary = new Ext.grid.feature.GroupingSummary(Ext.apply({\r
59 ftype: 'groupingsummary'\r
60 }, groupingSummaryCfg));\r
61\r
62 columns = columns || [{\r
63 itemId: 'studentColumn',\r
64 dataIndex: 'student',\r
65 text: 'Name',\r
66 summaryType: 'count',\r
67 summaryRenderer: function (value, summaryData, field, metaData) {\r
68 params = arguments;\r
69 return Ext.String.format('{0} student{1}', value, value !== 1 ? 's' : '');\r
70 }\r
71 }, {\r
72 itemId: 'markColumn',\r
73 dataIndex: 'mark',\r
74 text: 'Mark',\r
75 summaryType: 'average'\r
76 }, {\r
77 itemId: 'noDataIndexColumn',\r
78 summaryType: function (records, values) {\r
79 var i = 0,\r
80 length = records.length,\r
81 total = 0,\r
82 record;\r
83\r
84 for (; i < length; ++i) {\r
85 record = records[i];\r
86 total += record.get('allowance');\r
87 }\r
88 return total;\r
89 },\r
90 summaryRenderer: function (value, summaryData, field, metaData) {\r
91 return Ext.util.Format.usMoney(value || metaData.record.get('allowance'));\r
92 },\r
93 renderer: function(value, metaData, record, rowIdx, colIdx, store, view) {\r
94 return Ext.util.Format.usMoney(record.get('allowance'));\r
95 }\r
96 }];\r
97\r
98 grid = new Ext.grid.Panel(Ext.apply({\r
99 store: store,\r
100 columns: columns,\r
101 width: 600,\r
102 height: 300,\r
103 features: groupingSummary,\r
104 renderTo: Ext.getBody()\r
105 }, gridCfg));\r
106 selector = groupingSummary.summaryRowSelector;\r
107 }\r
108\r
109 function expectData(fields, expected) {\r
110 var groupInfo = groupingSummary.getMetaGroup(store.getGroups().getAt(0)),\r
111 record = groupInfo.aggregateRecord;\r
112\r
113 expect(record.get(fields[0])).toBe(expected[0]);\r
114 expect(record.get(fields[1])).toBe(expected[1]);\r
115 }\r
116\r
117 function expectSummaryRow(view) {\r
118 var summaryRow = grid.view.body.down('.x-grid-row-summary', true);\r
119\r
120 expect((summaryRow.textContent || summaryRow.innerText).replace(/\s/g, '')).toBe(view);\r
121 }\r
122\r
123 beforeEach(function() {\r
124 // Override so that we can control asynchronous loading\r
125 loadStore = Ext.data.ProxyStore.prototype.load = function() {\r
126 proxyStoreLoad.apply(this, arguments);\r
127 if (synchronousLoad) {\r
128 this.flushLoad.apply(this, arguments);\r
129 }\r
130 return this;\r
131 };\r
132 });\r
133\r
134 afterEach(function() {\r
135 // Undo the overrides.\r
136 Ext.data.ProxyStore.prototype.load = proxyStoreLoad;\r
137\r
138 grid.destroy();\r
139 grid = store = groupingSummary = columns = params = null;\r
140 Ext.undefine('spec.GroupingSummary');\r
141 Ext.data.Model.schema.clear();\r
142 });\r
143\r
144 describe('summaryRenderer', function () {\r
145 it('should be passed the expected function parameters', function () {\r
146 // Note that we're only capturing the values for the second group.\r
147 createGrid();\r
148\r
149 // Params should be:\r
150 // value - The calculated value.\r
151 // summaryData - Contains all raw summary values for the row.\r
152 // field - The name of the field we are calculating\r
153 // metaData - The collection of metadata about the current cell.\r
154 expect(params.length).toBe(4);\r
155 expect(params[0]).toBe(2);\r
156 expect(params[1]).toEqual({\r
157 studentColumn: 2,\r
158 markColumn: 70,\r
159 noDataIndexColumn: 12.3\r
160 });\r
161 expect(params[2]).toBe('student');\r
162 expect(params[3].tdCls).toBeDefined();\r
163 });\r
164\r
165 it('should be able to read the data from the summary record when there is no column.dataIndex', function () {\r
166 var node;\r
167\r
168 createGrid();\r
169\r
170 // The "Student 2" item is a wrapper which also encapsulates the summary row.\r
171 // It will contain 2 rows: Student 2 and the summary.\r
172 node = grid.view.all.item(1, true);\r
173\r
174 expect((node.textContent || node.innerText).replace(/\r\n?|\n/g, '')).toBe('Student 296$100.752 students90$116.25');\r
175 });\r
176\r
177 it('should update when group records are removed', function () {\r
178 var mathGroup;\r
179\r
180 createGrid();\r
181 mathGroup = groupingSummary.summaryData.Math;\r
182\r
183 // Pre-removal.\r
184 expect(mathGroup.markColumn).toBe(90);\r
185 expect(mathGroup.noDataIndexColumn).toBe(116.25);\r
186 expect(mathGroup.studentColumn).toBe(2);\r
187\r
188 store.removeAt(1);\r
189\r
190 // The summaryData record should be updated.\r
191 expect(mathGroup.markColumn).toBe(84);\r
192 expect(mathGroup.noDataIndexColumn).toBe(15.5);\r
193 expect(mathGroup.studentColumn).toBe(1);\r
194 });\r
195 });\r
196\r
197 describe("toggling the summary row", function() {\r
198 function toggle(visible) {\r
199 groupingSummary.toggleSummaryRow(visible);\r
200 }\r
201\r
202 it("should show the summary row by default", function() {\r
203 createGrid();\r
204 expect(grid.getView().getEl().select(selector).getCount()).toBe(2);\r
205 });\r
206\r
207 it("should not render the summary rows if configured with showSummaryRow: false", function() {\r
208 createGrid(null, {\r
209 showSummaryRow: false\r
210 });\r
211 expect(grid.getView().getEl().select(selector).getCount()).toBe(0);\r
212 });\r
213\r
214 it("should not show summary rows when toggling off", function() {\r
215 createGrid();\r
216 expect(grid.getView().getEl().select(selector).getCount()).toBe(2);\r
217 toggle();\r
218 expect(grid.getView().getEl().select(selector).getCount()).toBe(0);\r
219 });\r
220\r
221 it("should show summary rows when toggling on", function() {\r
222 createGrid(null, {\r
223 showSummaryRow: false\r
224 });\r
225 expect(grid.getView().getEl().select(selector).getCount()).toBe(0);\r
226 toggle();\r
227 expect(grid.getView().getEl().select(selector).getCount()).toBe(2);\r
228 });\r
229\r
230 it("should leave the summary visible when explicitly passing visible: true", function() {\r
231 createGrid();\r
232 toggle(true);\r
233 expect(grid.getView().getEl().select(selector).getCount()).toBe(2);\r
234 });\r
235\r
236 it("should leave the summary off when explicitly passed visible: false", function() {\r
237 createGrid();\r
238 toggle();\r
239 toggle(false);\r
240 expect(grid.getView().getEl().select(selector).getCount()).toBe(0);\r
241 });\r
242\r
243 it("should update the summary row if the change happened while not visible", function() {\r
244 createGrid();\r
245 // Off\r
246 toggle();\r
247 store.first().set('mark', 0);\r
248 toggle();\r
249\r
250 var row = grid.getView().getEl().select(selector).first(),\r
251 cell = row.down(grid.down('#markColumn').getCellSelector());\r
252\r
253\r
254 var content = cell.down(grid.getView().innerSelector).dom.innerHTML;\r
255 expect(content).toBe('48');\r
256 });\r
257 });\r
258\r
259 describe('when the view is refreshed', function () {\r
260 function expectIt(data) {\r
261 it('should retain the summary feature row information in the feature cache', function () {\r
262 // Get the cached information that the feature is retaining for the Math group.\r
263 var groupInfo = groupingSummary.getMetaGroup(store.getGroups().getAt(0)),\r
264 record = groupInfo.aggregateRecord;\r
265\r
266 expect(record.get('student')).toBe(data.student);\r
267 expect(record.get('mark')).toBe(data.mark);\r
268 expect(record.get('noDataIndexColumn')).toBe(data.noDataIndexColumn);\r
269 });\r
270\r
271 it('should retain the summary feature row information in the view', function () {\r
272 var summaryRow = grid.view.body.down('.x-grid-row-summary', true);\r
273\r
274 expect((summaryRow.textContent || summaryRow.innerText).replace(/\s/g, '')).toBe(data.view);\r
275 });\r
276 }\r
277\r
278 describe('when toggling the enabled/disabled state of the groups', function () {\r
279 // Note that the bug only happens when toggling twice (first to disable, then to enable).\r
280 // See EXTJS-16141.\r
281 beforeEach(function () {\r
282 createGrid();\r
283\r
284 groupingSummary.disable();\r
285 groupingSummary.enable();\r
286 });\r
287\r
288 expectIt({\r
289 student: 2,\r
290 mark: 90,\r
291 noDataIndexColumn: 116.25,\r
292 view: '2students90$116.25'\r
293 });\r
294 });\r
295\r
296 describe('when filtering the store', function () {\r
297 // See EXTJS-15267.\r
298 beforeEach(function () {\r
299 createGrid();\r
300\r
301 grid.store.addFilter({property: 'mark', operator: 'eq', value: 84})\r
302 });\r
303\r
304 describe('adding a filter', function () {\r
305 expectIt({\r
306 student: 1,\r
307 mark: 84,\r
308 noDataIndexColumn: 15.50,\r
309 view: '1student84$15.50'\r
310 });\r
311 });\r
312\r
313 describe('clearing the filters', function () {\r
314 beforeEach(function () {\r
315 grid.store.clearFilter();\r
316 });\r
317\r
318 expectIt({\r
319 student: 2,\r
320 mark: 90,\r
321 noDataIndexColumn: 116.25,\r
322 view: '2students90$116.25'\r
323 });\r
324 });\r
325 });\r
326 });\r
327\r
328 describe('reconfiguring', function () {\r
329 beforeEach(function () {\r
330 createGrid();\r
331 });\r
332\r
333 describe('new store', function () {\r
334 it('should update the summary row', function () {\r
335 store = new Ext.data.Store({\r
336 model: 'spec.GroupingSummary',\r
337 groupField: 'subject',\r
338 data: [{\r
339 student: 'Student 1',\r
340 subject: 'Math',\r
341 mark: 84,\r
342 allowance: 15.50\r
343 },{\r
344 student: 'Student 2',\r
345 subject: 'Science',\r
346 mark: 68,\r
347 allowance: 1.55\r
348 }],\r
349 autoDestroy: true\r
350 });\r
351\r
352 grid.reconfigure(store);\r
353\r
354 expectData(\r
355 ['mark', 'noDataIndexColumn'],\r
356 [84, 15.50]\r
357 );\r
358\r
359 expectSummaryRow('1student84$15.50');\r
360 });\r
361 });\r
362\r
363 describe('new columns', function () {\r
364 it('should update the summary row', function () {\r
365 grid.reconfigure(null, [{\r
366 itemId: 'studentColumn',\r
367 dataIndex: 'student',\r
368 text: 'Name',\r
369 summaryType: 'count',\r
370 summaryRenderer: function (value, summaryData, field, metaData) {\r
371 params = arguments;\r
372 return Ext.String.format('{0} student{1}', value, value !== 1 ? 's' : '');\r
373 }\r
374 }, {\r
375 itemId: 'allowance',\r
376 dataIndex: 'allowance',\r
377 text: 'Allowance',\r
378 summaryType: 'average'\r
379 }]);\r
380\r
381 expectData(\r
382 ['student', 'allowance'],\r
383 [2, 58.125]\r
384 );\r
385\r
386 expectSummaryRow('2students58.125');\r
387 });\r
388 });\r
389 });\r
390\r
391 describe("loading the store", function() {\r
392 beforeEach(function() {\r
393 MockAjaxManager.addMethods();\r
394 });\r
395\r
396 afterEach(function() {\r
397 MockAjaxManager.removeMethods();\r
398 });\r
399\r
400 it("should update the summary when loading remote data", function() {\r
401 createGrid(null, null, null, {\r
402 data: null,\r
403 proxy: {\r
404 type: 'ajax',\r
405 url: 'Foo'\r
406 }\r
407 });\r
408 store.load();\r
409 Ext.Ajax.mockComplete({\r
410 status: 200,\r
411 responseText: Ext.encode(data)\r
412 });\r
413\r
414 var rows = grid.view.el.query(groupingSummary.summaryRowSelector);\r
415\r
416 expect((rows[0].textContent || rows[0].innerText).replace(/\s/g, '')).toBe('2students90$116.25');\r
417 expect((rows[1].textContent || rows[1].innerText).replace(/\s/g, '')).toBe('2students70$12.30');\r
418\r
419 store.load();\r
420 Ext.Ajax.mockComplete({\r
421 status: 200,\r
422 responseText: Ext.encode([{\r
423 student: 'Student 1',\r
424 subject: 'Math',\r
425 mark: 77,\r
426 allowance: 30\r
427 }, {\r
428 student: 'Student 2',\r
429 subject: 'Science',\r
430 mark: 20,\r
431 allowance: 30.12\r
432 }, {\r
433 student: 'Student 3',\r
434 subject: 'Science',\r
435 mark: 30,\r
436 allowance: 12\r
437 }, {\r
438 student: 'Student 4',\r
439 subject: 'Science',\r
440 mark: 40,\r
441 allowance: 1\r
442 }])\r
443 });\r
444\r
445 rows = grid.view.el.query(groupingSummary.summaryRowSelector);\r
446\r
447 expect((rows[0].textContent || rows[0].innerText).replace(/\s/g, '')).toBe('1student77$30.00');\r
448 expect((rows[1].textContent || rows[1].innerText).replace(/\s/g, '')).toBe('3students30$43.12');\r
449 });\r
450\r
451 it("should update the summary when loading local data", function() {\r
452 createGrid();\r
453\r
454 var rows = grid.view.el.query(groupingSummary.summaryRowSelector);\r
455\r
456 expect((rows[0].textContent || rows[0].innerText).replace(/\s/g, '')).toBe('2students90$116.25');\r
457 expect((rows[1].textContent || rows[1].innerText).replace(/\s/g, '')).toBe('2students70$12.30');\r
458\r
459 store.loadData([{\r
460 student: 'Student 1',\r
461 subject: 'Math',\r
462 mark: 77,\r
463 allowance: 30\r
464 }, {\r
465 student: 'Student 2',\r
466 subject: 'Science',\r
467 mark: 20,\r
468 allowance: 30.12\r
469 }, {\r
470 student: 'Student 3',\r
471 subject: 'Science',\r
472 mark: 30,\r
473 allowance: 12\r
474 }, {\r
475 student: 'Student 4',\r
476 subject: 'Science',\r
477 mark: 40,\r
478 allowance: 1\r
479 }]);\r
480\r
481 rows = grid.view.el.query(groupingSummary.summaryRowSelector);\r
482\r
483 expect((rows[0].textContent || rows[0].innerText).replace(/\s/g, '')).toBe('1student77$30.00');\r
484 expect((rows[1].textContent || rows[1].innerText).replace(/\s/g, '')).toBe('3students30$43.12');\r
485 });\r
486 });\r
487\r
488 describe('remoteRoot', function () {\r
489 function completeWithData(data) {\r
490 Ext.Ajax.mockComplete({\r
491 status: 200,\r
492 responseText: Ext.JSON.encode(data)\r
493 });\r
494 }\r
495\r
496 beforeEach(function () {\r
497 MockAjaxManager.addMethods();\r
498\r
499 createGrid(null, {\r
500 remoteRoot: 'summaryData'\r
501 }, null, {\r
502 remoteSort: true,\r
503 proxy: {\r
504 type: 'ajax',\r
505 url: 'data.json',\r
506 reader: {\r
507 type: 'json',\r
508 rootProperty: 'data'\r
509 }\r
510 },\r
511 grouper: {property: 'student'},\r
512 data: null\r
513 });\r
514\r
515 store.load();\r
516\r
517 completeWithData({\r
518 data: data,\r
519 summaryData: [{\r
520 allowance: 67,\r
521 mark: 42,\r
522 student: 'Student 1'\r
523 }, {\r
524 allowance: 100,\r
525 mark: 99,\r
526 student: 'Student 2'\r
527 }],\r
528 total: 4\r
529 });\r
530 });\r
531\r
532 afterEach(function () {\r
533 MockAjaxManager.removeMethods();\r
534 });\r
535\r
536 it('should correctly render the data in the view', function () {\r
537 var rows = grid.view.body.query('.x-grid-row-summary');\r
538\r
539 expect((rows[0].textContent || rows[0].innerText).replace(/\s/g, '')).toBe('Student1students42$67.00');\r
540 expect((rows[1].textContent || rows[1].innerText).replace(/\s/g, '')).toBe('Student2students99$100.00');\r
541 });\r
542\r
543 it('should create a summaryData object for each group', function () {\r
544 var summaryData = groupingSummary.summaryData;\r
545\r
546 expect(summaryData['Student 1']).toBeDefined();\r
547 expect(summaryData['Student 2']).toBeDefined();\r
548 });\r
549\r
550 it('should create a metaGroupCache entry for each group', function () {\r
551 var metaGroupCache = groupingSummary.getCache();\r
552\r
553 expect(metaGroupCache['Student 1']).toBeDefined();\r
554 expect(metaGroupCache['Student 2']).toBeDefined();\r
555 });\r
556 });\r
557});\r
558\r