text: defineSuite([
          'Widgets/Geocoder/GeocoderViewModel',
          'Core/Cartesian3',
          'Core/Rectangle',
          'Specs/createScene',
          'Specs/pollToPromise',
          'ThirdParty/when'
      ], function(
          GeocoderViewModel,
          Cartesian3,
          Rectangle,
          createScene,
          pollToPromise,
          when) {
      'use strict';
  
      var scene;
      var mockDestination = new Cartesian3(1.0, 2.0, 3.0);
  
      var geocoderResults1 = [{
          displayName: 'a',
          destination: mockDestination
      }, {
          displayName: 'b',
          destination: mockDestination
      }, {
          displayName: 'c',
          destination: mockDestination
      }];
      var customGeocoderOptions = {
          autoComplete: true,
          geocode: function (input) {
              return when.resolve(geocoderResults1);
          }
      };
  
      var geocoderResults2 = [{
          displayName: '1',
          destination: mockDestination
      }, {
          displayName: '2',
          destination: mockDestination
      }];
      var customGeocoderOptions2 = {
          autoComplete: true,
          geocode: function (input) {
              return when.resolve(geocoderResults2);
          }
      };
  
      var noResultsGeocoder = {
          autoComplete: true,
          geocode: function (input) {
              return when.resolve([]);
          }
      };
  
      beforeAll(function() {
          scene = createScene();
      });
  
      afterAll(function() {
          scene.destroyForSpecs();
      });
  
      it('constructor sets expected properties', function() {
          var flightDuration = 1234;
  
          var viewModel = new GeocoderViewModel({
              scene : scene,
              flightDuration : flightDuration
          });
  
          expect(viewModel.scene).toBe(scene);
          expect(viewModel.flightDuration).toBe(flightDuration);
          expect(viewModel.keepExpanded).toBe(false);
      });
  
      it('can get and set flight duration', function() {
          var viewModel = new GeocoderViewModel({
              scene : scene
          });
          viewModel.flightDuration = 324;
          expect(viewModel.flightDuration).toEqual(324);
  
          expect(function() {
              viewModel.flightDuration = -123;
          }).toThrowDeveloperError();
      });
  
      it('throws is searchText is not a string', function() {
          var viewModel = new GeocoderViewModel({
              scene : scene,
              geocoderServices : [customGeocoderOptions]
          });
          expect(function() {
              viewModel.searchText = undefined;
          }).toThrowDeveloperError();
      });
  
      it('moves camera when search command invoked', function() {
          var viewModel = new GeocoderViewModel({
              scene : scene,
              geocoderServices : [customGeocoderOptions]
          });
  
          var cameraPosition = Cartesian3.clone(scene.camera.position);
  
          viewModel.searchText = '220 Valley Creek Blvd, Exton, PA';
          viewModel.search();
  
          return pollToPromise(function() {
              scene.tweens.update();
              return !Cartesian3.equals(cameraPosition, scene.camera.position);
          });
      });
  
      it('constructor throws without scene', function() {
          expect(function() {
              return new GeocoderViewModel();
          }).toThrowDeveloperError();
      });
  
      it('raises the complete event camera finished', function() {
          var viewModel = new GeocoderViewModel({
              scene : scene,
              flightDuration : 0,
              geocoderServices : [customGeocoderOptions]
          });
  
          var spyListener = jasmine.createSpy('listener');
          viewModel.complete.addEventListener(spyListener);
  
          viewModel.searchText = '-1.0, -2.0';
          viewModel.search();
  
          expect(spyListener.calls.count()).toBe(1);
  
          viewModel.flightDuration = 1.5;
          viewModel.searchText = '2.0, 2.0';
          viewModel.search();
  
          return pollToPromise(function() {
              scene.tweens.update();
              return spyListener.calls.count() === 2;
          });
      });
  
      it('can be created with a custom geocoder', function() {
          expect(function() {
              return new GeocoderViewModel({
                  scene : scene,
                  geocoderServices : [customGeocoderOptions]
              });
          }).not.toThrowDeveloperError();
      });
  
      it('automatic suggestions can be retrieved', function() {
          var geocoder = new GeocoderViewModel({
              scene : scene,
              geocoderServices : [customGeocoderOptions]
          });
          geocoder._searchText = 'some_text';
          GeocoderViewModel._updateSearchSuggestions(geocoder);
          expect(geocoder._suggestions.length).toEqual(3);
      });
  
      it('update search suggestions results in empty list if the query is empty', function() {
          var geocoder = new GeocoderViewModel({
              scene : scene,
              geocoderServices : [customGeocoderOptions]
          });
          geocoder._searchText = '';
  
          GeocoderViewModel._updateSearchSuggestions(geocoder);
          expect(geocoder._suggestions.length).toEqual(0);
      });
  
      it('can activate selected search suggestion', function () {
          spyOn(GeocoderViewModel, 'flyToDestination');
          var destination = new Rectangle(0.0, -0.1, 0.1, 0.1);
          var geocoder = new GeocoderViewModel({
              scene : scene,
              geocoderServices : [customGeocoderOptions]
          });
  
          var suggestion = { displayName: 'a', destination: destination };
          geocoder._selectedSuggestion = suggestion;
          geocoder.activateSuggestion(suggestion);
          expect(geocoder._searchText).toEqual('a');
          expect(GeocoderViewModel.flyToDestination).toHaveBeenCalledWith(geocoder, destination);
      });
  
      it('if more than one geocoder service is provided, use first result from first geocode in array order', function () {
          spyOn(GeocoderViewModel, 'flyToDestination');
  
          var geocoder = new GeocoderViewModel({
              scene : scene,
              geocoderServices : [noResultsGeocoder, customGeocoderOptions2]
          });
          geocoder._searchText = 'sthsnth'; // an empty query will prevent geocoding
  
          geocoder.search();
          expect(geocoder._searchText).toEqual(geocoderResults2[0].displayName);
          expect(GeocoderViewModel.flyToDestination).toHaveBeenCalledWith(geocoder, mockDestination);
      });
  
      it('can update autoComplete suggestions list using multiple geocoders', function () {
          var geocoder = new GeocoderViewModel({
              scene : scene,
              geocoderServices : [customGeocoderOptions, customGeocoderOptions2]
          });
          geocoder._searchText = 'sthsnth'; // an empty query will prevent geocoding
          GeocoderViewModel._updateSearchSuggestions(geocoder);
          expect(geocoder._suggestions.length).toEqual(geocoderResults1.length + geocoderResults2.length);
      });
  
      it('uses custom destination found callback', function () {
          spyOn(GeocoderViewModel, 'flyToDestination');
  
          var destinationFound = jasmine.createSpy();
          var geocoder = new GeocoderViewModel({
              scene : scene,
              geocoderServices : [noResultsGeocoder, customGeocoderOptions2],
              destinationFound: destinationFound
          });
          geocoder._searchText = 'sthsnth'; // an empty query will prevent geocoding
          geocoder.search();
  
          expect(geocoder._searchText).toEqual(geocoderResults2[0].displayName);
          expect(GeocoderViewModel.flyToDestination).not.toHaveBeenCalled();
          expect(destinationFound).toHaveBeenCalledWith(geocoder, mockDestination);
      });
  
      it('automatic suggestions can be navigated by arrow up/down keys', function() {
          spyOn(GeocoderViewModel, '_adjustSuggestionsScroll');
          var viewModel = new GeocoderViewModel({
              scene : scene,
              geocoderServices : [customGeocoderOptions]
          });
          viewModel._searchText = 'some_text';
          GeocoderViewModel._updateSearchSuggestions(viewModel);
  
          expect(viewModel._selectedSuggestion).toEqual(undefined);
          viewModel._handleArrowDown(viewModel);
          expect(viewModel._selectedSuggestion.displayName).toEqual('a');
          viewModel._handleArrowDown(viewModel);
          viewModel._handleArrowDown(viewModel);
          expect(viewModel._selectedSuggestion.displayName).toEqual('c');
          viewModel._handleArrowDown(viewModel);
          expect(viewModel._selectedSuggestion.displayName).toEqual('a');
          viewModel._handleArrowDown(viewModel);
          viewModel._handleArrowUp(viewModel);
          expect(viewModel._selectedSuggestion.displayName).toEqual('a');
          viewModel._handleArrowUp(viewModel);
          expect(viewModel._selectedSuggestion).toBeUndefined();
      });
  }, 'WebGL');
  