123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479 |
- // Copyright 2008 The Closure Library Authors. All Rights Reserved.
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS-IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- goog.provide('goog.ui.editor.AbstractDialogTest');
- goog.setTestOnly('goog.ui.editor.AbstractDialogTest');
- goog.require('goog.dom');
- goog.require('goog.dom.DomHelper');
- goog.require('goog.dom.TagName');
- goog.require('goog.dom.classlist');
- goog.require('goog.events.Event');
- 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.userAgent');
- function shouldRunTests() {
- // Test disabled in IE7 due to flakiness. See b/4269021.
- return !(goog.userAgent.IE && goog.userAgent.isVersionOrHigher('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(goog.dom.TagName.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.classlist.contains(dialogElem, 'modal-dialog'));
- assertTrue(
- 'Dialog should have our custom class',
- goog.dom.classlist.contains(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();
- }
|