]> git.proxmox.com Git - extjs.git/blame - extjs/classic/classic/test/specs/grid/plugin/CellEditing.js
add extjs 6.0.1 sources
[extjs.git] / extjs / classic / classic / test / specs / grid / plugin / CellEditing.js
CommitLineData
6527f429
DM
1describe('Ext.grid.plugin.CellEditing', function () {\r
2 var store, plugin, grid, view, record, column, field,\r
3 TAB = 9,\r
4 synchronousLoad = true,\r
5 proxyStoreLoad = Ext.data.ProxyStore.prototype.load,\r
6 loadStore;\r
7\r
8 function makeGrid(pluginCfg, gridCfg, storeCfg, locked) {\r
9 store = new Ext.data.Store(Ext.apply({\r
10 fields: ['name', 'email', 'phone'],\r
11 data: [\r
12 {'name': 'Lisa', 'email': 'lisa@simpsons.com', 'phone': '555-111-1224', 'age': 14},\r
13 {'name': 'Bart', 'email': 'bart@simpsons.com', 'phone': '555-222-1234', 'age': 12},\r
14 {'name': 'Homer', 'email': 'homer@simpsons.com', 'phone': '555-222-1244', 'age': 44},\r
15 {'name': 'Marge', 'email': 'marge@simpsons.com', 'phone': '555-222-1254', 'age': 41}\r
16 ],\r
17 autoDestroy: true\r
18 }, storeCfg));\r
19\r
20 plugin = new Ext.grid.plugin.CellEditing(pluginCfg);\r
21\r
22 grid = new Ext.grid.Panel(Ext.apply({\r
23 columns: [\r
24 {header: 'Name', dataIndex: 'name', editor: 'textfield', locked: locked},\r
25 {header: 'Email', dataIndex: 'email', flex:1,\r
26 editor: {\r
27 xtype: 'textareafield',\r
28 allowBlank: false,\r
29 grow: true\r
30 }\r
31 },\r
32 {header: 'Phone', dataIndex: 'phone', editor: 'textfield'},\r
33 {header: 'Age', dataIndex: 'age', editor: 'textfield'}\r
34 ],\r
35 store: store,\r
36 selModel: 'cellmodel',\r
37 plugins: [plugin],\r
38 width: 200,\r
39 height: 400,\r
40 renderTo: Ext.getBody()\r
41 }, gridCfg));\r
42\r
43 view = grid.view;\r
44 }\r
45\r
46 function startEdit(recId, colId) {\r
47 record = store.getAt(recId || 0);\r
48 column = grid.columns[colId || 0];\r
49 plugin.startEdit(record, column);\r
50 field = column.field;\r
51 }\r
52\r
53 function triggerEditorKey(target, key) {\r
54 // Ext.supports.SpecialKeyDownRepeat changes the event Ext.form.field.Base listens for!\r
55 jasmine.fireKeyEvent(target, Ext.supports.SpecialKeyDownRepeat ? 'keydown' : 'keypress', key);\r
56 }\r
57\r
58 beforeEach(function() {\r
59 // Override so that we can control asynchronous loading\r
60 loadStore = Ext.data.ProxyStore.prototype.load = function() {\r
61 proxyStoreLoad.apply(this, arguments);\r
62 if (synchronousLoad) {\r
63 this.flushLoad.apply(this, arguments);\r
64 }\r
65 return this;\r
66 };\r
67\r
68 MockAjaxManager.addMethods();\r
69 });\r
70\r
71 afterEach(function() {\r
72 // Undo the overrides.\r
73 Ext.data.ProxyStore.prototype.load = proxyStoreLoad;\r
74\r
75 tearDown();\r
76 MockAjaxManager.removeMethods();\r
77 });\r
78\r
79 function tearDown() {\r
80 store = plugin = grid = view = record = column = field = Ext.destroy(grid);\r
81 }\r
82\r
83 describe('finding the cell editing plugin in a locking grid', function() {\r
84 beforeEach(function() {\r
85 makeGrid({pluginId:'test-cell-editing'}, null, null, true);\r
86 });\r
87\r
88 it('should find it by id', function() {\r
89 expect(grid.getPlugin('test-cell-editing')).toBe(plugin);\r
90 });\r
91 it('should find it by ptype', function() {\r
92 expect(grid.findPlugin('cellediting')).toBe(plugin);\r
93 });\r
94 });\r
95\r
96 describe('effect of hiding columns on cell editing selection', function () {\r
97 // These specs show that hiding columns pre- or post- cell edit will not place the x-grid-cell-selected class on the wrong\r
98 // cell in the wrong column when the row is updated since Ext.view.Table:renderCell is now looking up the cell context by\r
99 // header rather than by index. See EXTJSIV-11653.\r
100 var wasEdited = false,\r
101 columnManager, cell;\r
102\r
103 beforeEach(function () {\r
104 makeGrid({\r
105 listeners: {\r
106 edit: function (editor) {\r
107 wasEdited = true;\r
108 }\r
109 }\r
110 }, {\r
111 selType: 'cellmodel'\r
112 });\r
113\r
114 columnManager = grid.getColumnManager();\r
115 });\r
116\r
117 afterEach(function () {\r
118 wasEdited = false;\r
119 columnManager = null;\r
120 });\r
121\r
122 it('should give the edited cell the selected class after initially hiding columns', function () {\r
123 // First hide the columns.\r
124 columnManager.getColumns()[0].hide();\r
125 columnManager.getColumns()[1].hide();\r
126\r
127 // Then do the edit.\r
128 record = grid.store.getAt(0);\r
129 column = columnManager.getColumns()[2];\r
130 cell = grid.view.getCell(record, column);\r
131\r
132 jasmine.fireMouseEvent(cell, 'dblclick');\r
133 plugin.getEditor(record, column).setValue('111-111-1111');\r
134 plugin.completeEdit();\r
135\r
136 waitsFor(function () {\r
137 return wasEdited;\r
138 });\r
139\r
140 runs(function () {\r
141 // Finally show that the selected cell is in the correct column.\r
142 cell = Ext.fly(grid.view.getNode(record)).down('.x-grid-cell-selected');\r
143 expect(cell.hasCls('x-grid-cell-' + column.id)).toBe(true);\r
144 });\r
145 });\r
146\r
147 it('should move the selected cell along with its column when other columns are hidden', function () {\r
148 record = grid.store.getAt(0);\r
149 column = columnManager.columns[2];\r
150 cell = grid.view.getCell(record, column);\r
151\r
152 jasmine.fireMouseEvent(cell, 'dblclick');\r
153 plugin.getEditor(record, column).setValue('111-111-1111');\r
154 plugin.completeEdit();\r
155\r
156 waitsFor(function () {\r
157 return wasEdited;\r
158 });\r
159\r
160 runs(function () {\r
161 // First simply show that the selected cell is in the correct column.\r
162 cell = Ext.fly(grid.view.getNode(record)).down('.x-grid-cell-selected');\r
163 expect(cell.hasCls('x-grid-cell-' + column.id)).toBe(true);\r
164\r
165 columnManager.columns[0].hide();\r
166\r
167 // Now show that the selected cell is still in the correct column.\r
168 cell = Ext.fly(grid.view.getNode(record)).down('.x-grid-cell-selected');\r
169 expect(cell.hasCls('x-grid-cell-' + column.id)).toBe(true);\r
170 });\r
171 });\r
172 });\r
173\r
174 describe('events', function () {\r
175 var editorContext, cancelEditFired;\r
176\r
177 afterEach(function () {\r
178 editorContext = null;\r
179 });\r
180\r
181 describe('beforeedit', function () {\r
182 it('should retain changes to the editing context in the event handler', function () {\r
183 // See EXTJSIV-11643.\r
184 makeGrid({\r
185 listeners: {\r
186 beforeedit: function (editor, context) {\r
187 context.value = 'motley';\r
188 editorContext = context;\r
189 }\r
190 }\r
191 });\r
192\r
193 startEdit();\r
194\r
195 expect(editorContext.value).toBe('motley');\r
196 });\r
197 });\r
198\r
199 describe('canceledit', function () {\r
200 beforeEach(function () {\r
201\r
202 // Must wait for async focus events from previous suite to complete.\r
203 waits(10);\r
204 \r
205 runs(function() {\r
206 cancelEditFired = false;\r
207\r
208 makeGrid({\r
209 listeners: {\r
210 canceledit: function (editor, context) {\r
211 cancelEditFired = true;\r
212 editorContext = context;\r
213 }\r
214 }\r
215 });\r
216\r
217 startEdit();\r
218 });\r
219 });\r
220\r
221 it('should be able to get the original value when canceling the edit by the plugin', function() {\r
222 expect(plugin.editing).toBe(true);\r
223\r
224 // Note that the columnmove and columnresize events go through plugin.cancelEdit().\r
225 column.getEditor().setValue('baz');\r
226 plugin.cancelEdit();\r
227\r
228 expect(cancelEditFired).toBe(true);\r
229 expect(editorContext.originalValue).toBe('Lisa');\r
230 });\r
231\r
232 it('should be able to get the edited value when canceling the edit by the plugin', function() {\r
233 expect(plugin.editing).toBe(true);\r
234\r
235 // Note that the columnmove and columnresize events go through plugin.cancelEdit().\r
236 column.getEditor().setValue('foo');\r
237 plugin.cancelEdit();\r
238\r
239 expect(cancelEditFired).toBe(true);\r
240 expect(editorContext.value).toBe('foo');\r
241 });\r
242\r
243 it('should have different values for edited value and original value when canceling', function() {\r
244 expect(plugin.editing).toBe(true);\r
245\r
246 column.getEditor().setValue('foo');\r
247 plugin.cancelEdit();\r
248\r
249 expect(cancelEditFired).toBe(true);\r
250 expect(editorContext.value).not.toBe(editorContext.originalValue);\r
251 });\r
252\r
253 it('should be able to get the edited value when canceling the edit by the editor', function() {\r
254 expect(plugin.editing).toBe(true);\r
255\r
256 // Note that the canceledit event goes through editor.cancelEdit().\r
257 column.getEditor().setValue('bar');\r
258 plugin.getEditor(record, column).cancelEdit();\r
259\r
260 expect(cancelEditFired).toBe(true);\r
261 expect(editorContext.value).not.toBe(editorContext.originalValue);\r
262 expect(editorContext.value).toBe('bar');\r
263 });\r
264\r
265 describe('falsey values', function () {\r
266 it('should be able to capture falsey values when canceled by the plugin', function() {\r
267 expect(plugin.editing).toBe(true);\r
268\r
269 // Note that the columnmove and columnresize events go through plugin.cancelEdit().\r
270 column.getEditor().setValue('');\r
271 plugin.cancelEdit();\r
272\r
273 expect(cancelEditFired).toBe(true);\r
274 expect(editorContext.value).toBe('');\r
275 });\r
276\r
277 it('should be able to capture falsey values for the editedValue when canceled by the editor', function() {\r
278 expect(plugin.editing).toBe(true);\r
279\r
280 // Note that the canceledit event goes through editor.cancelEdit().\r
281 column.getEditor().setValue('');\r
282 plugin.getEditor(record, column).cancelEdit();\r
283\r
284 waitsFor(function() {\r
285 return cancelEditFired;\r
286 });\r
287 runs(function() {\r
288 expect(editorContext.value).toBe('');\r
289 });\r
290 });\r
291 });\r
292 });\r
293\r
294 describe('selecting ranges', function () {\r
295 // See EXTJS-16608.\r
296 var selModel;\r
297\r
298 function fireEvent(rowNum, eventName, shift) {\r
299 jasmine.fireMouseEvent(view.getNode(rowNum).getElementsByTagName('td')[0],eventName, null, null, null, !!shift);\r
300 }\r
301\r
302 function expectSelected(rec) {\r
303 var i, len;\r
304\r
305 if (arguments.length === 1) {\r
306 if (typeof rec == 'number') {\r
307 rec = store.getAt(rec);\r
308 }\r
309 expect(selModel.isSelected(rec)).toBe(true);\r
310 } else {\r
311 for (i = 0, len = arguments.length; i < len; ++i) {\r
312 expectSelected(arguments[i]);\r
313 }\r
314 }\r
315 }\r
316\r
317 afterEach(function () {\r
318 selModel = null;\r
319 });\r
320\r
321 function selectRange(eventName) {\r
322 describe('MULTI', function () {\r
323 beforeEach(function () {\r
324 makeGrid({\r
325 clicksToEdit: eventName === 'click' ? 1: 2\r
326 }, {\r
327 selModel: {\r
328 type: 'rowmodel',\r
329 mode: 'MULTI'\r
330 }\r
331 });\r
332\r
333 selModel = grid.selModel;\r
334 });\r
335\r
336 it('should select a range if we have a selection start point and shift is pressed', function () {\r
337 fireEvent(0, eventName);\r
338 fireEvent(3, eventName, true);\r
339 expectSelected(0, 1, 2, 3);\r
340 });\r
341\r
342 it('should maintain selection with a complex sequence', function() {\r
343 fireEvent(0, eventName);\r
344 expectSelected(0);\r
345 fireEvent(2, eventName, true);\r
346 expectSelected(0, 1, 2);\r
347 fireEvent(3, eventName);\r
348 expectSelected(3);\r
349 fireEvent(1, eventName, true);\r
350 expectSelected(1, 2, 3);\r
351\r
352 fireEvent(2, eventName);\r
353 expectSelected(2);\r
354 fireEvent(0, eventName, true);\r
355 expectSelected(0, 1, 2);\r
356 fireEvent(3, eventName, true);\r
357 expectSelected(2, 3);\r
358 });\r
359 });\r
360 }\r
361\r
362 selectRange('click');\r
363 selectRange('dblclick');\r
364 });\r
365 });\r
366\r
367 describe('sorting', function () {\r
368 it('should complete the edit when focusing the column', function () {\r
369 makeGrid();\r
370 startEdit();\r
371 column.focus();\r
372\r
373 expect(plugin.editing).toBe(false);\r
374 });\r
375 });\r
376\r
377 describe('making multiple selections with checkbox model', function () {\r
378 var store, selModel;\r
379\r
380 afterEach(function () {\r
381 store = selModel = null;\r
382 });\r
383\r
384 it('should keep existing selections when editing a cell in an previously-selected row', function () {\r
385 makeGrid(null, {\r
386 selModel: new Ext.selection.CheckboxModel({})\r
387 });\r
388\r
389 store = grid.store;\r
390 selModel = grid.selModel;\r
391\r
392 // Select all models in the store.\r
393 selModel.select(store.data.items);\r
394\r
395 // Now edit a cell.\r
396 startEdit(2);\r
397\r
398 // All the previous selections should still be selected.\r
399 expect(selModel.getSelection().length).toBe(store.data.length);\r
400 });\r
401\r
402 it('should expect that the correct records have been selected', function () {\r
403 var contains = Ext.Array.contains,\r
404 selections;\r
405\r
406 makeGrid(null, {\r
407 selModel: new Ext.selection.CheckboxModel({})\r
408 });\r
409\r
410 store = grid.store;\r
411 selModel = grid.selModel;\r
412\r
413 // Make some selections.\r
414 selModel.select([store.getAt(1), store.getAt(3)]);\r
415\r
416 // Now edit a cell in an unselected row.\r
417 // As of 5.0.1, it should NOT select, but should preserve existing MULTI selections: https://sencha.jira.com/browse/EXTJS-14472\r
418 startEdit();\r
419\r
420 selections = selModel.getSelection();\r
421\r
422 expect(contains(selections, store.getAt(0))).toBe(false);\r
423 expect(contains(selections, store.getAt(1))).toBe(true);\r
424 expect(contains(selections, store.getAt(2))).toBe(false);\r
425 expect(contains(selections, store.getAt(3))).toBe(true);\r
426 });\r
427\r
428 it('should keep existing selections when editing a cell in an unselected row', function () {\r
429 makeGrid(null, {\r
430 selModel: new Ext.selection.CheckboxModel({})\r
431 });\r
432\r
433 store = grid.store;\r
434 selModel = grid.selModel;\r
435\r
436 // Make some selections.\r
437 selModel.select([store.getAt(0), store.getAt(1)]);\r
438\r
439 // Now edit a cell in an unselected row.\r
440 // As of 5.0.1, it should NOT select, but should preserve existing MULTI selections: https://sencha.jira.com/browse/EXTJS-14472\r
441 startEdit(3, 0);\r
442\r
443 // The selections should now also include the row that contains the cell being edited.\r
444 expect(selModel.getSelection().length).toBe(2);\r
445 });\r
446 });\r
447\r
448 describe('setting value while remote querying', function () {\r
449 // These tests simulates a test case where a value is entered in the editor (either as .value or .rawValue) and then\r
450 // is tabbed out of the editor (and completing the edit) before the response returns and the combo store is loaded.\r
451 // See EXTJS-13127.\r
452 //\r
453 // There is a lot of coverage for combos, but we also needed to test the behavior of combos as cell editors. There have\r
454 // been bugs where raw values have been retained by the editor across tabs, i.e., if 'foo' is entered in the editor that\r
455 // same value will be retained as the user tabs through the grid (although this only seems to happen in grids where only\r
456 // a single column is editable, as tested below). Also, there have been bugs where the same editor value (.value) has been\r
457 // been written to each model as the user tabs (obviously not good). The following tests cover both of these scenarios.\r
458 //\r
459 // In addition, the tests cover what should happen if a value or raw value is set prior to or during the combo store load,\r
460 // both when forceSelection is on and off. In either case (of forceSelection), we have decided that the value should be\r
461 // allowed because the combo store hasn't been loaded yet. The contract with forceSelection is with the combo store, and if\r
462 // the user chooses to enter a value before said store is loaded then we cannot do anything about that as we cannot look\r
463 // anything up.\r
464\r
465 var comboStore, ed;\r
466\r
467 function createUI(forceSelection) {\r
468 comboStore = new Ext.data.Store({\r
469 fields: ['id', 'state', 'nickname'],\r
470 proxy: {\r
471 type: 'ajax',\r
472 url: 'fake',\r
473 reader: {\r
474 type: 'array'\r
475 }\r
476 }\r
477 });\r
478\r
479 makeGrid(null, {\r
480 columns: [{\r
481 header: 'State',\r
482 dataIndex: 'id',\r
483 renderer: function (value, metaData, record) {\r
484 return record.get('state');\r
485 },\r
486 editor: {\r
487 xtype: 'combo',\r
488 store: comboStore,\r
489 queryMode: 'remote',\r
490 typeAhead: true,\r
491 minChars: 2,\r
492 displayField: 'state',\r
493 valueField: 'id',\r
494 forceSelection: forceSelection\r
495 }\r
496 }]\r
497 }, {\r
498 fields: ['id', 'state', 'nickname'],\r
499 data: [\r
500 ['AL', 'Alabama', 'The Heart of Dixie'],\r
501 ['AK', 'Alaska', 'The Land of the Midnight Sun'],\r
502 ['AR', 'Arkansas', 'The Natural State'],\r
503 ['AZ', 'Arizona', 'The Grand Canyon State']\r
504 ],\r
505 proxy: {\r
506 type: 'memory',\r
507 reader: {\r
508 type: 'array'\r
509 }\r
510 }\r
511 });\r
512 }\r
513\r
514 describe('only one editable column', function () {\r
515 function initiateTests(expectation, loadStore) {\r
516 describe(expectation, function () {\r
517 function forceSelection(force) {\r
518 describe('forceSelection = ' + force, function () {\r
519 beforeEach(function () {\r
520 createUI(force);\r
521 });\r
522\r
523 afterEach(function () {\r
524 Ext.destroy(comboStore);\r
525 comboStore = ed = null;\r
526 });\r
527\r
528 function setup(force, method) {\r
529 // Initiate the edit.\r
530 jasmine.fireMouseEvent(grid.view.getNode(store.getAt(0)).getElementsByTagName('td')[0], 'dblclick');\r
531 ed = plugin.getActiveEditor();\r
532\r
533 if (loadStore) {\r
534 comboStore.load();\r
535 }\r
536\r
537\r
538 // Simulate the load which happens when text is typed into the editor.\r
539 // Let's then tab out to complete the edit.\r
540 if (method === 'setRawValue') {\r
541 ed.field.setRawValue('ben');\r
542 } else {\r
543 ed.setValue('ben');\r
544 }\r
545\r
546 jasmine.fireKeyEvent(ed.field.inputEl, 'keydown', 9);\r
547 }\r
548\r
549 function setValue(raw) {\r
550 var method = raw ? 'setRawValue' : 'setValue';\r
551\r
552 describe(method, function () {\r
553 it('should write the value to the model', function () {\r
554 var val = 'ben';\r
555\r
556 setup(force, method);\r
557\r
558 if (force && method === 'setRawValue') {\r
559 val = 'AL';\r
560 }\r
561\r
562 record = store.getAt(0);\r
563 expect(record.get('id')).toBe(val);\r
564 expect(record.get('state')).toBe('Alabama');\r
565 });\r
566\r
567 it('should not set any other fields in the model across tabs', function () {\r
568 // There have been bugs which caused the same value to be set in different models across tabs.\r
569 setup(force, method);\r
570\r
571 record = store.getAt(1);\r
572 expect(record.get('id')).toBe('AK');\r
573 expect(record.get('state')).toBe('Alaska');\r
574\r
575 record = store.getAt(2);\r
576 jasmine.fireKeyEvent(ed.field.inputEl, 'keydown', 9);\r
577 expect(record.get('state')).toBe('Arkansas');\r
578 expect(record.get('nickname')).toBe('The Natural State');\r
579\r
580 record = store.getAt(3);\r
581 jasmine.fireKeyEvent(ed.field.inputEl, 'keydown', 9);\r
582 expect(record.get('state')).toBe('Arizona');\r
583 expect(record.get('nickname')).toBe('The Grand Canyon State');\r
584 });\r
585\r
586 it('should give the editor different values across tabs', function () {\r
587 // There have been bugs which caused the editor to keep the same value across tabs.\r
588 setup(force, method);\r
589\r
590 // It should not propagate the user-inputted value.\r
591\r
592 // Let's make sure the editor has the correct value...\r
593 expect(ed.getValue()).toBe('AK');\r
594 expect(ed.field.getRawValue()).toBe('');\r
595\r
596 jasmine.fireKeyEvent(ed.field.inputEl, 'keydown', 9);\r
597 expect(ed.getValue()).toBe('AR');\r
598\r
599 jasmine.fireKeyEvent(ed.field.inputEl, 'keydown', 9);\r
600 expect(ed.getValue()).toBe('AZ');\r
601 });\r
602\r
603 it('should not give the editor a raw value because the combo store has not been loaded', function () {\r
604 // There have been bugs which caused the editor to keep the same raw value across tabs.\r
605 setup(force, method);\r
606\r
607 expect(ed.field.getRawValue()).toBe('');\r
608\r
609 jasmine.fireKeyEvent(ed.field.inputEl, 'keydown', 9);\r
610 expect(ed.field.getRawValue()).toBe('');\r
611\r
612 jasmine.fireKeyEvent(ed.field.inputEl, 'keydown', 9);\r
613 expect(ed.field.getRawValue()).toBe('');\r
614 });\r
615 });\r
616 }\r
617\r
618 setValue(false);\r
619 setValue(true);\r
620 });\r
621 }\r
622\r
623 forceSelection(false);\r
624 forceSelection(true);\r
625 });\r
626 }\r
627\r
628 initiateTests('before store load is initiated', false);\r
629 initiateTests('while store is loading', true);\r
630\r
631 describe('when tabbing (down/up to the contiguous row)', function () {\r
632 var activeEditor;\r
633\r
634 beforeEach(function () {\r
635 makeGrid({\r
636 clicksToEdit: 1\r
637 }, {\r
638 columns: [\r
639 {header: 'Name', dataIndex: 'name', editor: 'textfield'},\r
640 {header: 'Email', dataIndex: 'email', flex:1},\r
641 {header: 'Phone', dataIndex: 'phone'},\r
642 {header: 'Age', dataIndex: 'age'}\r
643 ],\r
644 selModel: 'rowmodel'\r
645 });\r
646\r
647 startEdit();\r
648\r
649 activeEditor = plugin.activeEditor;\r
650\r
651 // Spy on afterHide to count *successful* hides.\r
652 // hide may be called when already hidden during CellEditing tabbing sequence.\r
653 spyOn(activeEditor, 'afterHide').andCallThrough();\r
654\r
655 jasmine.fireKeyEvent(column.field.inputEl, 'keydown', 9);\r
656 });\r
657\r
658 afterEach(function () {\r
659 activeEditor = null;\r
660 });\r
661\r
662 it('should not complete', function () {\r
663 expect(activeEditor).not.toBe(null);\r
664 expect(plugin.activeColumn).not.toBe(null);\r
665 expect(plugin.activeRecord).not.toBe(null);\r
666 });\r
667\r
668 it('should hide the editor', function () {\r
669 expect(activeEditor).not.toBe(null);\r
670 expect(activeEditor.isVisible()).toBe(true);\r
671\r
672 // CellEditing is just part of actionable mode.\r
673 // Actionable mode does not know that you are going to focus to the same editor.\r
674 // It just desctivates the old row, activates the new row, and focuses the first tabbable element.\r
675 // Deactivating a row will hide the editors.\r
676 // So the "name" editor will have been hidden when that row was deactivated.\r
677 expect(activeEditor.afterHide.callCount).toBe(1);\r
678 });\r
679 });\r
680 });\r
681 });\r
682\r
683 describe('clicksToEdit', function () {\r
684 describe('2 clicks', function () {\r
685 beforeEach(function () {\r
686 makeGrid();\r
687 });\r
688\r
689 it('should default to 2', function () {\r
690 expect(plugin.clicksToEdit).toBe(2);\r
691 });\r
692\r
693 it('should begin editing when double-clicked', function () {\r
694 record = grid.store.getAt(0);\r
695 node = grid.view.getNodeByRecord(record);\r
696 jasmine.fireMouseEvent(Ext.fly(node).down('.x-grid-cell'), 'dblclick');\r
697\r
698 expect(plugin.activeEditor).not.toBeFalsy();\r
699 });\r
700\r
701 it('should not begin editing when single-clicked', function () {\r
702 record = grid.store.getAt(0);\r
703 node = grid.view.getNodeByRecord(record);\r
704 jasmine.fireMouseEvent(Ext.fly(node).down('.x-grid-cell'), 'click');\r
705\r
706 expect(plugin.activeEditor).toBeFalsy();\r
707 });\r
708\r
709 describe('editing a new cell', function () {\r
710 var cells, boundEl;\r
711\r
712 afterEach(function () {\r
713 cells = boundEl = null;\r
714 });\r
715\r
716 it('should update the activeEditor to point to the new cell, adjacent', function () {\r
717 record = grid.store.getAt(0);\r
718 node = grid.view.getNodeByRecord(record);\r
719 cells = Ext.fly(node).query('.x-grid-cell');\r
720\r
721 boundEl = cells[0];\r
722 jasmine.fireMouseEvent(boundEl, 'dblclick');\r
723\r
724 expect(plugin.activeEditor.boundEl.dom).toBe(boundEl);\r
725\r
726 // Update the boundEl to our new cell.\r
727 boundEl = cells[1];\r
728 jasmine.fireMouseEvent(boundEl, 'dblclick');\r
729\r
730 expect(plugin.activeEditor.boundEl.dom).toBe(boundEl);\r
731 });\r
732\r
733 it('should update the activeEditor to point to the new cell, below', function () {\r
734 record = grid.store.getAt(0);\r
735 node = grid.view.getNodeByRecord(record);\r
736 boundEl = Ext.fly(node).down('.x-grid-cell').dom;\r
737\r
738 jasmine.fireMouseEvent(boundEl, 'dblclick');\r
739\r
740 expect(plugin.activeEditor.boundEl.dom).toBe(boundEl);\r
741\r
742 record = grid.store.getAt(1);\r
743 node = grid.view.getNodeByRecord(record);\r
744\r
745 // Update the boundEl to our new cell.\r
746 boundEl = Ext.fly(node).down('.x-grid-cell').dom;\r
747\r
748 jasmine.fireMouseEvent(boundEl, 'dblclick');\r
749\r
750 expect(plugin.activeEditor.boundEl.dom).toBe(boundEl);\r
751 });\r
752 });\r
753 });\r
754\r
755 describe('1 click', function () {\r
756 beforeEach(function () {\r
757 makeGrid({\r
758 clicksToEdit: 1\r
759 });\r
760 });\r
761\r
762 it('should honor a different number than the default', function () {\r
763 expect(plugin.clicksToEdit).toBe(1);\r
764 });\r
765\r
766 it('should begin editing when single-clicked', function () {\r
767 record = grid.store.getAt(0);\r
768 node = grid.view.getNodeByRecord(record);\r
769 jasmine.fireMouseEvent(Ext.fly(node).down('.x-grid-cell'), 'click');\r
770\r
771 expect(plugin.activeEditor).not.toBeFalsy();\r
772 });\r
773\r
774 // Note: I'm disabling this for IE b/c certain versions (esp. 10 & 11) could not distinguish\r
775 // between single- and double-click.\r
776 if (!Ext.isIE) {\r
777 it('should not begin editing when double-clicked', function () {\r
778 record = grid.store.getAt(0);\r
779 node = grid.view.getNodeByRecord(record);\r
780 jasmine.fireMouseEvent(Ext.fly(node).down('.x-grid-cell'), 'dblclick');\r
781\r
782 expect(plugin.activeEditor).toBeFalsy();\r
783 });\r
784 }\r
785\r
786 describe('editing a new cell', function () {\r
787 var cells, boundEl;\r
788\r
789 afterEach(function () {\r
790 cells = boundEl = null;\r
791 });\r
792\r
793 it('should update the activeEditor to point to the new cell, adjacent', function () {\r
794 record = grid.store.getAt(0);\r
795 node = grid.view.getNodeByRecord(record);\r
796 cells = Ext.fly(node).query('.x-grid-cell');\r
797\r
798 boundEl = cells[0];\r
799 jasmine.fireMouseEvent(boundEl, 'click');\r
800\r
801 expect(plugin.activeEditor.boundEl.dom).toBe(boundEl);\r
802\r
803 // Update the boundEl to our new cell.\r
804 boundEl = cells[1];\r
805 jasmine.fireMouseEvent(boundEl, 'click');\r
806\r
807 expect(plugin.activeEditor.boundEl.dom).toBe(boundEl);\r
808 });\r
809\r
810 it('should update the activeEditor to point to the new cell, below', function () {\r
811 record = grid.store.getAt(0);\r
812 node = grid.view.getNodeByRecord(record);\r
813 boundEl = Ext.fly(node).down('.x-grid-cell').dom;\r
814\r
815 jasmine.fireMouseEvent(boundEl, 'click');\r
816\r
817 expect(plugin.activeEditor.boundEl.dom).toBe(boundEl);\r
818\r
819 record = grid.store.getAt(1);\r
820 node = grid.view.getNodeByRecord(record);\r
821\r
822 // Update the boundEl to our new cell.\r
823 boundEl = Ext.fly(node).down('.x-grid-cell').dom;\r
824\r
825 jasmine.fireMouseEvent(boundEl, 'click');\r
826\r
827 expect(plugin.activeEditor.boundEl.dom).toBe(boundEl);\r
828 });\r
829 });\r
830 });\r
831 });\r
832\r
833 describe('the CellEditor', function () {\r
834 beforeEach(function () {\r
835 makeGrid();\r
836 startEdit();\r
837 });\r
838\r
839 it('should get an ownerCmp reference to the grid', function () {\r
840 waitsFor(function() {\r
841 return plugin.activeEditor && plugin.activeEditor.ownerCmp === grid;\r
842 });\r
843 });\r
844\r
845 it('should be able to lookup up its owner in the component hierarchy chain', function () {\r
846 waitsFor(function() {\r
847 return plugin.activeEditor && plugin.activeEditor.up('grid') === grid;\r
848 });\r
849 });\r
850\r
851 describe('positioning the editor', function () {\r
852 it('should default to "l-l!"', function () {\r
853 field = column.field;\r
854\r
855 expect(field.xtype).toBe('textfield');\r
856 waitsFor(function() {\r
857 return plugin.activeEditor && plugin.activeEditor.alignment === 'l-l!';\r
858 });\r
859 });\r
860\r
861 it('should constrain to the view if the editor goes out of bounds', function () {\r
862 // Wait for the beforeEach's startEdit to get started\r
863 waitsFor(function() {\r
864 return plugin.activeEditor && plugin.activeEditor.field.hasFocus;\r
865 }, 'editor to focus', 1000);\r
866\r
867 // Need to be able to correctly startEdit while editing to move edit location\r
868 runs(function() {\r
869 startEdit(0, 1);\r
870 });\r
871\r
872 waitsFor(function() {\r
873 return field.hasFocus && field.getRegion().top === Ext.fly(plugin.activeEditor.container).getRegion().top;\r
874 }, 'something funky to happen', 1000);\r
875 });\r
876\r
877 it('should not reposition when shown', function () {\r
878 plugin.completeEdit();\r
879\r
880 spyOn(Ext.AbstractComponent.prototype, 'setPosition');\r
881\r
882 startEdit(0, 1);\r
883\r
884 expect(plugin.activeEditor.setPosition).not.toHaveBeenCalled();\r
885 });\r
886\r
887 it('should not reposition when within a draggable container', function () {\r
888 // See EXTJS-15532.\r
889 var win;\r
890\r
891 tearDown();\r
892\r
893 makeGrid(null, {\r
894 renderTo: null\r
895 });\r
896\r
897 win = new Ext.window.Window({\r
898 items: grid\r
899 }).show();\r
900\r
901 startEdit();\r
902\r
903 spyOn(plugin.activeEditor, 'setPosition');\r
904\r
905 jasmine.fireMouseEvent(win.el.dom, 'mousedown');\r
906 jasmine.fireMouseEvent(win.el.dom, 'mousemove', win.x, win.y);\r
907 jasmine.fireMouseEvent(win.el.dom, 'mousemove', (win.x - 100), (win.y - 100));\r
908 jasmine.fireMouseEvent(win.el.dom, 'mouseup', 400);\r
909\r
910 expect(plugin.activeEditor.setPosition).not.toHaveBeenCalled();\r
911\r
912 win.destroy();\r
913 });\r
914 });\r
915\r
916 describe('as textfield', function () {\r
917 it('should start the edit when ENTER is pressed', function () {\r
918 var node = view.body.query('td', true)[0];\r
919\r
920 // Wait for the beforeEach's startEdit to take effect\r
921 waitsFor(function() {\r
922 return plugin.activeEditor && plugin.activeEditor.field.hasFocus;\r
923 }, 'beforeEach startEdit to take effect');\r
924\r
925 // First complete the edit (we start an edit in the top-level beforeEach).\r
926 runs(function() {\r
927 grid.setActionableMode(false);\r
928 });\r
929\r
930 // Wait for it to clear itself up and focus to return to the cell\r
931 waitsFor(function() {\r
932 return plugin.activeEditor == null && plugin.editing === false && Ext.Element.getActiveElement() === node;\r
933 }, 'actionable mode to end and cell to regain focus');\r
934\r
935 runs(function() {\r
936 jasmine.fireKeyEvent(node, 'keydown', 13);\r
937 });\r
938 \r
939 waitsFor(function() {\r
940 return plugin.activeEditor && plugin.editing === true;\r
941 }, 'editing to start on the focused cell');\r
942 });\r
943\r
944 describe('when currently editing', function() {\r
945 it('should complete the edit when ENTER is pressed', function() {\r
946 var str = 'Utley is Top Dog',\r
947 model = store.getAt(0);\r
948\r
949 expect(model.get('name')).toBe('Lisa');\r
950 field.setValue(str);\r
951\r
952 jasmine.fireKeyEvent(field.inputEl.dom, 'keydown', 13);\r
953\r
954 waitsFor(function() {\r
955 return model.get('name') === str;\r
956 }, 'model to be set', 1000);\r
957\r
958 runs(function() {\r
959 expect(model.get('name')).toBe(str);\r
960 });\r
961 });\r
962\r
963 it('should cancel the edit when ESCAPE is pressed', function() {\r
964 jasmine.pressKey(field, 'esc');\r
965\r
966 waitsFor(function() {\r
967 return !plugin.editing;\r
968 }, 'editing to stop', 1000);\r
969\r
970 runs(function() {\r
971 expect(plugin.editing).toBe(false);\r
972 });\r
973 });\r
974 });\r
975 });\r
976\r
977 describe('as textarea', function () {\r
978 beforeEach(function () {\r
979 startEdit(0, 1);\r
980 });\r
981\r
982 it('should start the edit when ENTER is pressed', function () {\r
983 var node = view.body.query('td', true)[1];\r
984\r
985 // Wait for the beforeEach's startEdit to take effect\r
986 waitsFor(function() {\r
987 return plugin.activeEditor && plugin.activeEditor.field.hasFocus && view.actionableMode === true;\r
988 }, 'beforeEach startEdit to take effect');\r
989\r
990 // First complete the edit (we start an edit in the top-level beforeEach).\r
991 runs(function() {\r
992 grid.setActionableMode(false);\r
993 });\r
994\r
995 // Wait for it to clear itself up and focus to return to the cell\r
996 waitsFor(function() {\r
997 return plugin.activeEditor == null && plugin.editing === false && Ext.Element.getActiveElement() === node;\r
998 }, 'actionable mode to end and cell to regain focus');\r
999\r
1000 runs(function() {\r
1001 jasmine.fireKeyEvent(node, 'keydown', 13);\r
1002 });\r
1003 \r
1004 waitsFor(function() {\r
1005 return plugin.activeEditor && plugin.editing === true;\r
1006 }, 'editing to start on the focused cell');\r
1007 });\r
1008\r
1009 describe('when currently editing', function () {\r
1010 it('should not complete the edit when ENTER is pressed', function () {\r
1011 spyOn(plugin, 'completeEdit');\r
1012\r
1013 // Wait for the beforeEach's startEdit to take effect\r
1014 waitsFor(function() {\r
1015 return plugin.activeEditor && plugin.activeEditor.field.hasFocus;\r
1016 }, 'beforeEach startEdit to take effect');\r
1017\r
1018 // First complete the edit (we start an edit in the top-level beforeEach).\r
1019 runs(function() {\r
1020 triggerEditorKey(field.inputEl, 13);\r
1021\r
1022 expect(plugin.completeEdit).not.toHaveBeenCalled();\r
1023 });\r
1024 });\r
1025\r
1026 it('should not cancel the edit when ENTER is pressed', function () {\r
1027 spyOn(plugin, 'cancelEdit');\r
1028\r
1029 // Wait for the beforeEach's startEdit to take effect\r
1030 waitsFor(function() {\r
1031 return plugin.activeEditor && plugin.activeEditor.field.hasFocus;\r
1032 }, 'beforeEach startEdit to take effect');\r
1033\r
1034 // First complete the edit (we start an edit in the top-level beforeEach).\r
1035 runs(function() {\r
1036 triggerEditorKey(field.inputEl, 13);\r
1037\r
1038 expect(plugin.cancelEdit).not.toHaveBeenCalled();\r
1039 });\r
1040 });\r
1041\r
1042 it('should cancel the edit when ESCAPE is pressed', function () {\r
1043 spyOn(plugin, 'cancelEdit');\r
1044\r
1045 // Wait for the beforeEach's startEdit to take effect\r
1046 waitsFor(function() {\r
1047 return plugin.activeEditor && plugin.activeEditor.field.hasFocus;\r
1048 }, 'beforeEach startEdit to take effect');\r
1049\r
1050 // First complete the edit (we start an edit in the top-level beforeEach).\r
1051 runs(function() {\r
1052 triggerEditorKey(field.inputEl, 27);\r
1053 });\r
1054\r
1055 waitsFor(function () {\r
1056 return !plugin.editing;\r
1057 }, 'ESC keydown to have terminated editing');\r
1058\r
1059 runs(function () {\r
1060 expect(plugin.editing).toBe(false);\r
1061 });\r
1062 });\r
1063\r
1064 describe('grow and auto-sizing', function () {\r
1065 var str = 'Attention all planets of the Solar Federation!\nAttention all planets of the Solar Federation!\nWe have assumed control!';\r
1066\r
1067 it('should auto-size when written to', function () {\r
1068 spyOn(field, 'autoSize');\r
1069\r
1070 field.setValue(str);\r
1071\r
1072 expect(field.autoSize).toHaveBeenCalled();\r
1073 });\r
1074\r
1075 it('should grow', function () {\r
1076 var previousHeight = field.getHeight();\r
1077\r
1078 field.setValue(str);\r
1079\r
1080 expect(field.getHeight()).toBeGreaterThan(previousHeight);\r
1081 });\r
1082 });\r
1083 });\r
1084 });\r
1085 });\r
1086\r
1087 describe('key mappings', function () {\r
1088 it('should not stop propagation on the enter key', function () {\r
1089 var EM = Ext.EventManager;\r
1090\r
1091 spyOn(EM, 'stopPropagation');\r
1092 spyOn(EM, 'preventDefault');\r
1093\r
1094 makeGrid();\r
1095 startEdit(0, 1);\r
1096\r
1097 triggerEditorKey(column.field.inputEl, 13);\r
1098\r
1099 expect(EM.stopPropagation).not.toHaveBeenCalled();\r
1100 expect(EM.preventDefault).not.toHaveBeenCalled();\r
1101 });\r
1102 });\r
1103\r
1104 describe('in a collapsed container', function () {\r
1105 // To reproduce the bug:\r
1106 // 1. Start edit\r
1107 // 2. Collapse the fieldset\r
1108 // 3. Create the new editor (or any component that contains an editor)\r
1109 // 4. Show the fieldset\r
1110 // 5. Try to start edit\r
1111 //\r
1112 // See EXTJS-12752.\r
1113 var fieldset, editor_1, editor_2;\r
1114\r
1115 beforeEach(function () {\r
1116 fieldset = new Ext.form.FieldSet({\r
1117 collapsible: true,\r
1118 items: makeGrid({\r
1119 renderTo: null\r
1120 }),\r
1121 width: 500,\r
1122 renderTo: Ext.getBody()\r
1123 });\r
1124\r
1125 startEdit();\r
1126 });\r
1127\r
1128 afterEach(function () {\r
1129 Ext.destroy(fieldset, editor_1, editor_2);\r
1130 fieldset = editor_1 = editor_2 = null;\r
1131 });\r
1132\r
1133 it('should not set its hierarchicallyHidden property in response to any hierarchyEvents', function () {\r
1134 waitsFor(function() {\r
1135 return (editor_1 = plugin.activeEditor) && editor_1.field.hasFocus;\r
1136 }, 'editing to start');\r
1137 \r
1138 runs(function() {\r
1139\r
1140 // We have to fake a blur here.\r
1141 plugin.completeEdit();\r
1142\r
1143 fieldset.toggle();\r
1144\r
1145 editor_2 = new Ext.grid.CellEditor({\r
1146 field: 'textfield',\r
1147 renderTo: Ext.getBody()\r
1148 });\r
1149\r
1150 fieldset.toggle();\r
1151\r
1152 plugin.startEdit(record, column);\r
1153 });\r
1154\r
1155 waitsFor(function() {\r
1156 return editor_1.hidden === false;\r
1157 }, 'editor_1 to show');\r
1158\r
1159 runs(function() {\r
1160 expect(editor_1.hierarchicallyHidden).toBe(false);\r
1161 });\r
1162 });\r
1163\r
1164 it('should show the CellEditor when the edit is started', function () {\r
1165 waitsFor(function() {\r
1166 return (editor_1 = plugin.activeEditor) && editor_1.field.hasFocus;\r
1167 }, 'editing to start');\r
1168 \r
1169 runs(function() {\r
1170\r
1171 // We have to fake a blur here.\r
1172 plugin.completeEdit();\r
1173\r
1174 fieldset.toggle();\r
1175\r
1176 editor_2 = new Ext.grid.CellEditor({\r
1177 field: 'textfield',\r
1178 renderTo: Ext.getBody()\r
1179 });\r
1180\r
1181 fieldset.toggle();\r
1182\r
1183 plugin.startEdit(record, column);\r
1184 });\r
1185\r
1186 waitsFor(function() {\r
1187 return editor_1.hidden === false;\r
1188 }, 'editor_1 to show');\r
1189 });\r
1190 });\r
1191\r
1192 describe('selectOnFocus', function () {\r
1193 // I could not get the following spec to pass in the following browsers, although the test case does work.\r
1194 // The dom.select() method in FF seems to be asynchronous (possibly for Opera as well), and IE 11 always\r
1195 // returned an empty string for the text selection even though it claims to support window.getSelection().\r
1196 ((Ext.isGecko || Ext.isOpera || Ext.isIE11) ? xit : it)('should select the text in the cell when initiating an edit', function () {\r
1197 // See EXTJS-12364.\r
1198 var node;\r
1199\r
1200 function getSelectionText() {\r
1201 var text;\r
1202\r
1203 if (!Ext.isIE) {\r
1204 text = window.getSelection().toString();\r
1205 } else if (document.selection) {\r
1206 text = document.selection.createRange().text;\r
1207 }\r
1208\r
1209 return text;\r
1210 }\r
1211\r
1212 makeGrid(null, {\r
1213 columns: [\r
1214 {header: 'Name', dataIndex: 'name',\r
1215 editor: {\r
1216 xtype: 'textfield',\r
1217 selectOnFocus: true\r
1218 }\r
1219 },\r
1220 {header: 'Email', dataIndex: 'email', flex:1,\r
1221 editor: {\r
1222 xtype: 'textfield',\r
1223 selectOnFocus: true\r
1224 }\r
1225 },\r
1226 {header: 'Phone', dataIndex: 'phone', editor: 'textfield'},\r
1227 {header: 'Age', dataIndex: 'age', editor: 'textfield'}\r
1228 ]\r
1229 });\r
1230\r
1231 node = grid.view.getNode(grid.store.getAt(1));\r
1232 jasmine.fireMouseEvent(node.getElementsByTagName('td')[0], 'dblclick');\r
1233\r
1234 expect(getSelectionText()).toBe('Bart');\r
1235 });\r
1236 });\r
1237\r
1238 describe('not completing the edit', function () {\r
1239 beforeEach(function() {\r
1240\r
1241 // Must wait for async focus events from previous suite to complete.\r
1242 waits(10);\r
1243 });\r
1244 it('should preserve the correct editing context', function () {\r
1245 var listener = function () {\r
1246 return false;\r
1247 }, ed, context;\r
1248\r
1249 makeGrid(null, {\r
1250 columns: [\r
1251 {header: 'Name', dataIndex: 'name',\r
1252 editor: {\r
1253 xtype: 'textfield',\r
1254 selectOnFocus: true\r
1255 }\r
1256 },\r
1257 {header: 'Email', dataIndex: 'email', flex:1,\r
1258 editor: {\r
1259 xtype: 'textfield',\r
1260 selectOnFocus: true\r
1261 }\r
1262 },\r
1263 {header: 'Phone', dataIndex: 'phone', editor: 'textfield'},\r
1264 {header: 'Age', dataIndex: 'age', editor: 'textfield'}\r
1265 ]\r
1266 });\r
1267\r
1268 startEdit(0, 1);\r
1269 waitsFor(function() {\r
1270 ed = plugin.activeEditor;\r
1271 return !!ed;\r
1272 }, 'editing to start at cell(0, 1)');\r
1273 runs(function() {\r
1274 context = plugin.context;\r
1275\r
1276 ed.on('beforecomplete', listener);\r
1277 ed.setValue('derp');\r
1278 // Cancel edit.\r
1279 triggerEditorKey(ed.field.inputEl, 27);\r
1280\r
1281 expect(plugin.context).toBe(context);\r
1282 });\r
1283 });\r
1284 });\r
1285\r
1286 describe('operations that refresh the view', function () {\r
1287 var ed;\r
1288\r
1289 afterEach(function () {\r
1290 ed = null;\r
1291 });\r
1292\r
1293 describe('when editing and tabbing', function () {\r
1294 function doIt(autoSync) {\r
1295 it('should not complete the edit in the new position, autoSync ' + autoSync, function () {\r
1296 makeGrid(null, null, {\r
1297 autoSync: autoSync\r
1298 });\r
1299\r
1300 record = grid.store.getAt(0);\r
1301 column = grid.columns[0];\r
1302\r
1303 plugin.startEdit(record, column);\r
1304 ed = plugin.activeEditor;\r
1305 ed.setValue('Pete the Dog was here');\r
1306\r
1307 // Now let's tab and check that the editor is still shown and active.\r
1308 jasmine.fireKeyEvent(ed.field.inputEl, 'keydown', 9);\r
1309\r
1310 waitsFor(function () {\r
1311 return !!plugin.activeEditor.editing;\r
1312 }, 'editing to start', 1000);\r
1313\r
1314 runs(function () {\r
1315 // ed is the old editor\r
1316 expect(ed.editing).toBe(false);\r
1317 expect(plugin.activeEditor.editing).toBe(true);\r
1318 expect(plugin.activeColumn.dataIndex).toBe('email');\r
1319 });\r
1320 });\r
1321 }\r
1322\r
1323 doIt(true);\r
1324 doIt(false);\r
1325 });\r
1326\r
1327 describe('when editing and syncing', function () {\r
1328 it('should not complete the edit in the current position', function () {\r
1329 makeGrid();\r
1330\r
1331 record = grid.store.getAt(0);\r
1332 column = grid.columns[0];\r
1333\r
1334 plugin.startEdit(record, column);\r
1335 ed = plugin.activeEditor;\r
1336 ed.setValue('Pete the Dog was here');\r
1337 store.sync();\r
1338\r
1339 waitsFor(function () {\r
1340 return !!plugin.activeEditor.editing;\r
1341 }, 'editing to start', 1000);\r
1342\r
1343 runs(function () {\r
1344 expect(ed.editing).toBe(true);\r
1345 expect(plugin.activeColumn.dataIndex).toBe('name');\r
1346 });\r
1347 });\r
1348 });\r
1349 });\r
1350});\r