]>
Commit | Line | Data |
---|---|---|
6527f429 DM |
1 | describe('Ext.grid.plugin.RowEditing', function () {\r |
2 | var store, plugin, grid, view, column,\r | |
3 | synchronousLoad = true,\r | |
4 | proxyStoreLoad = Ext.data.ProxyStore.prototype.load,\r | |
5 | loadStore;\r | |
6 | \r | |
7 | function makeGrid(pluginCfg, gridCfg, storeCfg) {\r | |
8 | var gridPlugins = gridCfg && gridCfg.plugins,\r | |
9 | plugins;\r | |
10 | \r | |
11 | store = new Ext.data.Store(Ext.apply({\r | |
12 | fields: ['name', 'email', 'phone'],\r | |
13 | data: [\r | |
14 | {'name': 'Lisa', 'email': 'lisa@simpsons.com', 'phone': '555-111-1224'},\r | |
15 | {'name': 'Bart', 'email': 'bart@simpsons.com', 'phone': '555-222-1234'},\r | |
16 | {'name': 'Homer', 'email': 'homer@simpsons.com', 'phone': '555-222-1244'},\r | |
17 | {'name': 'Marge', 'email': 'marge@simpsons.com', 'phone': '555-222-1254'}\r | |
18 | ],\r | |
19 | autoDestroy: true\r | |
20 | }, storeCfg));\r | |
21 | \r | |
22 | plugin = new Ext.grid.plugin.RowEditing(pluginCfg);\r | |
23 | \r | |
24 | if (gridPlugins) {\r | |
25 | plugins = [].concat(plugin, gridPlugins);\r | |
26 | delete gridCfg.plugins;\r | |
27 | }\r | |
28 | \r | |
29 | grid = new Ext.grid.Panel(Ext.apply({\r | |
30 | columns: [\r | |
31 | {header: 'Name', dataIndex: 'name', editor: 'textfield'},\r | |
32 | {header: 'Email', dataIndex: 'email',\r | |
33 | editor: {\r | |
34 | xtype: 'textfield',\r | |
35 | allowBlank: false\r | |
36 | }\r | |
37 | },\r | |
38 | {header: 'Phone', dataIndex: 'phone'}\r | |
39 | ],\r | |
40 | store: store,\r | |
41 | plugins: plugins || [plugin],\r | |
42 | width: 400,\r | |
43 | height: 400,\r | |
44 | renderTo: document.body\r | |
45 | }, gridCfg));\r | |
46 | \r | |
47 | view = grid.view;\r | |
48 | }\r | |
49 | \r | |
50 | beforeEach(function() {\r | |
51 | // Override so that we can control asynchronous loading\r | |
52 | loadStore = Ext.data.ProxyStore.prototype.load = function() {\r | |
53 | proxyStoreLoad.apply(this, arguments);\r | |
54 | if (synchronousLoad) {\r | |
55 | this.flushLoad.apply(this, arguments);\r | |
56 | }\r | |
57 | return this;\r | |
58 | };\r | |
59 | });\r | |
60 | \r | |
61 | afterEach(function () {\r | |
62 | // Undo the overrides.\r | |
63 | Ext.data.ProxyStore.prototype.load = proxyStoreLoad;\r | |
64 | \r | |
65 | store = plugin = grid = view = column = Ext.destroy(grid);\r | |
66 | });\r | |
67 | \r | |
68 | describe('Widget column', function() {\r | |
69 | it('should work', function() {\r | |
70 | makeGrid({\r | |
71 | clicksToEdit: 2\r | |
72 | }, {\r | |
73 | columns: [\r | |
74 | {header: 'Name', dataIndex: 'name', editor: 'textfield'},\r | |
75 | {header: 'Email', dataIndex: 'email',\r | |
76 | editor: {\r | |
77 | xtype: 'textfield',\r | |
78 | allowBlank: false\r | |
79 | }\r | |
80 | },\r | |
81 | {header: 'Phone', dataIndex: 'phone'},\r | |
82 | {\r | |
83 | xtype: 'widgetcolumn',\r | |
84 | widget: {\r | |
85 | xtype: 'button',\r | |
86 | text: 'Delete',\r | |
87 | handler: onDeleteClick\r | |
88 | }\r | |
89 | }\r | |
90 | ]\r | |
91 | });\r | |
92 | \r | |
93 | var storeCount = store.getCount(),\r | |
94 | editPos = new Ext.grid.CellContext(view).setPosition(0, 3),\r | |
95 | cell = editPos.getCell(true);\r | |
96 | \r | |
97 | function onDeleteClick(btn) {\r | |
98 | var rec = btn.getWidgetRecord();\r | |
99 | store.remove(rec);\r | |
100 | }\r | |
101 | \r | |
102 | // Programatically focus because simulated mousedown event does not focus, so\r | |
103 | // The tabIndex will NOT be -1, so it will process as if mousedowning on an active widget.\r | |
104 | view.getNavigationModel().setPosition(editPos);\r | |
105 | \r | |
106 | // First click should delete the record.\r | |
107 | // Second click - the dblclick - should not edit being on a focusable widget\r | |
108 | jasmine.fireMouseEvent(cell.firstChild.firstChild, 'dblclick');\r | |
109 | \r | |
110 | // Some browsers process the first and second click separately and will delete two rows.\r | |
111 | // So just check that the store size has been reduced.\r | |
112 | expect(store.getCount()).toBeLessThan(storeCount);\r | |
113 | \r | |
114 | // Editing should never start; flag should be undefined/falsy\r | |
115 | expect(plugin.editing).not.toBe(true);\r | |
116 | });\r | |
117 | });\r | |
118 | \r | |
119 | describe('should work', function () {\r | |
120 | var node;\r | |
121 | \r | |
122 | afterEach(function () {\r | |
123 | node = null;\r | |
124 | });\r | |
125 | \r | |
126 | it('should display the row editor for the grid in editing mode', function () {\r | |
127 | makeGrid();\r | |
128 | \r | |
129 | node = grid.view.getNode(0);\r | |
130 | \r | |
131 | jasmine.fireMouseEvent(Ext.fly(node).down('.x-grid-cell-inner', true), 'dblclick');\r | |
132 | \r | |
133 | expect(plugin.editor).toBeDefined();\r | |
134 | expect(plugin.editing).toBe(true);\r | |
135 | });\r | |
136 | });\r | |
137 | \r | |
138 | describe('renderers', function () {\r | |
139 | it('should be called with the correct scope for the defaultRenderer (column)', function () {\r | |
140 | // See EXTJS-15047.\r | |
141 | var record, scope;\r | |
142 | \r | |
143 | makeGrid(null, {\r | |
144 | columns: [\r | |
145 | {text: 'Foo', width: 50,\r | |
146 | defaultRenderer: function () {\r | |
147 | scope = this;\r | |
148 | return 'some text';\r | |
149 | }\r | |
150 | },\r | |
151 | {header: 'Name', dataIndex: 'name', editor: 'textfield'},\r | |
152 | {header: 'Email', dataIndex: 'email',\r | |
153 | editor: {\r | |
154 | xtype: 'textfield',\r | |
155 | allowBlank: false\r | |
156 | }\r | |
157 | },\r | |
158 | {header: 'Phone', dataIndex: 'phone'}\r | |
159 | ]\r | |
160 | });\r | |
161 | \r | |
162 | record = grid.store.getAt(0);\r | |
163 | column = grid.columns[0];\r | |
164 | plugin.startEdit(record, column);\r | |
165 | \r | |
166 | expect(scope === grid.columns[0]).toBe(true);\r | |
167 | });\r | |
168 | });\r | |
169 | \r | |
170 | describe('starting the edit', function () {\r | |
171 | var combo, textfield, record, items;\r | |
172 | \r | |
173 | describe('should work', function () {\r | |
174 | beforeEach(function () {\r | |
175 | combo = new Ext.form.field.ComboBox({\r | |
176 | queryMode: 'local',\r | |
177 | valueField: 'name',\r | |
178 | displayField: 'name',\r | |
179 | store: {\r | |
180 | fields: ['name'],\r | |
181 | data: [\r | |
182 | { name: 'Lisa' },\r | |
183 | { name: 'Bart' },\r | |
184 | { name: 'Homer' },\r | |
185 | { name: 'Marge' }\r | |
186 | ]\r | |
187 | }\r | |
188 | });\r | |
189 | \r | |
190 | textfield = new Ext.form.field.Text();\r | |
191 | \r | |
192 | makeGrid(null, {\r | |
193 | columns: [\r | |
194 | {header: 'Name', dataIndex: 'name', editor: combo},\r | |
195 | {header: 'Email', dataIndex: 'email',\r | |
196 | editor: {\r | |
197 | xtype: 'textfield',\r | |
198 | allowBlank: false\r | |
199 | }\r | |
200 | },\r | |
201 | {header: 'Phone', dataIndex: 'phone', editor: textfield}\r | |
202 | ]\r | |
203 | });\r | |
204 | \r | |
205 | record = grid.store.getAt(0);\r | |
206 | column = grid.columns[0];\r | |
207 | \r | |
208 | plugin.startEdit(record, column);\r | |
209 | });\r | |
210 | \r | |
211 | afterEach(function () {\r | |
212 | record = items = null;\r | |
213 | });\r | |
214 | \r | |
215 | describe('initial values', function () {\r | |
216 | it('should give each editor a dataIndex property', function () {\r | |
217 | items = plugin.editor.items;\r | |
218 | \r | |
219 | expect(items.getAt(0).dataIndex).toBe('name');\r | |
220 | expect(items.getAt(1).dataIndex).toBe('email');\r | |
221 | expect(items.getAt(2).dataIndex).toBe('phone');\r | |
222 | });\r | |
223 | \r | |
224 | it('should start the editor with values taken from the model', function () {\r | |
225 | items = plugin.editor.items;\r | |
226 | \r | |
227 | expect(items.getAt(0).getValue()).toBe('Lisa');\r | |
228 | expect(items.getAt(1).getValue()).toBe('lisa@simpsons.com');\r | |
229 | expect(items.getAt(2).getValue()).toBe('555-111-1224');\r | |
230 | });\r | |
231 | });\r | |
232 | \r | |
233 | describe('using an existing component as an editor', function () {\r | |
234 | it('should be able to lookup its value from the corresponding model field', function () {\r | |
235 | items = plugin.editor.items;\r | |
236 | \r | |
237 | // The combo editor is an existing component.\r | |
238 | expect(items.getAt(0).getValue()).toBe('Lisa');\r | |
239 | \r | |
240 | // The textfield editor is an existing component.\r | |
241 | expect(items.getAt(2).getValue()).toBe('555-111-1224');\r | |
242 | });\r | |
243 | });\r | |
244 | });\r | |
245 | \r | |
246 | describe('calling startEdit with different columnHeader values', function () {\r | |
247 | it('should allow columnHeader to be a Number', function () {\r | |
248 | makeGrid();\r | |
249 | \r | |
250 | record = grid.store.getAt(0);\r | |
251 | \r | |
252 | // Will return `true` if the edit was successfully started.\r | |
253 | expect(plugin.startEdit(record, 0)).toBe(true);\r | |
254 | });\r | |
255 | \r | |
256 | it('should allow columnHeader to be a Column instance', function () {\r | |
257 | makeGrid();\r | |
258 | \r | |
259 | record = grid.store.getAt(0);\r | |
260 | column = grid.columns[0];\r | |
261 | \r | |
262 | // Will return `true` if the edit was successfully started.\r | |
263 | expect(plugin.startEdit(record, column)).toBe(true);\r | |
264 | });\r | |
265 | \r | |
266 | it('should default to the first visible column if unspecified', function () {\r | |
267 | makeGrid();\r | |
268 | \r | |
269 | record = grid.store.getAt(0);\r | |
270 | \r | |
271 | // Will return `true` if the edit was successfully started.\r | |
272 | expect(plugin.startEdit(record)).toBe(true);\r | |
273 | });\r | |
274 | });\r | |
275 | \r | |
276 | describe('adding new rows to the view', function () {\r | |
277 | var viewEl, count, record, editor;\r | |
278 | \r | |
279 | function addRecord(index) {\r | |
280 | var el;\r | |
281 | \r | |
282 | plugin.cancelEdit();\r | |
283 | store.insert(index, {name: 'Homer', email: 'homer@simpsons.com', phone: '555-222-1244'});\r | |
284 | record = store.getAt(index ? index - 1 : 0);\r | |
285 | plugin.startEdit(record, 0);\r | |
286 | editor = plugin.editor;\r | |
287 | \r | |
288 | el = Ext.fly(view.getNode(record));\r | |
289 | \r | |
290 | return new Ext.util.Point(el.getX(), el.getY());\r | |
291 | }\r | |
292 | \r | |
293 | afterEach(function () {\r | |
294 | count = viewEl = record = editor = null;\r | |
295 | });\r | |
296 | \r | |
297 | it('should be contained by and visible in the view', function () {\r | |
298 | makeGrid(null, {\r | |
299 | height: 100\r | |
300 | });\r | |
301 | \r | |
302 | count = store.getCount();\r | |
303 | viewEl = view.getEl();\r | |
304 | \r | |
305 | // Add to the beginning.\r | |
306 | expect(addRecord(0).isContainedBy(viewEl)).toBe(true);\r | |
307 | expect(addRecord(0).isContainedBy(viewEl)).toBe(true);\r | |
308 | expect(addRecord(0).isContainedBy(viewEl)).toBe(true);\r | |
309 | expect(addRecord(0).isContainedBy(viewEl)).toBe(true);\r | |
310 | \r | |
311 | // Add to the end.\r | |
312 | expect(addRecord(count).isContainedBy(viewEl)).toBe(true);\r | |
313 | expect(addRecord(count).isContainedBy(viewEl)).toBe(true);\r | |
314 | expect(addRecord(count).isContainedBy(viewEl)).toBe(true);\r | |
315 | expect(addRecord(count).isContainedBy(viewEl)).toBe(true);\r | |
316 | });\r | |
317 | \r | |
318 | describe('scrolling into view', function () {\r | |
319 | function buffered(buffered) {\r | |
320 | describe('buffered renderer = ' + buffered, function () {\r | |
321 | beforeEach(function () {\r | |
322 | makeGrid(null, {\r | |
323 | buffered: buffered,\r | |
324 | height: 100\r | |
325 | });\r | |
326 | \r | |
327 | count = store.getCount();\r | |
328 | viewEl = view.getEl();\r | |
329 | });\r | |
330 | \r | |
331 | it('should scroll when adding to the beginning', function () {\r | |
332 | addRecord(0);\r | |
333 | expect(editor.isVisible()).toBe(true);\r | |
334 | expect(editor.context.record).toBe(record);\r | |
335 | });\r | |
336 | \r | |
337 | it('should scroll when adding to the end', function () {\r | |
338 | addRecord(store.getCount());\r | |
339 | expect(editor.isVisible()).toBe(true);\r | |
340 | expect(editor.context.record).toBe(record);\r | |
341 | });\r | |
342 | });\r | |
343 | }\r | |
344 | \r | |
345 | buffered(false);\r | |
346 | buffered(true);\r | |
347 | });\r | |
348 | });\r | |
349 | });\r | |
350 | \r | |
351 | describe('completing the edit', function () {\r | |
352 | var combo, record, items;\r | |
353 | \r | |
354 | beforeEach(function () {\r | |
355 | combo = new Ext.form.field.ComboBox({\r | |
356 | queryMode: 'local',\r | |
357 | valueField: 'name',\r | |
358 | displayField: 'name',\r | |
359 | store: {\r | |
360 | fields: ['name'],\r | |
361 | data: [\r | |
362 | { name: 'Lisa' },\r | |
363 | { name: 'Bart' },\r | |
364 | { name: 'Homer' },\r | |
365 | { name: 'Marge' }\r | |
366 | ]\r | |
367 | }\r | |
368 | });\r | |
369 | \r | |
370 | makeGrid(null, {\r | |
371 | columns: [\r | |
372 | {header: 'Name', dataIndex: 'name', editor: combo},\r | |
373 | {header: 'Email', dataIndex: 'email',\r | |
374 | editor: {\r | |
375 | xtype: 'textfield',\r | |
376 | allowBlank: false\r | |
377 | }\r | |
378 | }\r | |
379 | ]\r | |
380 | });\r | |
381 | \r | |
382 | record = grid.store.getAt(0);\r | |
383 | column = grid.columns[0];\r | |
384 | \r | |
385 | plugin.startEdit(record, column);\r | |
386 | });\r | |
387 | \r | |
388 | afterEach(function () {\r | |
389 | combo = record = items = null;\r | |
390 | });\r | |
391 | \r | |
392 | describe('using an existing component as an editor', function () {\r | |
393 | it('should update the underlying cell and the record', function () {\r | |
394 | column.getEditor().setValue('utley');\r | |
395 | plugin.editor.completeEdit();\r | |
396 | \r | |
397 | expect(Ext.fly(grid.view.getNode(record)).down('.x-grid-cell-inner', true).innerHTML).toBe('utley');\r | |
398 | expect(store.getAt(0).get('name')).toBe('utley');\r | |
399 | });\r | |
400 | });\r | |
401 | });\r | |
402 | \r | |
403 | describe('canceledit', function () {\r | |
404 | var editorContext = {},\r | |
405 | record;\r | |
406 | \r | |
407 | beforeEach(function () {\r | |
408 | makeGrid({\r | |
409 | listeners: {\r | |
410 | canceledit: function (editor, context) {\r | |
411 | editorContext = context;\r | |
412 | }\r | |
413 | }\r | |
414 | });\r | |
415 | \r | |
416 | record = grid.store.getAt(0);\r | |
417 | column = grid.columns[0];\r | |
418 | \r | |
419 | plugin.startEdit(record, column);\r | |
420 | });\r | |
421 | \r | |
422 | afterEach(function () {\r | |
423 | editorContext = record = null;\r | |
424 | });\r | |
425 | \r | |
426 | it('should be able to get the original value when canceling the edit', function() {\r | |
427 | column.getEditor().setValue('baz');\r | |
428 | plugin.cancelEdit();\r | |
429 | \r | |
430 | expect(editorContext.originalValues.name).toBe('Lisa');\r | |
431 | });\r | |
432 | \r | |
433 | it('should be able to get the edited value when canceling the edit', function() {\r | |
434 | column.getEditor().setValue('foo');\r | |
435 | plugin.cancelEdit();\r | |
436 | \r | |
437 | expect(editorContext.newValues.name).toBe('foo');\r | |
438 | });\r | |
439 | \r | |
440 | it('should have different values for edited value and original value when canceling', function() {\r | |
441 | column.getEditor().setValue('foo');\r | |
442 | plugin.cancelEdit();\r | |
443 | \r | |
444 | expect(editorContext.newValues.name).not.toBe(editorContext.originalValues.name);\r | |
445 | });\r | |
446 | \r | |
447 | it('should be able to capture falsey values when canceled', function() {\r | |
448 | column.getEditor().setValue('');\r | |
449 | plugin.cancelEdit();\r | |
450 | \r | |
451 | expect(editorContext.newValues.name).toBe('');\r | |
452 | });\r | |
453 | });\r | |
454 | \r | |
455 | describe('locked grid', function () {\r | |
456 | var suiteCfg = {\r | |
457 | columns: [\r | |
458 | {header: 'Name', dataIndex: 'name', width: 100, locked: true, editor: true},\r | |
459 | {header: 'Email', dataIndex: 'email', width: 100, editor: true},\r | |
460 | {header: 'Phone', dataIndex: 'phone', width: 100, editor: true}\r | |
461 | ],\r | |
462 | plugins: {\r | |
463 | ptype: 'rowediting'\r | |
464 | }\r | |
465 | },\r | |
466 | node;\r | |
467 | \r | |
468 | beforeEach(function () {\r | |
469 | makeGrid(null, suiteCfg);\r | |
470 | });\r | |
471 | \r | |
472 | afterEach(function () {\r | |
473 | node = null;\r | |
474 | });\r | |
475 | \r | |
476 | it('should display the row editor for the locked grid in editing mode', function () {\r | |
477 | node = grid.lockedGrid.view.getNode(0);\r | |
478 | \r | |
479 | jasmine.fireMouseEvent(Ext.fly(node).down('.x-grid-cell-inner', true), 'dblclick');\r | |
480 | \r | |
481 | plugin = grid.findPlugin('rowediting');\r | |
482 | \r | |
483 | expect(plugin.editor !== null).toBe(true);\r | |
484 | expect(plugin.editing).toBe(true);\r | |
485 | });\r | |
486 | \r | |
487 | it('should display the row editor for the normal grid in editing mode', function () {\r | |
488 | node = grid.normalGrid.view.getNode(0);\r | |
489 | \r | |
490 | jasmine.fireMouseEvent(Ext.fly(node).down('.x-grid-cell-inner', true), 'dblclick');\r | |
491 | \r | |
492 | plugin = grid.findPlugin('rowediting');\r | |
493 | \r | |
494 | expect(plugin.editor !== null).toBe(true);\r | |
495 | expect(plugin.editing).toBe(true);\r | |
496 | });\r | |
497 | \r | |
498 | describe('with grouping feature', function () {\r | |
499 | describe('when the activeRecord of the activeEditor has been filtered', function () {\r | |
500 | // These specs simulate the filtering of the data store when the row editing plugin is active\r | |
501 | // and over a record that has been filtered after the row editor was activated/started editing.\r | |
502 | // The bug appeared in KS when the row editor was open and the dataset was filtered by the grid\r | |
503 | // filter feature. Since the locking partners share the same store, the normal grid can't look\r | |
504 | // up the record in its store if the locked grid has already filtered the store, which is the\r | |
505 | // case here. Note that the bug only occurred when the editor was started from the normalGrid,\r | |
506 | // NOT the lockedGrid (since the store hadn't been filtered yet).\r | |
507 | //\r | |
508 | // To simulate, simply filter the store after the plugin has been activated. During the filter\r | |
509 | // operation, it will try to lookup the row record by its internal id in the GroupStore, but it\r | |
510 | // will fail because the dataset has been filtered and the GroupStore#getByInternalId method will\r | |
511 | // lookup the record in the data store. The fix is to lookup the record in the snapshot collection,\r | |
512 | // if it exists. This mimics the solution implemented by v5 which solves this by maintaining another\r | |
513 | // unfiltered collection, Ext.util.CollectionKey. So, because we can get the record shows that the\r | |
514 | // bug has been fixed, since the record is being found (regardless of filtering).\r | |
515 | // See EXTJS-13374.\r | |
516 | //\r | |
517 | // Note these specs must use the bufferedrenderer plugin.\r | |
518 | var normalView, lockedView, record;\r | |
519 | \r | |
520 | beforeEach(function () {\r | |
521 | grid.destroy();\r | |
522 | \r | |
523 | makeGrid(null, Ext.applyIf({\r | |
524 | features: {\r | |
525 | ftype : 'groupingsummary',\r | |
526 | groupHeaderTpl : '{name}'\r | |
527 | },\r | |
528 | plugins: ['bufferedrenderer'],\r | |
529 | lockedGridConfig: null,\r | |
530 | normalGridConfig: null\r | |
531 | }, suiteCfg), {\r | |
532 | groupField: 'name'\r | |
533 | });\r | |
534 | \r | |
535 | normalView = grid.normalGrid.view;\r | |
536 | lockedView = grid.lockedGrid.view;\r | |
537 | });\r | |
538 | \r | |
539 | afterEach(function () {\r | |
540 | normalView = lockedView = record = null;\r | |
541 | });\r | |
542 | \r | |
543 | describe('activating the editor from the normal view', function () {\r | |
544 | beforeEach(function () {\r | |
545 | node = normalView.getNode(0);\r | |
546 | \r | |
547 | jasmine.fireMouseEvent(Ext.fly(node).down('.x-grid-cell-inner', true), 'dblclick');\r | |
548 | \r | |
549 | // Now filter the store. Make sure that the row that's clicked on has been filtered\r | |
550 | // and is no longer in the filtered data collection. This is what triggered the bug\r | |
551 | // because the GroupStore is trying to look up the record in the filtered collection.\r | |
552 | store.filter('email', /home/);\r | |
553 | record = normalView.getRecord(node);\r | |
554 | });\r | |
555 | \r | |
556 | it('should still be able to lookup the record in the datastore when filtered', function () {\r | |
557 | expect(record).toBeDefined();\r | |
558 | expect(record.get('email')).toBe('bart@simpsons.com');\r | |
559 | });\r | |
560 | \r | |
561 | it('should close the editor', function () {\r | |
562 | expect(plugin.editing).toBe(false);\r | |
563 | });\r | |
564 | });\r | |
565 | \r | |
566 | describe('activating the editor from the locked view', function () {\r | |
567 | beforeEach(function () {\r | |
568 | node = lockedView.getNode(0);\r | |
569 | \r | |
570 | jasmine.fireMouseEvent(Ext.fly(node).down('.x-grid-cell-inner', true), 'dblclick');\r | |
571 | \r | |
572 | store.filter('email', /home/);\r | |
573 | record = lockedView.getRecord(node);\r | |
574 | });\r | |
575 | \r | |
576 | it('should still be able to lookup the record in the datastore when filtered', function () {\r | |
577 | expect(record).toBeDefined();\r | |
578 | expect(record.get('email')).toBe('bart@simpsons.com');\r | |
579 | });\r | |
580 | \r | |
581 | it('should close the editor', function () {\r | |
582 | expect(plugin.editing).toBe(false);\r | |
583 | });\r | |
584 | });\r | |
585 | });\r | |
586 | });\r | |
587 | });\r | |
588 | \r | |
589 | describe('clicksToEdit', function () {\r | |
590 | var node, record;\r | |
591 | \r | |
592 | afterEach(function () {\r | |
593 | node = record = null;\r | |
594 | });\r | |
595 | \r | |
596 | describe('2 clicks', function () {\r | |
597 | beforeEach(function () {\r | |
598 | makeGrid();\r | |
599 | });\r | |
600 | \r | |
601 | it('should default to 2', function () {\r | |
602 | expect(plugin.clicksToEdit).toBe(2);\r | |
603 | });\r | |
604 | \r | |
605 | it('should begin editing when double-clicked', function () {\r | |
606 | record = grid.store.getAt(0);\r | |
607 | node = grid.view.getNodeByRecord(record);\r | |
608 | jasmine.fireMouseEvent(Ext.fly(node).down('.x-grid-cell'), 'dblclick');\r | |
609 | \r | |
610 | expect(plugin.editor).not.toBeFalsy();\r | |
611 | });\r | |
612 | \r | |
613 | it('should not begin editing when single-clicked', function () {\r | |
614 | record = grid.store.getAt(0);\r | |
615 | node = grid.view.getNodeByRecord(record);\r | |
616 | jasmine.fireMouseEvent(Ext.fly(node).down('.x-grid-cell'), 'click');\r | |
617 | \r | |
618 | expect(plugin.editor).toBeFalsy();\r | |
619 | });\r | |
620 | });\r | |
621 | \r | |
622 | describe('1 click', function () {\r | |
623 | beforeEach(function () {\r | |
624 | makeGrid({\r | |
625 | clicksToEdit: 1\r | |
626 | });\r | |
627 | });\r | |
628 | \r | |
629 | it('should honor a different number than the default', function () {\r | |
630 | expect(plugin.clicksToEdit).toBe(1);\r | |
631 | });\r | |
632 | \r | |
633 | it('should begin editing when single-clicked', function () {\r | |
634 | record = grid.store.getAt(0);\r | |
635 | node = grid.view.getNodeByRecord(record);\r | |
636 | jasmine.fireMouseEvent(Ext.fly(node).down('.x-grid-cell'), 'click');\r | |
637 | \r | |
638 | expect(plugin.editor).not.toBeFalsy();\r | |
639 | });\r | |
640 | \r | |
641 | it('should not begin editing when double-clicked', function () {\r | |
642 | record = grid.store.getAt(0);\r | |
643 | node = grid.view.getNodeByRecord(record);\r | |
644 | jasmine.fireMouseEvent(Ext.fly(node).down('.x-grid-cell'), 'dblclick');\r | |
645 | \r | |
646 | expect(plugin.editor).not.toBeFalsy();\r | |
647 | });\r | |
648 | });\r | |
649 | });\r | |
650 | \r | |
651 | describe('the RowEditor', function () {\r | |
652 | var field;\r | |
653 | \r | |
654 | afterEach(function () {\r | |
655 | field = null;\r | |
656 | });\r | |
657 | \r | |
658 | describe('as textfield', function () {\r | |
659 | beforeEach(function () {\r | |
660 | makeGrid();\r | |
661 | \r | |
662 | column = grid.columns[0];\r | |
663 | plugin.startEdit(store.getAt(0), column);\r | |
664 | field = column.field;\r | |
665 | });\r | |
666 | \r | |
667 | it('should start the edit when ENTER is pressed', function () {\r | |
668 | var node;\r | |
669 | \r | |
670 | // First complete the edit (we start an edit in the top-level beforeEach).\r | |
671 | plugin.completeEdit();\r | |
672 | // Let's just do a sanity to make sure we're really not currently editing.\r | |
673 | expect(plugin.editing).toBe(false);\r | |
674 | \r | |
675 | node = view.body.query('td', true)[0];\r | |
676 | jasmine.fireKeyEvent(node, 'keydown', 13);\r | |
677 | \r | |
678 | waitsFor(function () {\r | |
679 | return plugin.editing;\r | |
680 | });\r | |
681 | \r | |
682 | runs(function () {\r | |
683 | expect(plugin.editing).toBe(true);\r | |
684 | });\r | |
685 | });\r | |
686 | \r | |
687 | describe('when currently editing', function () {\r | |
688 | it('should complete the edit when ENTER is pressed', function () {\r | |
689 | var str = 'Utley is Top Dog',\r | |
690 | model = store.getAt(0);\r | |
691 | \r | |
692 | expect(model.get('name')).toBe('Lisa');\r | |
693 | field.setValue(str);\r | |
694 | \r | |
695 | jasmine.fireKeyEvent(field.inputEl, 'keydown', 13);\r | |
696 | \r | |
697 | waitsFor(function () {\r | |
698 | return model.get('name') === str;\r | |
699 | });\r | |
700 | \r | |
701 | runs(function () {\r | |
702 | expect(model.get('name')).toBe(str);\r | |
703 | });\r | |
704 | });\r | |
705 | \r | |
706 | it('should cancel the edit when ESCAPE is pressed', function () {\r | |
707 | spyOn(plugin, 'cancelEdit');\r | |
708 | \r | |
709 | jasmine.fireKeyEvent(field.inputEl, 'keydown', 27);\r | |
710 | \r | |
711 | expect(plugin.cancelEdit).toHaveBeenCalled();\r | |
712 | });\r | |
713 | });\r | |
714 | });\r | |
715 | \r | |
716 | describe('as textarea', function () {\r | |
717 | beforeEach(function () {\r | |
718 | makeGrid();\r | |
719 | \r | |
720 | column = grid.columns[1];\r | |
721 | plugin.startEdit(store.getAt(0), column);\r | |
722 | field = column.field;\r | |
723 | });\r | |
724 | \r | |
725 | it('should start the edit when ENTER is pressed', function () {\r | |
726 | var node;\r | |
727 | \r | |
728 | // First complete the edit (we start an edit in the top-level beforeEach).\r | |
729 | plugin.completeEdit();\r | |
730 | // Let's just do a sanity to make sure we're really not currently editing.\r | |
731 | expect(plugin.editing).toBe(false);\r | |
732 | \r | |
733 | node = view.body.query('td', true)[1];\r | |
734 | jasmine.fireKeyEvent(node, 'keydown', 13);\r | |
735 | \r | |
736 | expect(plugin.editing).toBe(true);\r | |
737 | });\r | |
738 | \r | |
739 | describe('when currently editing', function () {\r | |
740 | it('should complete the edit when ENTER is pressed', function () {\r | |
741 | spyOn(plugin, 'completeEdit');\r | |
742 | \r | |
743 | jasmine.fireKeyEvent(field.inputEl, 'keydown', 13);\r | |
744 | \r | |
745 | expect(plugin.completeEdit).toHaveBeenCalled();\r | |
746 | });\r | |
747 | \r | |
748 | it('should not cancel the edit when ENTER is pressed', function () {\r | |
749 | spyOn(plugin, 'cancelEdit');\r | |
750 | \r | |
751 | jasmine.fireKeyEvent(field.inputEl, 'keydown', 13);\r | |
752 | \r | |
753 | expect(plugin.cancelEdit).not.toHaveBeenCalled();\r | |
754 | });\r | |
755 | \r | |
756 | it('should cancel the edit when ESCAPE is pressed', function () {\r | |
757 | spyOn(plugin, 'cancelEdit');\r | |
758 | \r | |
759 | jasmine.fireKeyEvent(field.inputEl, 'keydown', 27);\r | |
760 | \r | |
761 | expect(plugin.cancelEdit).toHaveBeenCalled();\r | |
762 | });\r | |
763 | });\r | |
764 | });\r | |
765 | });\r | |
766 | });\r |