Application testing with Cesium/Electron

I'm currently working on an application that uses Cesium within Electron. We have CI setup with Jenkins but have been running into issues testing with the portion of the application that makes use of Cesium because WebGL fails to initialize. Testing and such runs fine if tests are run manually from the command line on that machine but when run through Jenkins or run remotely through Remote Desktop, it fails.

Does anyone have any experience testing with Cesium/Electron/Jenkins? If so, could you share any tips on how you set it up?

If this can't be done in Jenkins, are there any systems that you would recommend that would allow for testing with Cesium/Electron?

P.S. Currently using spectron/mocha/chai for testing. Is there something better?

Thanks in advance

As you stated, the crux of the problem is that most CI systems run headless or in a way that doesn’t allow WebGL to be initialized. Historically, the solution was to use something like Mesa to enable software rendering, but this is difficult (and in some cases impossible) to get working with browsers and makes everything slow.

The solution we settled on for Cesium’s own unit tests (and the apps we build with Cesium) is to stub out the WebGL interface completely (thinks to JavaScript’s dynamic type system) and not actually do any of the rendering. The unit tests still all run and pass, they just never draw anything to the canvas.

While we hope to eventually make it a standlone npm module, you can grab our stub from https://github.com/AnalyticalGraphicsInc/cesium/blob/master/Specs/getWebGLStub.js and use it for your own unit tests. To use it, just include it in your app and pass it as an option to either the Viewer or the scene. For example:

return new Viewer(container, {

contextOptions : {

getWebGLStub : getWebGLStub

}

});

I use a global variable that only my test sets to enable the stub for my apps, but the exact implementation of how you turn on the stub in your tests is up to you. Searching for getWebGLStub in Cesium’s code base will show you how it gets activated there.

Hope that helps,

Matt

I am also trying to test an application that uses Cesium and I am trying to incorporate the webGLStub but my globe keeps rendering still.

    // initialize the Cesium globe
    this.view = new Cesium.Viewer( 'cesium', {
      contextOptions: {
        getWebGLStub: getWebGLStub
      }
    } )

This is my Viewer creation. I have included the stub, defaultValue, and all the other files needed for the Stub to function. The globe still renders. Is there something I'm missing?

Do you have a longer code snippet. I’m guessing getWebGLStub here is undefined.

import defaultValue from '../../../support_modules/defaultValue.js'
import getWebGLStub from '../../../support_modules/getWebGLStub.js'

I have it declared in the same file.

    let options = defaultValue( options, {} )
    options.contextOptions = defaultValue( options.contextOptions, {} )
    options.contextOptions.webgl = defaultValue( options.contextOptions.webgl, {} )
    if ( !!window.webglStub ) {
      options.contextOptions.getWebGLStub = getWebGLStub
    }

    this.view = new Cesium.Viewer( 'cesium', options )

This is how I'm defining the options.

All of the files needed:

clone.js
defaultValue.js
defined.js
DeveloperError.js
freezeObject.js
getWebGLStub.js
WebGLConstants.js

These files are all in the same folder together and all of their requirements match up to the same directory as well eg.

define( [
  './clone',
  './defaultValue',
  './defined',
  './DeveloperError',
  './WebGLConstants'
], function(
  clone,
  defaultValue,
  defined,
  DeveloperError,
  WebGLConstants ) ...

For the rest of the initialization of cesium, I'm doing this:

    this.view.scene.globe.imageryLayers._layers[ 0 ].name = 'Natural Earth (Default)'
    this.eventhandler = new Cesium.ScreenSpaceEventHandler( this.view.scene.canvas )
    this.createCollections()

    Cesium.knockout.getObservable( this.view.animation.viewModel, 'timeLabel' ).subscribe( this.throttleEmitTimeUpdate.call( this ) )

    this.ipc.on( 'render-data', ( event, sources ) => this.render( sources ) )

    this.ipc.on( 'clear-data', () => {
      this.view.dataSources.removeAll()
      this.createCollections()
    } )

    Cesium.CzmlDataSource.updaters.push( this.processCustomStaticProperty )

    Cesium.DataSourceCollection.prototype.__defineGetter__( 'sources', function() {
      return this._dataSources
    } )

    Cesium.CzmlDataSource.prototype.getById = function( id ) {
      return _.find( this.entities.values, {
        id: id
      } )
    }

    this.registerCustomEventEmitters()

  }

AFAIK, nothing I've done here should cause the webGL stub to break.
Currently the scene still renders and tries to default to Bing.

I feel like I'm missing something to do with activating the stub.
Was I supposed to take all of those files out of cesium?
Am I supposed to pass something to the stub as parameters when assigning it to: options.contextOptions.getWebGLStub = getWebGLStub

I'm not quite sure what I'm missing and have no logs to follow.

Thanks a bunch for the help!

I don’t know exactly what’s going wrong there, but I created a standalone project that works with the stub. Maybe it will be helpful in uncovering your issue.

Could not get it to upload here… so here’s a google drive link: https://drive.google.com/open?id=0BwZiE_1SDr-Xd2xvSG94cWo1eGc

Sean, thanks for the reply. I work with Jonathan.

The issue turned out to be that we had Cesium 1.29 and the ability to use the WebGL Stub was introduced at 1.30. It was on the line right above the 1.29 changes in the Changelog. If you hear screaming and stuff smashing, it may be Jonathan and I :slight_smile:

Thanks man

Ha nice! I’m glad you got it working now.