Testing and auto-generated ids in SproutCore

  January 27th, 2010

If you’re trying to automate tests of your SproutCore application with Selenium, for example, you’ll realise that the HTML element ids are automatically generated. They change every now and then and break all your tests.

To get rid of this problem, you can override the layerId method of certain view classes to generate a stable, and human readable, id.

The following code takes the view hierarchy, and generates an id based on the parents’ names. For example, the mainPage.mainView.someOtherView.theTargetView view will be given the mmsome.theTargetView id.

CT._ct_layerId = function() {
  var k1, k2, k3, k4, guid;

  if (!this._ct_layerId_cache) {
    guid = SC.guidFor(this);

    // Compute the new value
    k1 = this.get('keyForParentView');

    // If k1 is null, defer the computation to later...
    if (!k1) return SC.guidFor(this);

    // Finish the computation
    k2 = this.getPath('parentView.keyForParentView') || '';
    k3 = this.getPath('parentView.parentView.keyForParentView') || '';
    k4 = this.getPath('parentView.parentView.parentView.keyForParentView') || '';

    // Cache the result
    this._ct_layerId_cache = k4.substr(0,1) + k3.substr(0,1) + k2.substr(0,4) + '.' + k1;

    // If the id is already taken, fallback to guid
    if (SC.View.views[this._ct_layerId_cache]) {
      this._ct_layerId_cache = guid;

    // else, update the SC.View.views hash with the new value
    } else {
      delete SC.View.views[guid];
      SC.View.views[this._ct_layerId_cache] = this;
    }
  }

  return this._ct_layerId_cache;
}.property();

SC.View.prototype.mixin({

  keyForParentView: function() {
    var parentView = this.get('parentView'),
        key;
    for (key in parentView) {
      if (this === parentView[key]) return key;
    }
    return null;
  }.property()

});

SC.TextFieldView.prototype.mixin({
  layerId: CT._ct_layerId
});

SC.LabelView.prototype.mixin({
  layerId: CT._ct_layerId
});

SC.ImageView.prototype.mixin({
  layerId: CT._ct_layerId
});

Leave a comment