liuyg
2021-07-02 25ce610f6ecca7325e7a743dc032c4a76559c63d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
define([
    'intern!tdd',
    'intern/chai!assert',
    './util',
    'intern/dojo/node!leadfoot/helpers/pollUntil',
    'intern/dojo/node!leadfoot/keys',
    'require'
], function (test, assert, util, pollUntil, keys, require) {
    // Number of visible rows in the grid.
    // Check the data loaded in test file (Editor.html) and rows visible
    // when the page is loaded to ensure this is correct.
    var GRID_ROW_COUNT = 3;
    var rowSelectorPrefix = '#grid-row-';
 
    var EditorCommand = util.createCommandConstructor({
        dismissViaEnter: function () {
            // Presses the enter key and ends the current element context.
            return new this.constructor(this, function () {
                return this.parent.type(keys.ENTER);
            });
        },
        dismissViaBlur: function () {
            // Exits to the parent context and focuses an unrelated element.
            return new this.constructor(this, function () {
                return this.parent.end()
                    .findByTagName('h2')
                    .click();
            });
        }
    });
 
    test.suite('dgrid/editor functional tests', function () {
        var gotoEnd; // Function defined when `before` logic runs
 
        // Functions performing operations to test the editor columns in the grid,
        // passed to createDatachangeTest
 
        function testAlwaysOnEditor(command, rowIndex, dismissFunc) {
            // Turn off whitespace check because it doesn't like [dismissFunc]() on its own line
            /* jshint white: false */
            var startValue,
                appendValue = 'abc';
 
            // Click the cell's editor element to focus it
            command = command.findByCssSelector(rowSelectorPrefix + rowIndex + ' .field-name input')
                    .click()
                    // Store the current cell value
                    .getProperty('value')
                    .then(function (cellValue) {
                        startValue = cellValue;
                    });
            // Type extra characters to change value
            return gotoEnd(command)
                    .type(appendValue)
                    [dismissFunc]()
                    .end()
                // Click another cell to blur the edited cell (and trigger saving and dgrid-datachange event)
                .findByCssSelector(rowSelectorPrefix + rowIndex + ' .field-description')
                    .click()
                    // The test page has a dgrid-datachange event listener that will push the new value
                    // into a global array: datachangeStack
                    .execute('return datachangeStack.shift();')
                    .then(function (datachangeValue) {
                        assert.strictEqual(startValue + appendValue, datachangeValue,
                            'Value in dgrid-datachange event (' + datachangeValue +
                                ') should equal edited value (' + startValue + appendValue + ')');
                    })
                    .end();
        }
 
        function testEditOnEditor(command, rowIndex, dismissFunc) {
            // Turn off whitespace check because it doesn't like [dismissFunc]() on its own line
            /* jshint white: false */
 
            var cellSelector = rowSelectorPrefix + rowIndex + ' .field-description',
                startValue,
                appendValue = 'abc';
 
            // Click the cell to activate the editor
            command = command.findByCssSelector(cellSelector)
                    .click()
                    .end()
                // Set context to the cell's editor
                .findByCssSelector(cellSelector + ' input')
                    // Store the current cell value
                    .getProperty('value')
                    .then(function (cellValue) {
                        startValue = cellValue;
                    });
            // Type extra characters to change value
            return gotoEnd(command)
                    .type(appendValue)
                    [dismissFunc]()
                    .end()
                // The test page has a dgrid-datachange event listener that will push the new value
                // into a global array: datachangeStack
                .execute('return datachangeStack.shift();')
                .then(function (datachangeValue) {
                    assert.strictEqual(startValue + appendValue, datachangeValue,
                        'Value in dgrid-datachange event (' + datachangeValue +
                            ') should equal edited value (' + startValue + appendValue + ')');
                });
        }
 
        function createDatachangeTest(testFunc, dismissFunc, initFunction) {
            // Generates test functions for enter/blur value registration tests
            return function () {
                this.async(60000);
                var command = new EditorCommand(this.remote);
 
                command = command.get(require.toUrl('./Editor.html'))
                    .then(pollUntil(function () {
                        return window.ready;
                    }, null, 5000));
 
                if (initFunction) {
                    command = command.execute(initFunction);
                }
 
                for (var rowIndex = 0; rowIndex < GRID_ROW_COUNT; rowIndex++) {
                    command = testFunc(command, rowIndex, dismissFunc);
                }
 
                return command;
            };
        }
 
        function createFocusTest(selector, initFunction) {
            // Generates test functions for focus preservation tests
            return function () {
                var command = new EditorCommand(this.remote),
                    rowIndex;
 
                function each(rowIndex) {
                    // Click the cell to activate and focus the editor
                    return command.findByCssSelector(rowSelectorPrefix + rowIndex + ' ' + selector)
                            .click()
                            .end()
                        .executeAsync(function (id, rowIdPrefix, done) {
                            /* global grid */
                            function getRowId(node) {
                                // Retrieves ID of row based on an input node
                                while (node && node.id.slice(0, 9) !== rowIdPrefix) {
                                    node = node.parentNode;
                                }
                                return node && node.id;
                            }
 
                            var activeId = getRowId(document.activeElement);
                            grid.collection.emit('update', { target: grid.collection.get(id) });
                            // Need to wait until next turn for refocus
                            setTimeout(function () {
                                done(activeId === getRowId(document.activeElement));
                            }, 0);
                        }, [ rowIndex, rowSelectorPrefix.slice(1) ])
                        .then(function (testPassed) {
                            assert.isTrue(testPassed,
                                'Focused element before refresh should remain focused after refresh');
                        })
                        .findByTagName('h2')
                            .click()
                            .end();
                }
 
                command = command.get(require.toUrl('./Editor-OnDemand.html'))
                    .then(pollUntil(function () {
                        return window.ready;
                    }, null, 5000));
 
                if (initFunction) {
                    command = command.execute(initFunction);
                }
 
                for (rowIndex = 0; rowIndex < GRID_ROW_COUNT; rowIndex++) {
                    command = each(rowIndex);
                }
 
                return command;
            };
        }
 
        function createEscapeRevertTest(initFunction) {
            return function () {
                var command = new EditorCommand(this.remote),
                    rowIndex;
 
                function each(rowIndex) {
                    var cellSelector = rowSelectorPrefix + rowIndex + ' .field-description',
                        startValue,
                        appendValue = 'abc';
 
                    // Click the cell to focus the editor
                    var newCommand = command.findByCssSelector(cellSelector)
                            .click()
                            .end()
                        // Get the initial value from the editor field
                        .findByCssSelector(cellSelector + ' input')
                            .getProperty('value')
                            .then(function (cellValue) {
                                startValue = cellValue;
                            });
 
                    // Append extra chars and verify the editor's value has updated
                    return gotoEnd(newCommand)
                            .type(appendValue)
                            .getProperty('value')
                            .then(function (cellValue) {
                                assert.notStrictEqual(startValue, cellValue,
                                    'Row ' + rowIndex + ' editor value should differ from the original');
                            })
                            // Send Escape and verify the value has reverted in the grid's data
                            .type(keys.ESCAPE)
                            .execute('return grid.row(' + rowIndex + ').data.description;')
                            .then(function (cellValue) {
                                assert.strictEqual(startValue, cellValue,
                                    'Row ' + rowIndex + ' editor value should equal the starting value after escape');
                            })
                            .end();
                }
 
                command = command.get(require.toUrl('./Editor.html'))
                    .then(pollUntil(function () {
                        return window.ready;
                    }, null, 5000));
 
                if (initFunction) {
                    command = command.execute(initFunction);
                }
 
                for (rowIndex = 0; rowIndex < GRID_ROW_COUNT; rowIndex++) {
                    command = each(rowIndex);
                }
 
                return command;
            };
        }
 
        function createAutosaveTest(initFunction) {
            return function () {
                var command = new EditorCommand(this.remote),
                    appendValue = 'abc',
                    rowIndex;
 
                function each(rowIndex) {
                    var editedValue;
 
                    // Click the cell editor and update the value
                    var newCommand = command.findByCssSelector(rowSelectorPrefix + rowIndex + ' .field-name input')
                            .click();
                    return gotoEnd(newCommand)
                            .type(appendValue)
                            .getProperty('value')
                            .then(function (cellValue) {
                                editedValue = cellValue;
                            })
                            .dismissViaBlur()
                            .end()
                        // Click elsewhere to trigger saving of edited cell
                        .findByTagName('h2')
                            .click()
                            .end()
                        // Wait for the save to complete before moving on to next iteration
                        .then(pollUntil(function () {
                            return window.saveComplete;
                        }, null, 5000))
                        // Get the saved value from the test page and verify it
                        .execute('return gridSaveStack.shift();')
                        .then(function (savedValue) {
                            assert.strictEqual(editedValue, savedValue,
                                'Row ' + rowIndex + ', column "name" saved value (' + savedValue +
                                    ') should equal the entered value (' + editedValue + ')');
                        });
                }
 
                command = command.get(require.toUrl('./Editor-OnDemand.html'))
                    .then(pollUntil(function () {
                        return window.ready;
                    }, null, 5000));
 
                if (initFunction) {
                    command = command.execute(initFunction);
                }
 
                for (rowIndex = 0; rowIndex < GRID_ROW_COUNT; rowIndex++) {
                    command = each(rowIndex);
                }
 
                return command;
            };
        }
 
        // Function passed to above functions to change grid column structure
        // to test other types of editors
 
        function setTextBox() {
            /* global setEditorToTextBox */
            setEditorToTextBox();
        }
 
        test.before(function () {
            // In order to function properly on all platforms, we need to know
            // what the proper character sequence is to go to the end of a text field.
            // End key works generally everywhere except Mac OS X.
            return util.isInputHomeEndSupported(this.remote).then(function (isSupported) {
                gotoEnd = isSupported ? function (command) {
                    return command.type(keys.END);
                } : function (command) {
                    return command.type(keys.META + keys.ARROW_RIGHT);
                };
            });
        });
 
        test.test('escape reverts edited value', createEscapeRevertTest());
        test.test('escape reverts edited value - TextBox', createEscapeRevertTest(setTextBox));
 
        // This combination works, though it's debatable whether it even should
        test.test('enter registers edited value for always-on editor',
            createDatachangeTest(testAlwaysOnEditor, 'dismissViaEnter'));
 
        test.test('enter registers edited value for editOn editor',
            createDatachangeTest(testEditOnEditor, 'dismissViaEnter'));
 
        test.test('blur registers edited value for always-on editor',
            createDatachangeTest(testAlwaysOnEditor, 'dismissViaBlur'));
 
        test.test('blur registers edited value for always-on editor - TextBox',
            createDatachangeTest(testAlwaysOnEditor, 'dismissViaBlur', setTextBox));
 
        test.test('blur registers edited value for editOn editor',
            createDatachangeTest(testEditOnEditor, 'dismissViaBlur'));
 
        test.test('blur registers edited value for editOn editor - TextBox',
            createDatachangeTest(testEditOnEditor, 'dismissViaBlur', setTextBox));
 
        test.test('maintain focus on update for always-on editor',
            createFocusTest('.field-name input'));
 
        test.test('maintain focus on update for always-on editor - TextBox',
            createFocusTest('.field-name input', setTextBox));
 
        test.test('maintain focus on update for editOn editor',
            createFocusTest('.field-description'));
 
        test.test('maintain focus on update for editOn editor - TextBox',
            createFocusTest('.field-description', setTextBox));
 
        test.test('autoSave: true', createAutosaveTest());
        test.test('autoSave: true - TextBox', createAutosaveTest(setTextBox));
 
        test.test('shared editor reset', function () {
            return this.remote
                .get(require.toUrl('./Editor.html'))
                .then(pollUntil(function () {
                    return window.ready;
                }, null, 5000))
                .execute(function () {
                    /* global setEditorToValidationTextBox, data */
                    setEditorToValidationTextBox();
                    data[1].description = '';
                    data[2].description = '';
                    grid.refresh();
                    grid.renderArray(data);
                })
                .findByCssSelector('#grid-row-1 .field-description')
                    .click()
                    .end()
                .findByCssSelector('#grid-row-2 .field-description')
                    .click()
                    .findByCssSelector('.dijitInputInner')
                        .getAttribute('aria-invalid')
                        .then(function (isInvalid) {
                            assert.notStrictEqual(isInvalid, 'true',
                                'Cell editor validation state should not carry over into newly active cell editor');
                            })
                        .end()
                    .end();
        });
    });
});