title: Angular2 + Openlayers3: Test fails when map renders. Writing tests impossible?
body: <p>I have create an Angular2 app (+Webpack). I added a component which shows an Openlayers3 map.It also adds a few markers and a polygon. I am reasonable happy with the functionality, but writing a test for it nearly proves impossible.</p>
  
  <p>This is the test source code: ( I have not added any expect statements yet. The test seems to break when Openlayers tries to render the map.</p>
  
  <pre><code>/* tslint:disable:no-unused-variable */
  import {async, ComponentFixture, TestBed} from '@angular/core/testing';
  import {DebugElement, NO_ERRORS_SCHEMA} from '@angular/core';
  import * as ol from 'openlayers';
  
  
  import {OlComponent} from './ol.component';
  
  let comp: OlComponent;
  
  describe('OlComponent', () =&gt; {
  
      let fixture: ComponentFixture&lt;OlComponent&gt;;
      let component: OlComponent;
  
  
      let element: any;
  
      beforeEach(async(() =&gt; {
          TestBed.configureTestingModule({
              declarations: [
                  OlComponent
              ],
              schemas: [NO_ERRORS_SCHEMA],
  
          })
  
      }))
  
  
      it('should display the map', () =&gt; {
          TestBed.overrideComponent(OlComponent, {
              set: {
                  template: '&lt;div id="map" style="width:10px;height:10px"&gt;&lt;/div&gt;'
              }
          });
          fixture = TestBed.createComponent(OlComponent);
          console.log(fixture);
          component = fixture.componentInstance;
  
  
          element = fixture.nativeElement;
          console.log(element);
          let map = element.querySelector('#map');
          map.style.width = "100px";
          map.style.height = "100px";
  
          component.ngOnInit();
          fixture.detectChanges
  
      });
  });
  </code></pre>
  
  <p>All my efforts so far have only produced this error message when running the test (see source code(s) below.</p>
  
  <pre><code>OlComponent
  ✖ should display the map
    Chrome 53.0.2785 (Linux 0.0.0)
  TypeError: Cannot read property 'length' of undefined
      at Kc (webpack:///~/openlayers/dist/ol.js:43:372 &lt;- karma-shim.js:70246:398)
      at Object.fromLonLat (webpack:///~/openlayers/dist/ol.js:768:188 &lt;- karma-shim.js:70971:196)
      at OlComponent.createMap (webpack:///src/app/ol-maps/ol.component.ts:9:1914 &lt;- karma-shim.js:70159:1929)
      at OlComponent.ngOnInit (webpack:///src/app/ol-maps/ol.component.ts:9:6364 &lt;- karma-shim.js:70159:6369)
      at Object.&lt;anonymous&gt; (webpack:///src/app/ol-maps/ol.component.spec.ts:33:0 &lt;- karma-shim.js:53653:19)
      at ZoneDelegate.invoke (webpack:///~/zone.js/dist/zone.js:232:0 &lt;- karma-shim.js:40990:26)
      at ProxyZoneSpec.onInvoke (webpack:///~/zone.js/dist/proxy.js:79:0 &lt;- karma-shim.js:40654:39)
      at ZoneDelegate.invoke (webpack:///~/zone.js/dist/zone.js:231:0 &lt;- karma-shim.js:40989:32)
      at Zone.run (webpack:///~/zone.js/dist/zone.js:114:0 &lt;- karma-shim.js:40872:43)
      at Object.&lt;anonymous&gt; (webpack:///~/zone.js/dist/jasmine-patch.js:102:0 &lt;- karma-shim.js:40369:34)
      at webpack:///~/@angular/core/bundles/core-testing.umd.js:91:0 &lt;- karma-shim.js:3519:21
      at ZoneDelegate.invoke (webpack:///~/zone.js/dist/zone.js:232:0 &lt;- karma-shim.js:40990:26)
      at AsyncTestZoneSpec.onInvoke (webpack:///~/zone.js/dist/async-test.js:49:0 &lt;- karma-shim.js:39959:39)
      at ProxyZoneSpec.onInvoke (webpack:///~/zone.js/dist/proxy.js:76:0 &lt;- karma-shim.js:40651:39)
      at ZoneDelegate.invoke (webpack:///~/zone.js/dist/zone.js:231:0 &lt;- karma-shim.js:40989:32)
      at Zone.run (webpack:///~/zone.js/dist/zone.js:114:0 &lt;- karma-shim.js:40872:43)
      at AsyncTestZoneSpec._finishCallback (webpack:///~/@angular/core/bundles/core-testing.umd.js:86:0 &lt;- karma-shim.js:3514:29)
      at webpack:///~/zone.js/dist/async-test.js:38:0 &lt;- karma-shim.js:39948:31
      at ZoneDelegate.invokeTask (webpack:///~/zone.js/dist/zone.js:265:0 &lt;- karma-shim.js:41023:35)
      at Zone.runTask (webpack:///~/zone.js/dist/zone.js:154:0 &lt;- karma-shim.js:40912:47)
      at ZoneTask.invoke (webpack:///~/zone.js/dist/zone.js:335:0 &lt;- karma-shim.js:41093:33)
      at data.args.(anonymous function) (webpack:///~/zone.js/dist/zone.js:970:0 &lt;- karma-shim.js:41728:25)
  </code></pre>
  
  <p>OK, here is the source code of the files involved: I am starting of with a service providing Openlayers3 to the component</p>
  
  <pre><code>import {Injectable} from '@angular/core';
  import * as ol from 'openlayers';
  
  
  @Injectable()
  export class OlService {
  
      get(): any {
          return ol;
      }
  }
  </code></pre>
  
  <p>Moving on to the component. (I removed the layers URLs)</p>
  
  <pre><code>import {Component, OnInit, Input} from '@angular/core';
  import {OlService} from './ol.service';
  
  @Component({
      selector: 'my-map',
      templateUrl: './ol.component.html',
      styleUrls: ['./ol.component.scss'],
      providers: [OlService]
  })
  export class OlComponent implements OnInit {
  
      @Input() lnglat: [number, number];
      @Input() zoom: number;
  
      private map;
      public layers = [];
      private vectorSource;
  
      constructor(private olService: OlService) {
  
      }
  
      createMap = () =&gt; {
          let ol = this.olService.get();
          this.vectorSource = new ol.source.Vector({});
          // define layers
  
          let OSM = new ol.layer.Tile({
              source: new ol.source.OSM()
          });
          OSM.set('name', 'Openstreetmap');
  
  
          let geography = new ol.layer.Tile({
              source: new ol.source.TileJSON({
                  url: '',
                  crossOrigin: '',
              }),
              visible: false
          });
          geography.set('name', 'Geography');
  
          let boundaries = new ol.layer.Tile({
              opacity: 0.5,
  
              source: new ol.source.TileWMS({
                  url: '',
                  params: {
                      'LAYERS': 'fwsys:fwsys_region',
                      'TILED': true,
                      'transparent': 'true',
                      'format': 'image/png'
                  },
                  serverType: 'geoserver',
                  projection: ol.proj.get('EPSG:3857')
              })
          });
          boundaries.set('name', 'Boundaries');
          let vector = new ol.layer.Vector({
              source: this.vectorSource
          });
  
          this.map = new ol.Map({
              target: 'map',
              layers: [OSM, geography, vector, boundaries],
              view: new ol.View({
                  center: ol.proj.fromLonLat(this.lnglat),
                  zoom: this.zoom,
                  projection: ol.proj.get('EPSG:3857')
              })
          });
  
          let select_interaction = new ol.interaction.Select();
  
          this.map.addInteraction(select_interaction);
  
          // add popup for all features
          let container = document.getElementById('popup');
          let content = document.getElementById('popup-content');
          let closer = document.getElementById('popup-closer');
  
  
          let popup = new ol.Overlay({
              element: container,
              autoPan: true,
              positioning: 'bottom-center',
              stopEvent: false,
              offset: [0, -5]
          });
  
          closer.onclick = function () {
              popup.setPosition(undefined);
              closer.blur();
              return false;
          };
          this.map.addOverlay(popup);
  
          this.map.on('click', (evt) =&gt; {
              let feature = this.map.forEachFeatureAtPixel(evt.pixel, (feat) =&gt; {
                  return feat;
              });
              if (feature) {
                  let coordinate = evt.coordinate;
                  content.innerHTML = feature.get('name');
                  popup.setPosition(coordinate);
              }
  
  
          });
          this.addLayerSwitcher([OSM, geography, boundaries]);
          this.addMarker([174.76, -37.10], 'Close to Auckland', 'akl1');
          this.addMarker([173.76, -37.10], 'Out in in waters', 'pacific1');
  
          this.addPolygon([[174.76, -37.18], [176.76, -37.18], [176.76, -38.18], [174.76, -38.18]], 'Hamilton', 'id_hamilton');
      };
  
      addPolygon = (polygon: [[number, number]], name: string, id: string) =&gt; {
          let ol = this.olService.get();
          let projectedPolygon = [];
  
          for (let poly of polygon) {
              projectedPolygon.push(ol.proj.transform(poly, 'EPSG:4326', 'EPSG:3857'));
          }
  
          let p = new ol.geom.Polygon([projectedPolygon]);
  
          let featurething = new ol.Feature({
              name: name,
              id: id,
              geometry: p
          });
  
          this.vectorSource.addFeature(featurething);
  
      };
  
      addMarker = (coords: [number, number], name: string, id: string) =&gt; {
          let ol = this.olService.get();
          let iconFeature = new ol.Feature({
              geometry: new ol.geom.Point(ol.proj.transform(coords, 'EPSG:4326', 'EPSG:3857')),
              name: name,
              id: id,
          });
  
          let iconStyle = new ol.style.Style({
              image: new ol.style.Icon(/** @type {olx.style.IconOptions} */ ({
                  opacity: 0.75,
                  anchor: [0.5, 1],
                  src: '//cdn4.iconfinder.com/data/icons/pictype-free-vector-icons/16/location-alt-32.png'
              }))
          });
  
          iconFeature.setStyle(iconStyle);
  
          this.vectorSource.addFeature(iconFeature);
  
      }
  
      addLayerSwitcher = (layers: [any]) =&gt; {
  
          this.layers = layers;
  
      }
      toggleLayer = (layer, evt) =&gt; {
          evt.target.blur();
          if (layer.getVisible()) {
              layer.setVisible(false);
  
          } else {
              layer.setVisible(true);
          }
  
      }
  
      ngOnInit() {
          this.createMap();
      }
  
  }
  </code></pre>