hunk.code_window: 	state.tags = m.observable(m.asStructure([]));
   	// custom transform
   	TreeNode.prototype.transform = function(iter, memo) {
   		memo = memo || [];
   		if (!state.tags.length || intersection(state.tags, this.tags).length) memo.push(iter(this));
   		this.children.forEach(function(child) { child.transform(iter, memo); });
   		return memo;
   	}
   	// setup
   	var node = new TreeNode('root', {tags: [1]});
   	node.addChild(new TreeNode('root-child-1', {tags: [2]}));
  
hunk.labels: keep keep keep replace replace replace replace replace keep keep keep keep keep
hunk.after_edit: 	TreeNode.prototype.transform = function(iteratee, results) {
   		results = results || [];
   		if (!state.tags.length || intersection(state.tags, this.tags).length) results.push(iteratee(this));
   		this.children.forEach(function(child) { child.transform(iteratee, results); });
   		return results;
  
hunk.file_path: test/transform.js
hunk.type: replace
file: var m = require('../../');
  
  // TODO: should this development depdendency be removed? (it's for tag tests)
  module.exports.intersection = require('lodash.intersection');
  
  module.exports.pluckFn = function(key) {
    return function(obj) {
      var keys = key.split('.'), value = obj;
      for (var i = 0, l = keys.length; i < l; i++) { if (!value) return; value = value[keys[i]]; }
      return value;
    }
  }
  module.exports.identity = function(value) { return value; }
  
  module.exports.testSet = function() {
    var testSet = {};
  
    var state = testSet.state = m.observable({
      root: null,
      renderedNodes: m.asStructure([]),
      collapsed: new m.map() // KM: ideally, I would like to use a set
    });
  
    var stats = testSet.stats = {
      refCount: 0
    }
  
    var TreeNode = testSet.TreeNode = function(name, extensions) {
      this.children = m.observable(m.asStructure([]));
      this.icon = m.observable('folder');
  
      this.parent = null; // not observed
      this.name = name; // not observed
  
      // optional extensions
      if (extensions) { for (var key in extensions) { this[key] = extensions[key]; } }
    }
    TreeNode.prototype.addChild = function(node) { node.parent = this; this.children.push(node); }
    TreeNode.prototype.addChildren = function(nodes) {
      var _this = this;
      nodes.map(function(node) { node.parent = _this; });
      this.children.splice.apply(this.children, [this.children.length, 0].concat(nodes));
    }
  
    TreeNode.prototype.path = function() {
      var node = this, parts = [];
      while (node) {
        parts.push(node.name);
        node = node.parent;
      }
      return parts.join('/');
    }
  
    TreeNode.prototype.map = function(iter, memo) {
      memo = memo || [];
      memo.push(iter(this));
      this.children.forEach(function(child) { child.map(iter, memo); });
      return memo;
    }
  
    TreeNode.prototype.find = function(iter) {
      if (iter(this)) return this;
  
      var result;
      for (var i = 0, l = this.children.length; i < l; i++) {
        result = this.children[i].find(iter);
        if (result) return result;
      }
      return null;
    }
  
    var DisplayNode = testSet.DisplayNode = function(node) {
      stats.refCount++;
      this.node = node;
    }
    DisplayNode.prototype.destroy = function() { stats.refCount--; }
  
    DisplayNode.prototype.toggleCollapsed = function() {
      var path = this.node.path();
      state.collapsed.has(path) ? state.collapsed.delete(path) : state.collapsed.set(path, true); // KM: ideally, I would like to use a set
    }
  
    return testSet;
  }