]> git.proxmox.com Git - extjs.git/blame - extjs/classic/classic/test/specs/grid/column/Check.js
bump version to 7.0.0-4
[extjs.git] / extjs / classic / classic / test / specs / grid / column / Check.js
CommitLineData
947f0963
TL
1topSuite("Ext.grid.column.Check", ['Ext.grid.Panel', 'Ext.grid.column.Template'], function() {
2 var itNotIE9 = Ext.isIE9 ? xit : it,
3 grid, view, store, col,
4 invert = false;
5
6 function getColCfg(cfg) {
7 return Ext.apply({
8 xtype: 'checkcolumn',
9 text: 'Checked',
10 dataIndex: 'val',
11 invert: invert
12 }, cfg);
13 }
14
15 function makeGrid(columns, data, gridCfg) {
16 store = new Ext.data.Store({
17 model: spec.CheckColumnModel,
18 data: data || [{
19 val: true
20 }, {
21 val: true
22 }, {
23 val: false
24 }, {
25 val: true
26 }, {
27 val: false
28 }]
29 });
30
31 if (!columns) {
32 columns = [getColCfg()];
33 }
34
35 grid = new Ext.grid.Panel(Ext.apply({
36 width: 200,
37 renderTo: Ext.getBody(),
38 store: store,
39 columns: columns
40 }, gridCfg));
41 view = grid.getView();
42 col = grid.getColumnManager().getFirst();
43 }
44
45 function triggerCellMouseEvent(type, rowIdx, cellIdx, button, x, y) {
46 var target = getCellImg(rowIdx, cellIdx);
47
48 jasmine.fireMouseEvent(target, type, x, y, button);
49 }
50
51 function getCell(rowIdx) {
52 return grid.getView().getCellInclusive({
53 row: rowIdx,
54 column: 0
55 }, true);
56 }
57
58 function getCellImg(rowIdx) {
59 var cell = getCell(rowIdx);
60
61 return cell.querySelector('.x-grid-checkcolumn');
62 }
63
64 function hasCls(el, cls) {
65 return Ext.fly(el).hasCls(cls);
66 }
67
68 function clickHeader() {
69 jasmine.fireMouseEvent(col.el.dom.querySelector('.' + col.headerCheckboxCls), 'click');
70 }
71
72 beforeEach(function() {
73 Ext.define('spec.CheckColumnModel', {
74 extend: 'Ext.data.Model',
75 fields: ['val']
76 });
77 });
78
79 afterEach(function() {
80 Ext.destroy(grid, store);
81 col = grid = store = null;
82 Ext.undefine('spec.CheckColumnModel');
83 Ext.data.Model.schema.clear();
84 });
85
86 it("should be able to create an instance without passing a config", function() {
87 var col = new Ext.grid.column.Check();
88
89 expect(col.isCheckColumn).toBe(true);
90 col.destroy();
91 });
92
93 describe("check rendering", function() {
94
95 it("should add the x-grid-checkcolumn class to the checkbox element", function() {
96 makeGrid();
97
98 expect(hasCls(getCellImg(0), 'x-grid-checkcolumn')).toBe(true);
99 });
100
101 it("should set the x-grid-checkcolumn-checked class on checked items", function() {
102 makeGrid();
103
104 expect(hasCls(getCellImg(0), 'x-grid-checkcolumn-checked')).toBe(true);
105 expect(hasCls(getCellImg(1), 'x-grid-checkcolumn-checked')).toBe(true);
106 expect(hasCls(getCellImg(2), 'x-grid-checkcolumn-checked')).toBe(false);
107 expect(hasCls(getCellImg(3), 'x-grid-checkcolumn-checked')).toBe(true);
108 expect(hasCls(getCellImg(4), 'x-grid-checkcolumn-checked')).toBe(false);
109 });
110 it("should set the x-grid-checkcolumn-checked class on checked items with invert: true", function() {
111 invert = true;
112 makeGrid();
113 invert = false;
114
115 expect(hasCls(getCellImg(0), 'x-grid-checkcolumn-checked')).toBe(false);
116 expect(hasCls(getCellImg(1), 'x-grid-checkcolumn-checked')).toBe(false);
117 expect(hasCls(getCellImg(2), 'x-grid-checkcolumn-checked')).toBe(true);
118 expect(hasCls(getCellImg(3), 'x-grid-checkcolumn-checked')).toBe(false);
119 expect(hasCls(getCellImg(4), 'x-grid-checkcolumn-checked')).toBe(true);
120 });
121 });
122
123 describe("enable/disable", function() {
124 describe("during config", function() {
125 it("should not include the disabledCls if the column is not disabled", function() {
126 makeGrid();
127 expect(hasCls(getCell(0), col.disabledCls)).toBe(false);
128 });
129
130 it("should include the disabledCls if the column is disabled", function() {
131 var cfg = getColCfg();
132
133 cfg.disabled = true;
134 makeGrid([cfg]);
135 expect(hasCls(getCell(0), col.disabledCls)).toBe(true);
136 });
137 });
138
139 describe("after render", function() {
140 it("should add the disabledCls if disabling", function() {
141 makeGrid();
142 col.disable();
143 expect(hasCls(getCell(0), col.disabledCls)).toBe(true);
144 expect(hasCls(getCell(1), col.disabledCls)).toBe(true);
145 expect(hasCls(getCell(2), col.disabledCls)).toBe(true);
146 expect(hasCls(getCell(3), col.disabledCls)).toBe(true);
147 expect(hasCls(getCell(4), col.disabledCls)).toBe(true);
148 });
149
150 it("should remove the disabledCls if enabling", function() {
151 var cfg = getColCfg();
152
153 cfg.disabled = true;
154 makeGrid([cfg]);
155 col.enable();
156 expect(hasCls(getCell(0), col.disabledCls)).toBe(false);
157 expect(hasCls(getCell(1), col.disabledCls)).toBe(false);
158 expect(hasCls(getCell(2), col.disabledCls)).toBe(false);
159 expect(hasCls(getCell(3), col.disabledCls)).toBe(false);
160 expect(hasCls(getCell(4), col.disabledCls)).toBe(false);
161 });
162 });
163 });
164
165 describe("interaction", function() {
166 describe("stopSelection", function() {
167 describe("stopSelection: false", function() {
168 it("should select when a full row update is required", function() {
169 var cfg = getColCfg();
170
171 cfg.stopSelection = false;
172 // Template column always required a full update
173 makeGrid([cfg, {
174 xtype: 'templatecolumn',
175 dataIndex: 'val',
176 tpl: '{val}'
177 }]);
178 triggerCellMouseEvent('click', 0);
179 expect(grid.getSelectionModel().isSelected(store.getAt(0))).toBe(true);
180 });
181
182 it("should select when a full row update is not required", function() {
183 var cfg = getColCfg();
184
185 cfg.stopSelection = false;
186 // Template column always required a full update
187 makeGrid([cfg, {
188 dataIndex: 'val'
189 }]);
190 triggerCellMouseEvent('click', 0);
191 expect(grid.getSelectionModel().isSelected(store.getAt(0))).toBe(true);
192 });
193 });
194
195 describe("stopSelection: true", function() {
196 it("should not select when a full row update is required", function() {
197 var cfg = getColCfg();
198
199 cfg.stopSelection = true;
200 // Template column always required a full update
201 makeGrid([cfg, {
202 xtype: 'templatecolumn',
203 dataIndex: 'val',
204 tpl: '{val}'
205 }]);
206 triggerCellMouseEvent('click', 0);
207 expect(grid.getSelectionModel().isSelected(store.getAt(0))).toBe(false);
208 });
209
210 it("should not select when a full row update is not required", function() {
211 var cfg = getColCfg();
212
213 cfg.stopSelection = true;
214 // Template column always required a full update
215 makeGrid([cfg, {
216 dataIndex: 'val'
217 }]);
218 triggerCellMouseEvent('click', 0);
219 expect(grid.getSelectionModel().isSelected(store.getAt(0))).toBe(false);
220 });
221 });
222 });
223
224 describe("events", function() {
225 it("should pass the column, record index, new checked state & record for beforecheckchange", function() {
226 var arg1, arg2, arg3, arg4;
227
228 makeGrid();
229 col.on('beforecheckchange', function(a, b, c, d) {
230 arg1 = a;
231 arg2 = b;
232 arg3 = c;
233 arg4 = d;
234 });
235 triggerCellMouseEvent(col.triggerEvent, 0);
236 expect(arg1).toBe(col);
237 expect(arg2).toBe(0);
238 expect(arg3).toBe(false);
239 expect(arg4).toBe(store.getAt(0));
240 });
241
242 it("should pass the column, record index, new checked state & record for checkchange", function() {
243 var arg1, arg2, arg3, arg4;
244
245 makeGrid();
246 col.on('checkchange', function(a, b, c, d) {
247 arg1 = a;
248 arg2 = b;
249 arg3 = c;
250 arg4 = d;
251 });
252 triggerCellMouseEvent(col.triggerEvent, 2);
253 expect(arg1).toBe(col);
254 expect(arg2).toBe(2);
255 expect(arg3).toBe(true);
256 expect(arg4).toBe(store.getAt(2));
257 });
258
259 it("should not fire fire checkchange if beforecheckchange returns false", function() {
260 var called = false;
261
262 makeGrid();
263 col.on('checkchange', function() {
264 called = true;
265 });
266 col.on('beforecheckchange', function() {
267 return false;
268 });
269 triggerCellMouseEvent(col.triggerEvent, 2);
270 expect(called).toBe(false);
271 });
272 });
273
274 it("should toggle the record value", function() {
275 makeGrid();
276 triggerCellMouseEvent(col.triggerEvent, 0);
277 expect(store.getAt(0).get('val')).toBe(false);
278 expect(hasCls(getCellImg(0), 'x-grid-checkcolumn-checked')).toBe(false);
279 triggerCellMouseEvent(col.triggerEvent, 2);
280 expect(store.getAt(2).get('val')).toBe(true);
281 expect(hasCls(getCellImg(2), 'x-grid-checkcolumn-checked')).toBe(true);
282 });
283
284 it("should toggle when using property without a dataIndex", function() {
285 makeGrid([{
286 xtype: 'checkcolumn',
287 property: 'foo'
288 }], ['bar']);
289
290 triggerCellMouseEvent(col.triggerEvent, 0);
291 expect(store.getAt(0).foo).toBe(true);
292 });
293
294 it("should toggle the record value with invert: true", function() {
295 invert = true;
296 makeGrid();
297 invert = false;
298 triggerCellMouseEvent(col.triggerEvent, 0);
299 expect(store.getAt(0).get('val')).toBe(false);
300 expect(hasCls(getCellImg(0), 'x-grid-checkcolumn-checked')).toBe(true);
301 triggerCellMouseEvent(col.triggerEvent, 2);
302 expect(store.getAt(2).get('val')).toBe(true);
303 expect(hasCls(getCellImg(2), 'x-grid-checkcolumn-checked')).toBe(false);
304 });
305
306 it("should not trigger any changes when disabled", function() {
307 var cfg = getColCfg();
308
309 cfg.disabled = true;
310 makeGrid([cfg]);
311 triggerCellMouseEvent(col.triggerEvent, 0);
312 expect(store.getAt(0).get('val')).toBe(true);
313 triggerCellMouseEvent(col.triggerEvent, 2);
314 expect(store.getAt(2).get('val')).toBe(false);
315 });
316 });
317
318 describe('Header checkbox', function() {
319 beforeEach(function() {
320 var ready;
321
322 makeGrid([{
323 xtype: 'checkcolumn',
324 headerCheckbox: true,
325 text: 'Checked',
326 dataIndex: 'val',
327 listeners: {
328 headercheckchange: function() {
329 ready = true;
330 }
331 }
332 }]);
333
334 // Wait for the header state to be synched.
335 // This is done on animation frae, and there's no event.
336 waits(100);
337 });
338
339 it('should toggle all on header checkbox click', function() {
340 var headercheckchangeCount = 0;
341
342 col.on({
343 headercheckchange: function() {
344 headercheckchangeCount++;
345 }
346 });
347
348 // Test selecting all
349 clickHeader();
350 store.each(function(rec) {
351 expect(rec.get('val')).toBe(true);
352 });
353
354 // Header checkbox is updated on a timer for efficiency, so must wait
355 waitsFor(function() {
356 expect(headercheckchangeCount).toBe(1);
357
358 return col.el.hasCls(col.headerCheckedCls) === true;
359 });
360
361 runs(function() {
362 // Test deselecting all
363 clickHeader();
364 store.each(function(rec) {
365 expect(rec.get('val')).toBe(false);
366 });
367 });
368
369 // Header checkbox is updated on a timer for efficiency, so must wait
370 waitsFor(function() {
371 expect(headercheckchangeCount).toBe(2);
372
373 return col.el.hasCls(col.headerCheckedCls) === false;
374 });
375 });
376 it('should not toggle all on header checkbox click if the beforeheadercheckchange event is vetoed', function() {
377 var headercheckchangeCalled = false;
378
379 col.on({
380 beforeheadercheckchange: function() {
381 return false;
382 },
383 headercheckchange: function() {
384 headercheckchangeCalled = true;
385 }
386 });
387
388 // Test vetoing of selecting all
389 clickHeader();
390 store.each(function(rec) {
391 expect(rec.isModified('val')).toBe(false);
392 });
393
394 // Nothing should happen.
395 // We are expecting the header checkbox state to remain false
396 waits(100);
397
398 // The header must not have been updated to true because of the veto
399 runs(function() {
400 expect(headercheckchangeCalled).toBe(false);
401 expect(col.el.hasCls(col.headerCheckedCls)).toBe(false);
402 });
403 });
404
405 itNotIE9('should set the header checkbox when all rows are checked', function() {
406 var headercheckchangeCount = 0;
407
408 col.on({
409 headercheckchange: function() {
410 headercheckchangeCount++;
411 }
412 });
413
414 // Rows 2 and 4 are unchecked. Header should start unchecked.
415 expect(col.el.hasCls(col.headerCheckedCls)).toBe(false);
416
417 triggerCellMouseEvent('click', 2);
418
419 // Nothing should happen.
420 // We are expecting the header checkbox state to remain false
421 waits(100);
422
423 // The header must not have been updated to true because of the veto
424 runs(function() {
425 expect(headercheckchangeCount).toBe(0);
426 expect(col.el.hasCls(col.headerCheckedCls)).toBe(false);
427 triggerCellMouseEvent('click', 4);
428 });
429
430 // Header checkbox is updated on a timer for efficiency, so must wait
431 waitsFor(function() {
432 return col.el.hasCls(col.headerCheckedCls) === true;
433 }, 'column header to be checked');
434 });
435
436 itNotIE9('should clear the header checkbox when a new, unchecked record is added', function() {
437 var rowCount = view.all.getCount();
438
439 // Rows 2 and 4 are unchecked. Header should start unchecked.
440 expect(col.el.hasCls(col.headerCheckedCls)).toBe(false);
441
442 // Now all are selected
443 clickHeader();
444
445 // Header checkbox is updated on a timer for efficiency, so must wait
446 waitsFor(function() {
447 return col.el.hasCls(col.headerCheckedCls) === true;
448 });
449
450 // Add a record. This should cause the header checkbox to clear
451 runs(function() {
452 store.add({});
453 });
454
455 // Header checkbox is updated on a timer for efficiency, so must wait
456 waitsFor(function() {
457 return view.all.getCount() === rowCount + 1 &&
458 col.el.hasCls(col.headerCheckedCls) === false;
459 }, 'column header to be unchecked');
460 });
461
462 itNotIE9('should set the header checkbox when all records have the dataIndex field set', function() {
463 // Rows 2 and 4 are unchecked. Header should start unchecked.
464 expect(col.el.hasCls(col.headerCheckedCls)).toBe(false);
465
466 store.getAt(2).set('val', true);
467
468 // Nothing should happen.
469 // We are expecting the header checkbox state to remain false
470 waits(100);
471
472 runs(function() {
473 expect(col.el.hasCls(col.headerCheckedCls)).toBe(false);
474 store.getAt(4).set('val', true);
475 });
476
477 // Header checkbox is updated on a timer for efficiency, so must wait
478 waitsFor(function() {
479 return col.el.hasCls(col.headerCheckedCls) === true;
480 }, 'column header to be checked');
481 });
482 });
483
484 describe("aria", function() {
485 it("should not throw when committing", function() {
486 var cfg = getColCfg();
487
488 cfg.useAriaElements = true;
489 makeGrid([cfg]);
490 var rec = store.first(),
491 cell;
492
493 rec.commit();
494 cell = grid.getView().getCell(rec, col);
495 expect(cell.getAttribute('aria-describedby')).toBe(col.id + '-cell-description-selected');
496 rec.set('val', false);
497 cell = grid.getView().getCell(rec, col);
498 expect(cell.getAttribute('aria-describedby')).toBe(col.id + '-cell-description-not-selected');
499 });
500 });
501
502 describe("tips", function() {
503 function getTipEl(row) {
504 row = grid.getView().getRow(row);
505
506 return Ext.fly(row).down('.x-grid-cell', true);
507 }
508
509 describe("no tips", function() {
510 it("should not have tips during render", function() {
511 makeGrid(null, [{ val: true }, { val: false }]);
512 expect(getTipEl(0).hasAttribute('data-qtip')).toBe(false);
513 expect(getTipEl(1).hasAttribute('data-qtip')).toBe(false);
514 });
515
516 it("should not have tips after modifying values", function() {
517 makeGrid(null, [{ val: true }, { val: false }]);
518 store.getAt(0).set('val', false);
519 store.getAt(1).set('val', true);
520 expect(getTipEl(0).hasAttribute('data-qtip')).toBe(false);
521 expect(getTipEl(1).hasAttribute('data-qtip')).toBe(false);
522 });
523 });
524
525 describe("tooltip only", function() {
526 it("should only have tips on unchecked cells during render", function() {
527 makeGrid([getColCfg({
528 tooltip: 'foo'
529 })], [{ val: true }, { val: false }]);
530 expect(getTipEl(0).hasAttribute('data-qtip')).toBe(false);
531 expect(getTipEl(1).getAttribute('data-qtip')).toBe('foo');
532 });
533
534 it("should only have tips on unchecked cells after modifying values", function() {
535 makeGrid([getColCfg({
536 tooltip: 'foo'
537 })], [{ val: true }, { val: false }]);
538 store.getAt(0).set('val', false);
539 store.getAt(1).set('val', true);
540 expect(getTipEl(0).getAttribute('data-qtip')).toBe('foo');
541 expect(getTipEl(1).hasAttribute('data-qtip')).toBe(false);
542 });
543 });
544
545 describe("checkedTooltip only", function() {
546 it("should only have tips on checked cells during render", function() {
547 makeGrid([getColCfg({
548 checkedTooltip: 'foo'
549 })], [{ val: true }, { val: false }]);
550 expect(getTipEl(0).getAttribute('data-qtip')).toBe('foo');
551 expect(getTipEl(1).hasAttribute('data-qtip')).toBe(false);
552 });
553
554 it("should only have tips on checked cells after modifying values", function() {
555 makeGrid([getColCfg({
556 checkedTooltip: 'foo'
557 })], [{ val: true }, { val: false }]);
558 store.getAt(0).set('val', false);
559 store.getAt(1).set('val', true);
560 expect(getTipEl(0).hasAttribute('data-qtip')).toBe(false);
561 expect(getTipEl(1).getAttribute('data-qtip')).toBe('foo');
562 });
563 });
564
565 describe("both tips", function() {
566 it("should have tips on both cell types during render", function() {
567 makeGrid([getColCfg({
568 tooltip: 'foo',
569 checkedTooltip: 'bar'
570 })], [{ val: true }, { val: false }]);
571 expect(getTipEl(0).getAttribute('data-qtip')).toBe('bar');
572 expect(getTipEl(1).getAttribute('data-qtip')).toBe('foo');
573 });
574
575 it("should html encode tips during render", function() {
576 makeGrid([getColCfg({
577 tooltip: '<span>no</span>',
578 checkedTooltip: '<span>yes</span>'
579 })], [{ val: true }, { val: false }]);
580 expect(getTipEl(0).getAttribute('data-qtip')).toBe('<span>yes</span>');
581 expect(getTipEl(1).getAttribute('data-qtip')).toBe('<span>no</span>');
582 });
583
584 it("should have cells on both cell types after modifying values", function() {
585 makeGrid([getColCfg({
586 tooltip: 'foo',
587 checkedTooltip: 'bar'
588 })], [{ val: true }, { val: false }]);
589 store.getAt(0).set('val', false);
590 store.getAt(1).set('val', true);
591 expect(getTipEl(0).getAttribute('data-qtip')).toBe('foo');
592 expect(getTipEl(1).getAttribute('data-qtip')).toBe('bar');
593 });
594
595 it("should html encode tips after modifying values", function() {
596 makeGrid([getColCfg({
597 tooltip: '<span>no</span>',
598 checkedTooltip: '<span>yes</span>'
599 })], [{ val: true }, { val: false }]);
600 store.getAt(0).set('val', false);
601 store.getAt(1).set('val', true);
602 expect(getTipEl(0).getAttribute('data-qtip')).toBe('<span>no</span>');
603 expect(getTipEl(1).getAttribute('data-qtip')).toBe('<span>yes</span>');
604 });
605 });
606 });
607});