text: /* @license
   * Copyright 2019 Google LLC. 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.
   */
  import { $defaultPosterElement, $posterContainerElement, LoadingMixin, POSTER_TRANSITION_TIME } from '../../features/loading.js';
  import ModelViewerElementBase, { $userInputElement } from '../../model-viewer-base.js';
  import { CachingGLTFLoader } from '../../three-components/CachingGLTFLoader.js';
  import { timePasses, waitForEvent } from '../../utilities.js';
  import { assetPath, dispatchSyntheticEvent, pickShadowDescendant, until } from '../helpers.js';
  import { BasicSpecTemplate } from '../templates.js';
  const expect = chai.expect;
  const CUBE_GLB_PATH = assetPath('models/cube.gltf');
  const HORSE_GLB_PATH = assetPath('models/Horse.glb');
  suite('ModelViewerElementBase with LoadingMixin', () => {
      suite('when registered', () => {
          let nextId = 0;
          let tagName;
          let ModelViewerElement;
          setup(() => {
              tagName = `model-viewer-loading-${nextId++}`;
              ModelViewerElement = class extends LoadingMixin(ModelViewerElementBase) {
                  static get is() {
                      return tagName;
                  }
              };
              customElements.define(tagName, ModelViewerElement);
          });
          BasicSpecTemplate(() => ModelViewerElement, () => tagName);
          // TODO: Elements must have loaded to hide poster...
          suite('loading', () => {
              let element;
              setup(async () => {
                  element = new ModelViewerElement();
                  document.body.insertBefore(element, document.body.firstChild);
                  element.poster = assetPath('../screenshot.png');
                  // Wait at least a microtask for size calculations
                  await timePasses();
              });
              teardown(() => {
                  CachingGLTFLoader.clearCache();
                  if (element.parentNode != null) {
                      element.parentNode.removeChild(element);
                  }
              });
              test('creates a poster element that captures interactions', async () => {
                  const picked = pickShadowDescendant(element);
                  expect(picked).to.be.ok;
                  // TODO(cdata): Leaky internal details here:
                  expect(picked.id).to.be.equal('default-poster');
              });
              test('does not load when hidden from render tree', async () => {
                  let loadDispatched = false;
                  let preloadDispatched = false;
                  const loadHandler = () => {
                      loadDispatched = true;
                  };
                  const preloadHandler = () => {
                      preloadDispatched = true;
                  };
                  element.addEventListener('load', loadHandler);
                  element.addEventListener('preload', preloadHandler);
                  element.style.display = 'none';
                  // Give IntersectionObserver a chance to notify. In Chrome, this takes
                  // two rAFs (empirically observed). Await extra time just in case:
                  await timePasses(100);
                  element.src = CUBE_GLB_PATH;
                  await timePasses(500); // Arbitrary time to allow model to load
                  element.removeEventListener('load', loadHandler);
                  element.removeEventListener('preload', preloadHandler);
                  expect(loadDispatched).to.be.false;
                  expect(preloadDispatched).to.be.false;
              });
              suite('load', () => {
                  suite('when a model src changes after loading', () => {
                      setup(async () => {
                          element.src = CUBE_GLB_PATH;
                          await waitForEvent(element, 'load');
                      });
                      test('only dispatches load once per src change', async () => {
                          let loadCount = 0;
                          const onLoad = () => {
                              loadCount++;
                          };
                          element.addEventListener('load', onLoad);
                          try {
                              element.src = HORSE_GLB_PATH;
                              await waitForEvent(element, 'load');
                              element.src = CUBE_GLB_PATH;
                              await waitForEvent(element, 'load');
                              // Give any late-dispatching events a chance to dispatch
                              await timePasses(300);
                              expect(loadCount).to.be.equal(2);
                          }
                          finally {
                              element.removeEventListener('load', onLoad);
                          }
                      });
                      test('getDimensions() returns correct size', () => {
                          const size = element.getDimensions();
                          expect(size.x).to.be.eq(1);
                          expect(size.y).to.be.eq(1);
                          expect(size.z).to.be.eq(1);
                      });
                  });
              });
              suite('loading', () => {
                  suite('src changes quickly', () => {
                      test('eventually notifies that current src is preloaded', async () => {
                          element.loading = 'eager';
                          element.src = CUBE_GLB_PATH;
                          await timePasses();
                          element.src = HORSE_GLB_PATH;
                          let preloadEvent = null;
                          const onPreload = (event) => {
                              if (event.detail.url === HORSE_GLB_PATH) {
                                  preloadEvent = event;
                              }
                          };
                          element.addEventListener('preload', onPreload);
                          await until(() => element.loaded);
                          await timePasses();
                          element.removeEventListener('preload', onPreload);
                          expect(preloadEvent).to.be.ok;
                      });
                  });
                  suite('reveal', () => {
                      suite('auto', () => {
                          test('hides poster when element loads', async () => {
                              element.loading = 'eager';
                              element.src = CUBE_GLB_PATH;
                              await waitForEvent(element, 'model-visibility', (event) => event.detail.visible);
                              const input = element[$userInputElement];
                              const picked = pickShadowDescendant(element);
                              expect(picked).to.be.equal(input);
                          });
                      });
                      suite('interaction', () => {
                          test('retains poster after loading', async () => {
                              element.loading = 'eager';
                              element.reveal = 'interaction';
                              element.src = CUBE_GLB_PATH;
                              await waitForEvent(element, 'load');
                              await timePasses(POSTER_TRANSITION_TIME + 100);
                              const input = element[$userInputElement];
                              const picked = pickShadowDescendant(element);
                              expect(picked).to.not.be.equal(input);
                          });
                          suite('when focused', () => {
                              test('can hide the poster with keyboard interaction', async () => {
                                  element.loading = 'eager';
                                  element.reveal = 'interaction';
                                  element.src = CUBE_GLB_PATH;
                                  const posterElement = element[$defaultPosterElement];
                                  const inputElement = element[$userInputElement];
                                  await waitForEvent(element, 'load');
                                  // NOTE(cdata): Currently, Firefox does not forward focus
                                  // when delegatesFocus is true but focus is triggered
                                  // manually (e.g., with the .focus() method).
                                  posterElement.focus();
                                  expect(element.shadowRoot.activeElement)
                                      .to.be.equal(posterElement);
                                  dispatchSyntheticEvent(posterElement, 'keydown', { keyCode: 13 });
                                  await until(() => {
                                      return element.shadowRoot.activeElement === inputElement;
                                  });
                              });
                          });
                      });
                      suite('manual', () => {
                          test('does not hide poster until dismissed', async () => {
                              element.loading = 'eager';
                              element.reveal = 'manual';
                              element.src = CUBE_GLB_PATH;
                              const posterElement = element[$defaultPosterElement];
                              const input = element[$userInputElement];
                              await waitForEvent(element, 'load');
                              posterElement.focus();
                              expect(element.shadowRoot.activeElement)
                                  .to.be.equal(posterElement);
                              element.dismissPoster();
                              await until(() => {
                                  return element.shadowRoot.activeElement === input;
                              });
                          });
                      });
                  });
              });
              suite('configuring poster via attribute', () => {
                  suite('removing the attribute', () => {
                      test('sets poster to null', async () => {
                          // NOTE(cdata): This is less important after we resolve
                          // https://github.com/PolymerLabs/model-viewer/issues/76
                          element.setAttribute('poster', CUBE_GLB_PATH);
                          await timePasses();
                          element.removeAttribute('poster');
                          await timePasses();
                          expect(element.poster).to.be.equal(null);
                      });
                  });
              });
              suite('with loaded model src', () => {
                  setup(() => {
                      element.src = CUBE_GLB_PATH;
                  });
                  test('can be hidden imperatively', async () => {
                      const ostensiblyThePoster = pickShadowDescendant(element);
                      element.dismissPoster();
                      await waitForEvent(element, 'model-visibility', event => event.detail.visible === true);
                      const ostensiblyNotThePoster = pickShadowDescendant(element);
                      expect(ostensiblyThePoster).to.not.be.equal(ostensiblyNotThePoster);
                  });
                  suite('when poster is hidden', () => {
                      setup(async () => {
                          element.dismissPoster();
                          await waitForEvent(element, 'model-visibility', event => event.detail.visible === true);
                      });
                      test('allows the input to be interactive', async () => {
                          const input = element[$userInputElement];
                          const picked = pickShadowDescendant(element);
                          expect(picked).to.be.equal(input);
                      });
                      test('when src is reset, poster is dismissable', async () => {
                          const posterElement = element[$defaultPosterElement];
                          const posterContainer = element[$posterContainerElement];
                          const inputElement = element[$userInputElement];
                          element.reveal = 'interaction';
                          element.src = null;
                          await timePasses();
                          element.src = CUBE_GLB_PATH;
                          await timePasses();
                          expect(posterContainer.classList.contains('show')).to.be.true;
                          posterElement.focus();
                          expect(element.shadowRoot.activeElement)
                              .to.be.equal(posterElement);
                          dispatchSyntheticEvent(posterElement, 'keydown', { keyCode: 13 });
                          await until(() => {
                              return element.shadowRoot.activeElement === inputElement;
                          });
                      });
                  });
              });
          });
      });
  });
  //# sourceMappingURL=loading-spec.js.map