text: /*
   * Copyright 2016 Google Inc. 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('firebaseui.auth.ui.dialogTest');
  goog.setTestOnly('firebaseui.auth.ui.dialogTest');
  
  goog.require('firebaseui.auth.soy2.element');
  goog.require('firebaseui.auth.ui.element');
  goog.require('firebaseui.auth.ui.element.dialog');
  goog.require('firebaseui.auth.ui.mdl');
  goog.require('goog.dom');
  goog.require('goog.dom.TagName');
  goog.require('goog.math.Coordinate');
  goog.require('goog.soy');
  goog.require('goog.testing.MockControl');
  goog.require('goog.testing.events');
  goog.require('goog.testing.jsunit');
  goog.require('goog.ui.Component');
  
  
  var dialog;
  var dialog2;
  
  var mockControl;
  var mockUpgrade;
  var mockDowngrade;
  var component;
  var container;
  
  
  function setUp() {
    mockControl = new goog.testing.MockControl();
    window['dialogPolyfill'] = {
      'registerDialog': function(dialog) {
        dialog.open = false;
        dialog.showModal = function() {
          dialog.open = true;
        };
        dialog.close = function() {
          dialog.open = false;
        };
      }
    };
    mockUpgrade = mockControl.createMethodMock(firebaseui.auth.ui.mdl, 'upgrade');
    mockDowngrade = mockControl.createMethodMock(firebaseui.auth.ui.mdl,
        'downgrade');
  
    component = new goog.ui.Component();
    container = goog.dom.createDom(goog.dom.TagName.DIV);
    document.body.appendChild(container);
    // Position the container in some known location.
    container.style.position = "absolute";
    container.style.top = "50px";
    container.style.left = "100px";
    container.style.height = "200px";
    container.style.width = "150px";
    component.render(container);
  }
  
  
  function tearDown() {
    mockControl.$verifyAll();
    mockControl.$resetAll();
  
    // Remove dialogs from the DOM, if left over.
    if (dialog && document.body.contains(dialog)) {
      document.body.removeChild(dialog);
    }
    dialog = null;
    if (dialog2 && document.body.contains(dialog2)) {
      document.body.removeChild(dialog2);
    }
    dialog2 = null;
    goog.dom.removeNode(container);
  }
  
  
  if (goog.global['window'] &&
      typeof goog.global['window'].CustomEvent !== 'function') {
    var doc = goog.global.document;
    /**
     * CustomEvent polyfill for IE 9, 10 and 11.
     * https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent
     * @param {string} event The event type.
     * @param {Object=} opt_params The optional event parameters.
     * @return {!Event} The generated custom event.
     */
    var CustomEvent = function(event, opt_params) {
      var params = opt_params || {
        bubbles: false, cancelable: false, detail: undefined
      };
      var evt = doc.createEvent('CustomEvent');
      evt.initCustomEvent(
          event, params.bubbles, params.cancelable, params.detail);
      return evt;
    };
    CustomEvent.prototype = goog.global['window'].Event.prototype;
    goog.global['window'].CustomEvent = CustomEvent;
  }
  
  
  function testShowDialog() {
    dialog = goog.soy.renderAsElement(
        firebaseui.auth.soy2.element.dialog,
        {content: 'Hello, world!'});
    mockUpgrade(dialog);
    mockDowngrade(dialog);
  
    mockControl.$replayAll();
  
    firebaseui.auth.ui.element.dialog.showDialog.call(component, dialog);
  
    // The dialog should be attached to the DOM and be retrievable via
    // getDialogElement.
    assertTrue(document.body.contains(dialog));
    assertTrue(dialog.open);
    assertEquals(dialog, firebaseui.auth.ui.element.dialog.getDialogElement());
  
    // Confirm dialog centered relative to container.
    assertEquals(
        parseInt(
            50 - document.body.getBoundingClientRect().top +
            (200 - dialog.getBoundingClientRect().height) / 2, 10),
        parseInt(dialog.style.top, 10));
    var expectedDialogLeft = 100 - document.body.getBoundingClientRect().left +
        (150 - dialog.getBoundingClientRect().width) / 2;
    assertEquals(
        parseInt(expectedDialogLeft, 10),
        parseInt(dialog.style.left, 10));
    assertEquals(
        parseInt(
            document.body.getBoundingClientRect().width -
            expectedDialogLeft -
            dialog.getBoundingClientRect().width, 10),
        parseInt(dialog.style.right, 10));
  
    // Check alignment updated on resize.
    // Simulate container location and size updated.
    container.style.top = "5px";
    container.style.left = "10px";
    container.style.height = "20px";
    container.style.width = "15px";
    // Trigger resize event.
    goog.global['window'].dispatchEvent(new CustomEvent('resize'));
    // Dialog location should update.
    assertEquals(
        parseInt(
            5 - document.body.getBoundingClientRect().top +
            (20 - dialog.getBoundingClientRect().height) / 2, 10),
        parseInt(dialog.style.top, 10));
    expectedDialogLeft = 10 - document.body.getBoundingClientRect().left +
        (15 - dialog.getBoundingClientRect().width) / 2;
    assertEquals(
        parseInt(expectedDialogLeft, 10),
        parseInt(dialog.style.left, 10));
    assertEquals(
        parseInt(
            document.body.getBoundingClientRect().width -
            expectedDialogLeft -
            dialog.getBoundingClientRect().width, 10),
        parseInt(dialog.style.right, 10));
  
    // Dismiss dialog.
    firebaseui.auth.ui.element.dialog.dismissDialog.call(component);
    var expectedDismissedTop = parseInt(dialog.style.top, 10);
    // Simulate container location and size updated.
    container.style.top = "500px";
    // Trigger resize event.
    goog.global['window'].dispatchEvent(new CustomEvent('resize'));
    // Dialog location should not update as it already has been dismissed.
    assertEquals(
        expectedDismissedTop,
        parseInt(dialog.style.top, 10));
  }
  
  
  function testShowDialog_centerRelativeToDocumentBody() {
    dialog = goog.soy.renderAsElement(
        firebaseui.auth.soy2.element.dialog,
        {content: 'Hello, world!'});
    mockUpgrade(dialog);
  
    mockControl.$replayAll();
  
    firebaseui.auth.ui.element.dialog.showDialog.call(
        component, dialog, false, true);
  
    // The dialog should be attached to the DOM and be retrievable via
    // getDialogElement.
    assertTrue(document.body.contains(dialog));
    assertTrue(dialog.open);
    assertEquals(dialog, firebaseui.auth.ui.element.dialog.getDialogElement());
  
    // Confirm dialog centered relative to body (top, left and right style not
    // modified).
    assertNaN(parseInt(dialog.style.top, 10));
    assertNaN(parseInt(dialog.style.left, 10));
    assertNaN(parseInt(dialog.style.right, 10));
  }
  
  
  function testShowDialog_dismissDialog() {
    dialog = goog.soy.renderAsElement(
        firebaseui.auth.soy2.element.dialog,
        {content: 'Hello, world!'});
    mockUpgrade(dialog);
    mockDowngrade(dialog);
  
    mockControl.$replayAll();
  
    // Show the dialog.
    firebaseui.auth.ui.element.dialog.showDialog.call(component, dialog);
    assertTrue(document.body.contains(dialog));
    assertTrue(dialog.open);
    assertEquals(dialog, firebaseui.auth.ui.element.dialog.getDialogElement());
  
    // Dismiss the dialog.
    firebaseui.auth.ui.element.dialog.dismissDialog();
    assertFalse(document.body.contains(dialog));
    assertFalse(dialog.open);
    assertNull(firebaseui.auth.ui.element.dialog.getDialogElement());
  }
  
  
  function testShowDialog_showOtherDialog() {
    dialog = goog.soy.renderAsElement(
        firebaseui.auth.soy2.element.dialog,
        {content: 'Hello, world!'});
  
    dialog2 = goog.soy.renderAsElement(
        firebaseui.auth.soy2.element.dialog,
        {content: 'Hello, other world!'});
  
    mockUpgrade(dialog);
    mockDowngrade(dialog);
    mockUpgrade(dialog2);
  
    mockControl.$replayAll();
  
    // Show first dialog.
    firebaseui.auth.ui.element.dialog.showDialog.call(component, dialog);
  
    // First dialog should be opened.
    assertTrue(document.body.contains(dialog));
    assertTrue(dialog.open);
    assertEquals(dialog, firebaseui.auth.ui.element.dialog.getDialogElement());
  
    // Show a second dialog.
    firebaseui.auth.ui.element.dialog.showDialog.call(component, dialog2);
  
    // First dialog should be automatically removed when the new dialog is opened.
    assertFalse(document.body.contains(dialog));
    assertFalse(dialog.open);
  
    // Second dialog should be opened.
    assertTrue(document.body.contains(dialog2));
    assertTrue(dialog2.open);
    assertEquals(dialog2, firebaseui.auth.ui.element.dialog.getDialogElement());
  }
  
  
  /**
   * Test that dismissDialog still works if the dialog has been closed by some
   * other means. For example, the ESC key closes the HTML5 dialog.
   */
  function testShowDialog_dialogClosedByOtherMeans() {
    dialog = goog.soy.renderAsElement(
        firebaseui.auth.soy2.element.dialog,
        {content: 'Hello, world!'});
    dialog.close = function() {};
    var mockClose = mockControl.createMethodMock(dialog, 'close');
    mockUpgrade(dialog);
    mockDowngrade(dialog);
    mockClose().$never();
  
    mockControl.$replayAll();
  
    // Show the dialog.
    firebaseui.auth.ui.element.dialog.showDialog.call(component, dialog);
    assertTrue(document.body.contains(dialog));
    assertEquals(dialog, firebaseui.auth.ui.element.dialog.getDialogElement());
  
    // Simulate the dialog being closed by hitting the escape key. This hides
    // the dialog but does not remove it from the DOM..
    dialog.open = false;
  
    // Dismiss the dialog. The dialog should be removed from the DOM at this
    // point.
    firebaseui.auth.ui.element.dialog.dismissDialog();
    assertFalse(document.body.contains(dialog));
    assertNull(firebaseui.auth.ui.element.dialog.getDialogElement());
  }
  
  
  function testCloseDialogOnBackdropClick() {
    dialog = goog.soy.renderAsElement(
        firebaseui.auth.soy2.element.dialog,
        {content: 'Hello, world!'});
    mockUpgrade(dialog).$anyTimes();
    mockDowngrade(dialog).$anyTimes();
    mockControl.$replayAll();
  
    firebaseui.auth.ui.element.dialog.showDialog.call(component, dialog, true);
  
    var bounds = dialog.getBoundingClientRect();
  
    // Click inside the dialog. The dialog should remain displayed.
    // TODO: Make this work with browsers without HTML5 <dialog> support.
    if (bounds.width > 0 && bounds.height > 0) {
      goog.testing.events.fireClickSequence(dialog, null,
          new goog.math.Coordinate(bounds.left + 1, bounds.top + 1));
      assertTrue(document.body.contains(dialog));
      assertNotNull(firebaseui.auth.ui.element.dialog.getDialogElement());
    }
  
    // Click above and to the left of the dialog. The dialog should be dismissed.
    goog.testing.events.fireClickSequence(dialog, null,
        new goog.math.Coordinate(bounds.left - 1, bounds.top - 1));
    assertFalse(document.body.contains(dialog));
    assertNull(firebaseui.auth.ui.element.dialog.getDialogElement());
  
  
    firebaseui.auth.ui.element.dialog.showDialog.call(component, dialog, true);
    // Click to the right of the dialog. The dialog should be dismissed.
    goog.testing.events.fireClickSequence(dialog, null,
        new goog.math.Coordinate(bounds.left + bounds.width + 1, bounds.top + 1));
    assertFalse(document.body.contains(dialog));
    assertNull(firebaseui.auth.ui.element.dialog.getDialogElement());
  
  
    firebaseui.auth.ui.element.dialog.showDialog.call(component, dialog, true);
    // Click under the dialog. The dialog should be dismissed.
    goog.testing.events.fireClickSequence(dialog, null,
        new goog.math.Coordinate(
            bounds.left + 1, bounds.top + bounds.height + 1));
    assertFalse(document.body.contains(dialog));
    assertNull(firebaseui.auth.ui.element.dialog.getDialogElement());
  }
  