aboutsummaryrefslogtreecommitdiff
path: root/contexts/data/lib/closure-library/closure/goog/ui/editor/abstractdialog_test.html
blob: 97aa447a435a9f7f633202c15a12648f3bee521e (plain)
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
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
<!DOCTYPE html>
<!--
  All Rights Reserved.

  @author nicksantos@google.com (Nick Santos)
  @author marcosalmeida@google.com (Marcos Almeida)
-->
<html>
<!--
Copyright 2008 The Closure Library Authors. All Rights Reserved.

Use of this source code is governed by the Apache License, Version 2.0.
See the COPYING file for details.
-->
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Closure Unit Tests - goog.ui.editor.AbstractDialog</title>
<script src="../../base.js"></script>
<script>
  goog.require('goog.dom.DomHelper');
  goog.require('goog.events.EventHandler');
  goog.require('goog.events.KeyCodes');
  goog.require('goog.testing.MockControl');
  goog.require('goog.testing.events');
  goog.require('goog.testing.jsunit');
  goog.require('goog.testing.mockmatchers.ArgumentMatcher');
  goog.require('goog.ui.editor.AbstractDialog');
  goog.require('goog.ui.editor.AbstractDialog.Builder');
  goog.require('goog.ui.editor.AbstractDialog.EventType');
  goog.require('goog.userAgent');
</script>
</head>
<body>
<script>

function shouldRunTests() {
  // Test disabled in IE7 due to flakiness. See b/4269021.
  return !(goog.userAgent.IE && goog.userAgent.isVersion('7'));
}

var dialog;
var builder;

var mockCtrl;
var mockAfterHideHandler;
var mockOkHandler;
var mockCancelHandler;
var mockCustomButtonHandler;

var CUSTOM_EVENT = 'customEvent';
var CUSTOM_BUTTON_ID = 'customButton';


function setUp() {
  mockCtrl = new goog.testing.MockControl();
  mockAfterHideHandler = mockCtrl.createLooseMock(goog.events.EventHandler);
  mockOkHandler = mockCtrl.createLooseMock(goog.events.EventHandler);
  mockCancelHandler = mockCtrl.createLooseMock(goog.events.EventHandler);
  mockCustomButtonHandler = mockCtrl.createLooseMock(goog.events.EventHandler);
}

function tearDown() {
  if (dialog) {
    mockAfterHideHandler.$setIgnoreUnexpectedCalls(true);
    dialog.dispose();
  }
}

/**
 * Sets up the mock event handler to expect an AFTER_HIDE event.
 */
function expectAfterHide() {
  mockAfterHideHandler.handleEvent(
      new goog.testing.mockmatchers.ArgumentMatcher(function(arg) {
        return arg.type ==
               goog.ui.editor.AbstractDialog.EventType.AFTER_HIDE;
      }));
}

/**
 * Sets up the mock event handler to expect an OK event.
 */
function expectOk() {
  mockOkHandler.handleEvent(new goog.testing.mockmatchers.ArgumentMatcher(
      function(arg) {
        return arg.type == goog.ui.editor.AbstractDialog.EventType.OK;
      }));
}

/**
 * Sets up the mock event handler to expect an OK event and to call
 * preventDefault when handling it.
 */
function expectOkPreventDefault() {
  expectOk();
  mockOkHandler.$does(function(e) {
    e.preventDefault();
  });
}

/**
 * Sets up the mock event handler to expect an OK event and to return false
 * when handling it.
 */
function expectOkReturnFalse() {
  expectOk();
  mockOkHandler.$returns(false);
}

/**
 * Sets up the mock event handler to expect a CANCEL event.
 */
function expectCancel() {
  mockCancelHandler.handleEvent(new goog.testing.mockmatchers.ArgumentMatcher(
      function(arg) {
        return arg.type == goog.ui.editor.AbstractDialog.EventType.CANCEL;
      }));
}

/**
 * Sets up the mock event handler to expect a custom button event.
 */
function expectCustomButton() {
  mockCustomButtonHandler.handleEvent(
      new goog.testing.mockmatchers.ArgumentMatcher(function(arg) {
        return arg.type == CUSTOM_EVENT;
      }));
}

/**
 * Helper to create the dialog being tested in each test. Since NewDialog is
 * abstract, needs to add a concrete version of any abstract methods. Also
 * creates up the global builder variable which should be set up after the call
 * to this method.
 * @return {goog.ui.editor.AbstractDialog} The dialog.
 */
function createTestDialog() {
  var dialog = new goog.ui.editor.AbstractDialog(new goog.dom.DomHelper());
  builder = new goog.ui.editor.AbstractDialog.Builder(dialog);
  dialog.createDialogControl = function() {
    return builder.build();
  };
  dialog.createOkEvent = function(e) {
    return new goog.events.Event(goog.ui.editor.AbstractDialog.EventType.OK);
  };
  dialog.addEventListener(goog.ui.editor.AbstractDialog.EventType.AFTER_HIDE,
                          mockAfterHideHandler);
  dialog.addEventListener(goog.ui.editor.AbstractDialog.EventType.OK,
                          mockOkHandler);
  dialog.addEventListener(goog.ui.editor.AbstractDialog.EventType.CANCEL,
                          mockCancelHandler);
  dialog.addEventListener(CUSTOM_EVENT, mockCustomButtonHandler);
  return dialog;
}


/**
 * Asserts that the given dialog is open.
 * @param {string} msg Message to be printed in case of failure.
 * @param {goog.ui.editor.AbstractDialog} dialog Dialog to be tested.
 */
function assertOpen(msg, dialog) {
  assertTrue(msg + ' [AbstractDialog.isOpen()]', dialog && dialog.isOpen());
}

/**
 * Asserts that the given dialog is closed.
 * @param {string} msg Message to be printed in case of failure.
 * @param {goog.ui.editor.AbstractDialog} dialog Dialog to be tested.
 */
function assertNotOpen(msg, dialog) {
  assertFalse(msg + ' [AbstractDialog.isOpen()]', dialog && dialog.isOpen());
}


/**
 * Tests that if you create a dialog and hide it without having shown it, no
 * errors occur.
 */
function testCreateAndHide() {
  dialog = createTestDialog();
  mockCtrl.$replayAll();

  assertNotOpen('Dialog should not be open after creation', dialog);
  dialog.hide();
  assertNotOpen('Dialog should not be open after hide()', dialog);

  mockCtrl.$verifyAll(); // Verifies AFTER_HIDE was not dispatched.
}

/**
 * Tests that when you show and hide a dialog the flags indicating open are
 * correct and the AFTER_HIDE event is dispatched (and no errors happen).
 */
function testShowAndHide() {
  dialog = createTestDialog();
  expectAfterHide(dialog);
  mockCtrl.$replayAll();

  assertNotOpen('Dialog should not be open before show()', dialog);
  dialog.show();
  assertOpen('Dialog should be open after show()', dialog);
  dialog.hide();
  assertNotOpen('Dialog should not be open after hide()', dialog);

  mockCtrl.$verifyAll(); // Verifies AFTER_HIDE was dispatched.
}

/**
 * Tests that when you show and dispose a dialog (without hiding it first) the
 * flags indicating open are correct and the AFTER_HIDE event is dispatched (and
 * no errors happen).
 */
function testShowAndDispose() {
  dialog = createTestDialog();
  expectAfterHide(dialog);
  mockCtrl.$replayAll();

  assertNotOpen('Dialog should not be open before show()', dialog);
  dialog.show();
  assertOpen('Dialog should be open after show()', dialog);
  dialog.dispose();
  assertNotOpen('Dialog should not be open after dispose()', dialog);

  mockCtrl.$verifyAll(); // Verifies AFTER_HIDE was dispatched.
}

/**
 * Tests that when you dispose a dialog (without ever showing it first) the
 * flags indicating open are correct and the AFTER_HIDE event is never
 * dispatched (and no errors happen).
 */
function testDisposeWithoutShow() {
  dialog = createTestDialog();
  mockCtrl.$replayAll();

  assertNotOpen('Dialog should not be open before dispose()', dialog);
  dialog.dispose();
  assertNotOpen('Dialog should not be open after dispose()', dialog);

  mockCtrl.$verifyAll(); // Verifies AFTER_HIDE was NOT dispatched.
}

/**
 * Tests that labels set in the builder can be found in the resulting dialog's
 * HTML.
 */
function testBasicLayout() {
  dialog = createTestDialog();
  mockCtrl.$replayAll();

  // create some dialog content
  var content = goog.dom.createDom('div', null, 'The Content');
  builder.setTitle('The Title')
      .setContent(content)
      .addOkButton('The OK Button')
      .addCancelButton()
      .addButton('The Apply Button', goog.nullFunction)
      .addClassName('myClassName');
  dialog.show();

  var dialogElem = dialog.dialogInternal_.getElement();
  var html = dialogElem.innerHTML;
  // TODO(user): This is really insufficient. If the title and content
  // were swapped this test would still pass!
  assertContains('Dialog html should contain title', '>The Title<', html);
  assertContains('Dialog html should contain content', '>The Content<', html);
  assertContains('Dialog html should contain custom OK button label',
                 '>The OK Button<',
                 html);
  assertContains('Dialog html should contain default Cancel button label',
                 '>Cancel<',
                 html);
  assertContains('Dialog html should contain custom button label',
                 '>The Apply Button<',
                 html);
  assertTrue('Dialog should have default Closure class',
             goog.dom.classes.has(dialogElem, 'modal-dialog'));
  assertTrue('Dialog should have our custom class',
             goog.dom.classes.has(dialogElem, 'myClassName'));

  mockCtrl.$verifyAll();
}


/**
 * Tests that clicking the OK button dispatches the OK event and closes the
 * dialog (dispatching the AFTER_HIDE event too).
 */
function testOk() {
  dialog = createTestDialog();
  expectOk(dialog);
  expectAfterHide(dialog);
  mockCtrl.$replayAll();

  dialog.show();
  goog.testing.events.fireClickSequence(dialog.getOkButtonElement());
  assertNotOpen('Dialog should not be open after clicking OK', dialog);

  mockCtrl.$verifyAll();
}

/**
 * Tests that hitting the enter key dispatches the OK event and closes the
 * dialog (dispatching the AFTER_HIDE event too).
 */
function testEnter() {
  dialog = createTestDialog();
  expectOk(dialog);
  expectAfterHide(dialog);
  mockCtrl.$replayAll();

  dialog.show();
  goog.testing.events.fireKeySequence(dialog.dialogInternal_.getElement(),
                                      goog.events.KeyCodes.ENTER);
  assertNotOpen('Dialog should not be open after hitting enter', dialog);

  mockCtrl.$verifyAll();
}

/**
 * Tests that clicking the Cancel button dispatches the CANCEL event and closes
 * the dialog (dispatching the AFTER_HIDE event too).
 */
function testCancel() {
  dialog = createTestDialog();
  expectCancel(dialog);
  expectAfterHide(dialog);
  mockCtrl.$replayAll();

  builder.addCancelButton('My Cancel Button');

  dialog.show();
  goog.testing.events.fireClickSequence(dialog.getCancelButtonElement());
  assertNotOpen('Dialog should not be open after clicking Cancel', dialog);

  mockCtrl.$verifyAll();
}

/**
 * Tests that hitting the escape key dispatches the CANCEL event and closes
 * the dialog (dispatching the AFTER_HIDE event too).
 */
function testEscape() {
  dialog = createTestDialog();
  expectCancel(dialog);
  expectAfterHide(dialog);
  mockCtrl.$replayAll();

  dialog.show();
  goog.testing.events.fireKeySequence(dialog.dialogInternal_.getElement(),
                                      goog.events.KeyCodes.ESC);
  assertNotOpen('Dialog should not be open after hitting escape', dialog);

  mockCtrl.$verifyAll();
}

/**
 * Tests that clicking the custom button dispatches the custom event and closes
 * the dialog (dispatching the AFTER_HIDE event too).
 */
function testCustomButton() {
  dialog = createTestDialog();
  expectCustomButton(dialog);
  expectAfterHide(dialog);
  mockCtrl.$replayAll();

  builder.addButton('My Custom Button',
      function() {
        dialog.dispatchEvent(CUSTOM_EVENT)
      },
      CUSTOM_BUTTON_ID);

  dialog.show();
  goog.testing.events.fireClickSequence(
      dialog.getButtonElement(CUSTOM_BUTTON_ID));
  assertNotOpen('Dialog should not be open after clicking custom button',
                dialog);

  mockCtrl.$verifyAll();
}


/**
 * Tests that if the OK handler calls preventDefault, the dialog doesn't close.
 */
function testOkPreventDefault() {
  dialog = createTestDialog();
  expectOkPreventDefault(dialog);
  mockCtrl.$replayAll();

  dialog.show();
  goog.testing.events.fireClickSequence(dialog.getOkButtonElement());
  assertOpen('Dialog should not be closed because preventDefault was called',
             dialog);

  mockCtrl.$verifyAll();
}

/**
 * Tests that if the OK handler returns false, the dialog doesn't close.
 */
function testOkReturnFalse() {
  dialog = createTestDialog();
  expectOkReturnFalse(dialog);
  mockCtrl.$replayAll();

  dialog.show();
  goog.testing.events.fireClickSequence(dialog.getOkButtonElement());
  assertOpen('Dialog should not be closed because handler returned false',
             dialog);

  mockCtrl.$verifyAll();
}

/**
 * Tests that if creating the OK event fails, no event is dispatched and the
 * dialog doesn't close.
 */
function testCreateOkEventFail() {
  dialog = createTestDialog();
  dialog.createOkEvent = function() { // Override our mock createOkEvent.
    return null;
  };
  mockCtrl.$replayAll();

  dialog.show();
  goog.testing.events.fireClickSequence(dialog.getOkButtonElement());
  assertOpen('Dialog should not be closed because OK event creation failed',
             dialog);

  mockCtrl.$verifyAll(); // Verifies that no event was dispatched.
}


/**
 * Tests that processOkAndClose() dispatches the OK event and closes the
 * dialog (dispatching the AFTER_HIDE event too).
 */
function testProcessOkAndClose() {
  dialog = createTestDialog();
  expectOk(dialog);
  expectAfterHide(dialog);
  mockCtrl.$replayAll();

  dialog.show();
  dialog.processOkAndClose();
  assertNotOpen('Dialog should not be open after processOkAndClose()', dialog);

  mockCtrl.$verifyAll();
}

/**
 * Tests that if the OK handler triggered by processOkAndClose calls
 * preventDefault, the dialog doesn't close (in the old implementation this
 * failed due to not great design, so this is sort of a regression test).
 */
function testProcessOkAndClosePreventDefault() {
  dialog = createTestDialog();
  expectOkPreventDefault(dialog);
  mockCtrl.$replayAll();

  dialog.show();
  dialog.processOkAndClose();
  assertOpen('Dialog should not be closed because preventDefault was called',
              dialog);

  mockCtrl.$verifyAll();
}

</script>
</body>
</html>