<commit_before>(function( Wield ) {
	module( "Wield.Dom.prototype.after" );

	test( "after works", function() {
		var fixture = new Wield.Dom( document.getElementById("after") ),
			span = document.createElement("span");

		equal( fixture.element.parentNode.childNodes.length, 1, "the fixture is present and has child elements" );

		deepEqual( fixture, fixture.after(span), "after is chainable" );

		equal( fixture.element.parentNode.childNodes.length, 2, "the fixture is present but is empty" );
		equal( span, fixture.element.parentNode.childNodes[1], "the span is the second child" );
	});

	test( "after with object receiver works with Wield objects", function() {
		var fixture = new Wield.Dom( document.getElementById("after") ),
			span = new Wield.Dom( document.createElement("span") );

		equal( fixture.element.parentNode.childNodes.length, 1, "the fixture is present and has child elements" );

		deepEqual( fixture, fixture.after(span), "after is chainable" );

		equal( fixture.element.parentNode.childNodes.length, 2, "the fixture is present but is empty" );
		equal( span.element, fixture.element.parentNode.childNodes[1], "the span is the second child" );
	});

	test( "after works as a standalone function", function() {
		var fixture = document.getElementById( "after" ),
			span = document.createElement("span");

		equal( fixture.parentNode.childNodes.length, 1, "the fixture is present and has child elements" );

		Wield.Dom.prototype.after( fixture, span );

		equal( fixture.parentNode.childNodes.length, 2, "the fixture is present but is empty" );
		equal( span, fixture.parentNode.childNodes[1], "the span is the second child" );
	});

	module( "Wield.Dom.prototype.append" );

	test( "append works", function() {
		var fixture = new Wield.Dom( document.getElementById("append") );

		equal( fixture.element.childNodes.length, 0, "the fixture is empty" );

		deepEqual( fixture, fixture.append(document.createElement("span")), "method is chainable" );

		equal( fixture.element.childNodes.length, 1, "the fixture has one child" );
	});

	test( "append with object receiver works with wield objects", function() {
		var fixture = new Wield.Dom( document.getElementById("append") );

		equal( fixture.element.childNodes.length, 0, "the fixture is empty" );

		fixture.append( new Wield.Dom(document.createElement("span")) );

		equal( fixture.element.childNodes.length, 1, "the fixture has one child" );
	});

	test( "append is a noop for anything not Node.ELEMENT_NODE || Node.DOCUMENT_FRAGMENT_NODE", function() {
		expect( 0 );

		var textNode = new Wield.Dom({
			nodeType: Node.TEXT_NODE,
			appendChild: function() {
				ok( false, "appendChild was called" );
			}
		});

		textNode.append( document.createElement("span") );
	});

	test( "append works as a standalone function", function() {
		var fixture = document.getElementById( "append" );

		equal( fixture.childNodes.length, 0, "the fixture is empty" );

		Wield.Dom.prototype.append(
			fixture,
			document.createElement("span")
		);

		equal( fixture.childNodes.length, 1, "the fixture has one child" );
	});

	module( "Wield.Dom.prototype.before" );

	test( "before works", function() {
		var fixture = new Wield.Dom( document.getElementById("before") ),
			span = document.createElement("span");

		equal( fixture.element.parentNode.childNodes.length, 1, "the fixture is present and has child elements" );

		deepEqual( fixture, fixture.before(span), "before is chainable" );

		equal( fixture.element.parentNode.childNodes.length, 2, "the fixture is present but is empty" );
		equal( span, fixture.element.parentNode.childNodes[0], "the span is the second child" );
	});

	test( "before works", function() {
		var fixture = new Wield.Dom( document.getElementById("before") ),
			span = new Wield.Dom( document.createElement("span") );

		equal( fixture.element.parentNode.childNodes.length, 1, "the fixture is present and has child elements" );

		deepEqual( fixture, fixture.before(span), "before is chainable" );

		equal( fixture.element.parentNode.childNodes.length, 2, "the fixture is present but is empty" );
		equal( span.element, fixture.element.parentNode.childNodes[0], "the span is the second child" );
	});

	test( "before works as a standalone function", function() {
		var fixture = document.getElementById( "before" ),
			span = document.createElement("span");

		equal( fixture.parentNode.childNodes.length, 1, "the fixture is present and has child elements" );

		Wield.Dom.prototype.before( fixture, span );

		equal( fixture.parentNode.childNodes.length, 2, "the fixture is present but is empty" );
		equal( span, fixture.parentNode.childNodes[0], "the span is the second child" );
	});

	module( "Wield.Dom.prototype.empty" );

	test( "empty works", function() {
		var fixture = new Wield.Dom( document.getElementById("empty") );

		equal( fixture.element.childNodes.length, 2, "the fixture is present and has child elements" );

		deepEqual( fixture, fixture.empty(), "empty is chainable" );

		equal( fixture.element.childNodes.length, 0, "the fixture is present but is empty" );
	});

	test( "empty works as a standalone function", function() {
		var fixture = document.getElementById("empty");

		equal( fixture.childNodes.length, 2, "the fixture is present and has child elements" );

		Wield.Dom.prototype.empty( fixture );

		equal( fixture.childNodes.length, 0, "the fixture is present but is empty" );
	});

	module( "Wield.Dom.find" );

	if( document.querySelector ) {
		test( "find works", function() {
			var fixture = Wield.Dom.find( "#qunit-fixture" );

			equal( fixture.element.id, "qunit-fixture", "querySelector is used" );
		});

		test( "find works when invoked standalone", function() {
			var $ = Wield.Dom.find,
				fixture = $( "#qunit-fixture" );

			equal( fixture.element.id, "qunit-fixture", "querySelector is used" );
		});
	}

	test( "raises and exception when no finder is defined", function() {
		Wield.Dom.finder = undefined;

		throws(function() {
			Wield.Dom.find( "foo" );
		});
	});

	module( "Wield.Dom.prototype.html" );

	test( "html works", function() {
		var fixture = new Wield.Dom( document.getElementById("html") );

		equal( fixture.html(), "foo", "the html is returned" );
	});

	test( "html works as a standalone function", function() {
		var fixture = document.getElementById("html");

		equal( Wield.Dom.prototype.html( fixture ), "foo", "the html is returned" );
	});

	module( "Wield.Dom.prototype.remove" );

	test( "remove works", function() {
		var fixture = new Wield.Dom( document.getElementById("remove") );

		ok( document.getElementById("remove") !== null, "the fixture is present" );

		deepEqual( fixture, fixture.remove(), "remove is chainable" );

		equal( document.getElementById("remove"), null, "the fixture is gone" );
	});

	test( "remove works as a standalone function", function() {
		var fixture = document.getElementById("remove");

		ok( document.getElementById("remove") !== null, "the fixture is present" );

		Wield.Dom.prototype.remove( fixture );

		equal( document.getElementById("remove"), null, "the fixture is gone" );
	});

	test( "remove is a noop withiout a parent node", function() {
		expect( 0 );

		var fixture = new Wield.Dom({
			parentNode: null
		});

		// If `e.parentNode.removeChild` is called it'll throw an exception
		// not an amazing test :/
		fixture.remove();
	});

	module( "Wield.Dom.prototype.replaceWith" );

	test( "replaceWith works", function() {
		var fixture = new Wield.Dom( document.getElementById("replace") ),
		replacement = document.createElement( "div" );

		ok( document.getElementById("replace") !== null, "the fixture is present" );
		equal( document.getElementById("replacement"), null, "the replacement is not yet present" );

		replacement.id = "replacement";
		deepEqual( fixture, fixture.replaceWith( replacement ), "replaceWith is chainable" );

		equal( document.getElementById("replace"), null, "the fixture is gone" );
		ok( document.getElementById("replacement") !== null, "the replacement is present" );
	});

	test( "replaceWith works as a standalone function", function() {
		var fixture = document.getElementById("replace"),
		replacement = document.createElement( "div" );

		ok( document.getElementById("replace") !== null, "the fixture is present" );
		equal( document.getElementById("replacement"), null, "the replacement is not yet present" );

		replacement.id = "replacement";
		Wield.Dom.prototype.replaceWith( fixture, replacement );

		equal( document.getElementById("replace"), null, "the fixture is gone" );
		ok( document.getElementById("replacement") !== null, "the replacement is present" );
	});

	module( "Wield.Dom.prototype.unwrap" );

	test( "unwrap works", function() {
		var fixture = new Wield.Dom( document.getElementById("unwrap") ),
			wrapped = document.getElementById( "wrapped" );

		equal( wrapped.parentNode.id, "unwrap", "the fixture is wrapped" );

		deepEqual( fixture, fixture.unwrap(), "unwrap is chainable" );

		equal( wrapped.parentNode.id, "qunit-fixture", "the fixture isn't wrapped" );
	});

	test( "unwrap works as a standalone function", function() {
		var fixture = document.getElementById( "unwrap" ),
			wrapped = document.getElementById( "wrapped" );

		equal( wrapped.parentNode.id, "unwrap", "the fixture is wrapped" );

		Wield.Dom.prototype.unwrap( fixture );

		equal( wrapped.parentNode.id, "qunit-fixture", "the fixture isn't wrapped" );
	});

	module( "Wield.Dom.prototype.wrap" );

	test( "wrap works", function() {
		var fixture = new Wield.Dom( document.getElementById("wrap") ),
			wrapper = document.getElementById( "wrapper" );

		equal( fixture.element.parentNode.id, "qunit-fixture", "the fixture isn't wrapped" );

		deepEqual( fixture, fixture.wrap( wrapper ), "wrap is chainable" );

		equal( fixture.element.parentNode.id, "wrapper", "the fixture is wrapped" );
	});

	test( "wrap with object receiver works with wield objects", function() {
		var fixture = new Wield.Dom( document.getElementById("wrap") ),
			wrapper = new Wield.Dom( document.getElementById("wrapper") );

		equal( fixture.element.parentNode.id, "qunit-fixture", "the fixture isn't wrapped" );

		fixture.wrap( wrapper );

		equal( fixture.element.parentNode.id, "wrapper", "the fixture is wrapped" );
	});

	test( "wrap works as a standalone function", function() {
		var fixture = new Wield.Dom( document.getElementById("wrap") ),
			wrapper = document.getElementById( "wrapper" );

		equal( fixture.element.parentNode.id, "qunit-fixture", "the fixture isn't wrapped" );

		Wield.Dom.prototype.wrap( fixture.element, wrapper );

		equal( fixture.element.parentNode.id, "wrapper", "the fixture is wrapped" );
	});

	test( "wrap uses innermost child of the wrapper", function() {
		var fixture = new Wield.Dom( document.getElementById("wrap") ),
			wrapper = new Wield.Dom( document.getElementById( "wrapper" ) );

		wrapper.append( document.createElement("span") );

		equal( fixture.element.parentNode.id, "qunit-fixture", "the fixture isn't wrapped" );

		fixture.wrap( wrapper.element );

		equal( fixture.element.parentNode.id, "", "the fixture is wrapped" );
		equal( fixture.element.parentNode.nodeName, "SPAN", "the fixture is wrapped" );
	});

}( window.Wield ));
<commit_msg>using throws as a function is confusing :/<commit_after>(function( Wield ) {
	module( "Wield.Dom.prototype.after" );

	test( "after works", function() {
		var fixture = new Wield.Dom( document.getElementById("after") ),
			span = document.createElement("span");

		equal( fixture.element.parentNode.childNodes.length, 1, "the fixture is present and has child elements" );

		deepEqual( fixture, fixture.after(span), "after is chainable" );

		equal( fixture.element.parentNode.childNodes.length, 2, "the fixture is present but is empty" );
		equal( span, fixture.element.parentNode.childNodes[1], "the span is the second child" );
	});

	test( "after with object receiver works with Wield objects", function() {
		var fixture = new Wield.Dom( document.getElementById("after") ),
			span = new Wield.Dom( document.createElement("span") );

		equal( fixture.element.parentNode.childNodes.length, 1, "the fixture is present and has child elements" );

		deepEqual( fixture, fixture.after(span), "after is chainable" );

		equal( fixture.element.parentNode.childNodes.length, 2, "the fixture is present but is empty" );
		equal( span.element, fixture.element.parentNode.childNodes[1], "the span is the second child" );
	});

	test( "after works as a standalone function", function() {
		var fixture = document.getElementById( "after" ),
			span = document.createElement("span");

		equal( fixture.parentNode.childNodes.length, 1, "the fixture is present and has child elements" );

		Wield.Dom.prototype.after( fixture, span );

		equal( fixture.parentNode.childNodes.length, 2, "the fixture is present but is empty" );
		equal( span, fixture.parentNode.childNodes[1], "the span is the second child" );
	});

	module( "Wield.Dom.prototype.append" );

	test( "append works", function() {
		var fixture = new Wield.Dom( document.getElementById("append") );

		equal( fixture.element.childNodes.length, 0, "the fixture is empty" );

		deepEqual( fixture, fixture.append(document.createElement("span")), "method is chainable" );

		equal( fixture.element.childNodes.length, 1, "the fixture has one child" );
	});

	test( "append with object receiver works with wield objects", function() {
		var fixture = new Wield.Dom( document.getElementById("append") );

		equal( fixture.element.childNodes.length, 0, "the fixture is empty" );

		fixture.append( new Wield.Dom(document.createElement("span")) );

		equal( fixture.element.childNodes.length, 1, "the fixture has one child" );
	});

	test( "append is a noop for anything not Node.ELEMENT_NODE || Node.DOCUMENT_FRAGMENT_NODE", function() {
		expect( 0 );

		var textNode = new Wield.Dom({
			nodeType: Node.TEXT_NODE,
			appendChild: function() {
				ok( false, "appendChild was called" );
			}
		});

		textNode.append( document.createElement("span") );
	});

	test( "append works as a standalone function", function() {
		var fixture = document.getElementById( "append" );

		equal( fixture.childNodes.length, 0, "the fixture is empty" );

		Wield.Dom.prototype.append(
			fixture,
			document.createElement("span")
		);

		equal( fixture.childNodes.length, 1, "the fixture has one child" );
	});

	module( "Wield.Dom.prototype.before" );

	test( "before works", function() {
		var fixture = new Wield.Dom( document.getElementById("before") ),
			span = document.createElement("span");

		equal( fixture.element.parentNode.childNodes.length, 1, "the fixture is present and has child elements" );

		deepEqual( fixture, fixture.before(span), "before is chainable" );

		equal( fixture.element.parentNode.childNodes.length, 2, "the fixture is present but is empty" );
		equal( span, fixture.element.parentNode.childNodes[0], "the span is the second child" );
	});

	test( "before works", function() {
		var fixture = new Wield.Dom( document.getElementById("before") ),
			span = new Wield.Dom( document.createElement("span") );

		equal( fixture.element.parentNode.childNodes.length, 1, "the fixture is present and has child elements" );

		deepEqual( fixture, fixture.before(span), "before is chainable" );

		equal( fixture.element.parentNode.childNodes.length, 2, "the fixture is present but is empty" );
		equal( span.element, fixture.element.parentNode.childNodes[0], "the span is the second child" );
	});

	test( "before works as a standalone function", function() {
		var fixture = document.getElementById( "before" ),
			span = document.createElement("span");

		equal( fixture.parentNode.childNodes.length, 1, "the fixture is present and has child elements" );

		Wield.Dom.prototype.before( fixture, span );

		equal( fixture.parentNode.childNodes.length, 2, "the fixture is present but is empty" );
		equal( span, fixture.parentNode.childNodes[0], "the span is the second child" );
	});

	module( "Wield.Dom.prototype.empty" );

	test( "empty works", function() {
		var fixture = new Wield.Dom( document.getElementById("empty") );

		equal( fixture.element.childNodes.length, 2, "the fixture is present and has child elements" );

		deepEqual( fixture, fixture.empty(), "empty is chainable" );

		equal( fixture.element.childNodes.length, 0, "the fixture is present but is empty" );
	});

	test( "empty works as a standalone function", function() {
		var fixture = document.getElementById("empty");

		equal( fixture.childNodes.length, 2, "the fixture is present and has child elements" );

		Wield.Dom.prototype.empty( fixture );

		equal( fixture.childNodes.length, 0, "the fixture is present but is empty" );
	});

	module( "Wield.Dom.find" );

	if( document.querySelector ) {
		test( "find works", function() {
			var fixture = Wield.Dom.find( "#qunit-fixture" );

			equal( fixture.element.id, "qunit-fixture", "querySelector is used" );
		});

		test( "find works when invoked standalone", function() {
			var $ = Wield.Dom.find,
				fixture = $( "#qunit-fixture" );

			equal( fixture.element.id, "qunit-fixture", "querySelector is used" );
		});
	}

	test( "raises and exception when no finder is defined", function() {
		Wield.Dom.finder = undefined;

		QUnit.throws(function() {
			Wield.Dom.find( "foo" );
		});
	});

	module( "Wield.Dom.prototype.html" );

	test( "html works", function() {
		var fixture = new Wield.Dom( document.getElementById("html") );

		equal( fixture.html(), "foo", "the html is returned" );
	});

	test( "html works as a standalone function", function() {
		var fixture = document.getElementById("html");

		equal( Wield.Dom.prototype.html( fixture ), "foo", "the html is returned" );
	});

	module( "Wield.Dom.prototype.remove" );

	test( "remove works", function() {
		var fixture = new Wield.Dom( document.getElementById("remove") );

		ok( document.getElementById("remove") !== null, "the fixture is present" );

		deepEqual( fixture, fixture.remove(), "remove is chainable" );

		equal( document.getElementById("remove"), null, "the fixture is gone" );
	});

	test( "remove works as a standalone function", function() {
		var fixture = document.getElementById("remove");

		ok( document.getElementById("remove") !== null, "the fixture is present" );

		Wield.Dom.prototype.remove( fixture );

		equal( document.getElementById("remove"), null, "the fixture is gone" );
	});

	test( "remove is a noop withiout a parent node", function() {
		expect( 0 );

		var fixture = new Wield.Dom({
			parentNode: null
		});

		// If `e.parentNode.removeChild` is called it'll throw an exception
		// not an amazing test :/
		fixture.remove();
	});

	module( "Wield.Dom.prototype.replaceWith" );

	test( "replaceWith works", function() {
		var fixture = new Wield.Dom( document.getElementById("replace") ),
		replacement = document.createElement( "div" );

		ok( document.getElementById("replace") !== null, "the fixture is present" );
		equal( document.getElementById("replacement"), null, "the replacement is not yet present" );

		replacement.id = "replacement";
		deepEqual( fixture, fixture.replaceWith( replacement ), "replaceWith is chainable" );

		equal( document.getElementById("replace"), null, "the fixture is gone" );
		ok( document.getElementById("replacement") !== null, "the replacement is present" );
	});

	test( "replaceWith works as a standalone function", function() {
		var fixture = document.getElementById("replace"),
		replacement = document.createElement( "div" );

		ok( document.getElementById("replace") !== null, "the fixture is present" );
		equal( document.getElementById("replacement"), null, "the replacement is not yet present" );

		replacement.id = "replacement";
		Wield.Dom.prototype.replaceWith( fixture, replacement );

		equal( document.getElementById("replace"), null, "the fixture is gone" );
		ok( document.getElementById("replacement") !== null, "the replacement is present" );
	});

	module( "Wield.Dom.prototype.unwrap" );

	test( "unwrap works", function() {
		var fixture = new Wield.Dom( document.getElementById("unwrap") ),
			wrapped = document.getElementById( "wrapped" );

		equal( wrapped.parentNode.id, "unwrap", "the fixture is wrapped" );

		deepEqual( fixture, fixture.unwrap(), "unwrap is chainable" );

		equal( wrapped.parentNode.id, "qunit-fixture", "the fixture isn't wrapped" );
	});

	test( "unwrap works as a standalone function", function() {
		var fixture = document.getElementById( "unwrap" ),
			wrapped = document.getElementById( "wrapped" );

		equal( wrapped.parentNode.id, "unwrap", "the fixture is wrapped" );

		Wield.Dom.prototype.unwrap( fixture );

		equal( wrapped.parentNode.id, "qunit-fixture", "the fixture isn't wrapped" );
	});

	module( "Wield.Dom.prototype.wrap" );

	test( "wrap works", function() {
		var fixture = new Wield.Dom( document.getElementById("wrap") ),
			wrapper = document.getElementById( "wrapper" );

		equal( fixture.element.parentNode.id, "qunit-fixture", "the fixture isn't wrapped" );

		deepEqual( fixture, fixture.wrap( wrapper ), "wrap is chainable" );

		equal( fixture.element.parentNode.id, "wrapper", "the fixture is wrapped" );
	});

	test( "wrap with object receiver works with wield objects", function() {
		var fixture = new Wield.Dom( document.getElementById("wrap") ),
			wrapper = new Wield.Dom( document.getElementById("wrapper") );

		equal( fixture.element.parentNode.id, "qunit-fixture", "the fixture isn't wrapped" );

		fixture.wrap( wrapper );

		equal( fixture.element.parentNode.id, "wrapper", "the fixture is wrapped" );
	});

	test( "wrap works as a standalone function", function() {
		var fixture = new Wield.Dom( document.getElementById("wrap") ),
			wrapper = document.getElementById( "wrapper" );

		equal( fixture.element.parentNode.id, "qunit-fixture", "the fixture isn't wrapped" );

		Wield.Dom.prototype.wrap( fixture.element, wrapper );

		equal( fixture.element.parentNode.id, "wrapper", "the fixture is wrapped" );
	});

	test( "wrap uses innermost child of the wrapper", function() {
		var fixture = new Wield.Dom( document.getElementById("wrap") ),
			wrapper = new Wield.Dom( document.getElementById( "wrapper" ) );

		wrapper.append( document.createElement("span") );

		equal( fixture.element.parentNode.id, "qunit-fixture", "the fixture isn't wrapped" );

		fixture.wrap( wrapper.element );

		equal( fixture.element.parentNode.id, "", "the fixture is wrapped" );
		equal( fixture.element.parentNode.nodeName, "SPAN", "the fixture is wrapped" );
	});

}( window.Wield ));
<|endoftext|>


<commit_before>var _ = require('lodash');
var es = require('event-stream');
var Mailer = require('./mailer');

function Mail(opt) {
  if (!(this instanceof Mail)) {
    return new Mail(opt);
  }
  this.mailer = new Mailer(opt);
}

Mail.prototype.dest = function(glob, opt) {
  var m = this;

  opt = opt || {};

  return es.through(function write(file) {
    var self = this;

    if (file.contents) {
      var data = {};

      _.extend(data, file.meta);

      data.context.content = file.contents.toString();

      m.mailer.sendMail(data, function(error, info) {
        if (error) {
          self.emit('error', error);
        } else {
          self.emit('sent', info.response);
          self.emit('data', file);
        }
      });
    } else {
      self.emit('data', file);
    }
  });
};

module.exports = Mail;
<commit_msg>defend against missing context<commit_after>var _ = require('lodash');
var es = require('event-stream');
var Mailer = require('./mailer');

function Mail(opt) {
  if (!(this instanceof Mail)) {
    return new Mail(opt);
  }
  this.mailer = new Mailer(opt);
}

Mail.prototype.dest = function(glob, opt) {
  var m = this;

  opt = opt || {};

  return es.through(function write(file) {
    var self = this;

    if (file.contents) {
      var data = _.extend({context: {}}, file.data);

      data.context.content = file.contents.toString();

      m.mailer.sendMail(data, function(error, info) {
        if (error) {
          self.emit('error', error);
        } else {
          self.emit('sent', info.response);
          self.emit('data', file);
        }
      });
    } else {
      self.emit('data', file);
    }
  });
};

module.exports = Mail;
<|endoftext|>


<commit_before>import template from './template.js';
import { merge } from 'lodash';

const defaults = {
  filters: [],
  reincorporate: false,
  persistence: true,
  audit: false,
  salienceFormula  (a) { return a; }
};

class Improv {

  constructor (snippets, options = {}) {
    /* Constructor for Improv generators. */
    /* We don't want to mutate the options object we've been given; we don't know
    where it's been. */
    const spec = {}; merge(spec, defaults, options);
    this.snippets = snippets;
    this.filters = spec.filters;
    this.reincorporate = Boolean(spec.reincorporate);
    this.persistence = Boolean(spec.persistence);
    this.audit = Boolean(spec.audit);
    this.salienceFormula = spec.salienceFormula;
    this.history = [];
    this.tagHistory = [];

    if (this.audit) this.instantiateAuditData();
  }

  __gen (snippet, model) {
    /*
      Actually generate text. Separate from #gen() because we don't want to clear
      history or error-handling data while a call to #gen() hasn't finished
      returning
    */
    /* For the sake of better error handling, we try to keep an accurate record
       of what snippet is being generated at any given time. */
    if (typeof model.bindings === 'object' && model.bindings[snippet]) {
      // The snippet already exists in the model's bindings.
      return model.bindings[snippet];
    }
    const previousSnippet = this.currentSnippet;
    this.__currentSnippet = snippet;
    const chosenPhrase =
      this.selectPhrase(this.scoreFilter(this.applyFilters(snippet, model)), model);
    this.history.unshift(chosenPhrase);

    this.__currentSnippet = previousSnippet;
    if (this.audit) {
      const phraseTotal = this.__phraseAudit.get(snippet).get(chosenPhrase);
      this.__phraseAudit.get(snippet).set(chosenPhrase, phraseTotal + 1);
    }
    const output = template(chosenPhrase, model, this.__gen.bind(this));
    if (this.snippets[snippet].bind) {
      // Make sure the model has a bindings property
      if (typeof model.bindings === 'undefined') model.bindings = {};
      model.bindings[snippet] = output;
    }
    return output;
  }

  get phraseAudit () {
    /* This is a getter so that the internals of how auditing data is stored
       and calculated can change without changing the API. */
    if (!this.audit) throw new Error('Tried retriving audit from generator not in auditing mode.');
    return this.__phraseAudit;
  }

  gen (snippet, model = {}) {
    // Make sure the model has a tag property.
    if (typeof model.tags === 'undefined') model.tags = [];
    if (typeof this.snippets[snippet] === 'undefined') {
      throw new Error(`Tried generating snippet "${snippet}", but no such snippet exists in spec`);
    }
    const output = this.__gen(snippet, model);
    if (!this.persistence) {
      this.clearHistory(); this.clearTagHistory();
    }
    return output;
  }

  mergeTags (model, groupTags) {
    const mergeTag = function (a, b) {
      if (a.length < b.length) return b;
      return a;
    };
    groupTags.forEach(function (a) {
      const site = model.tags.findIndex(b => a[0] === b[0]);
      if (site === -1) {
        model.tags = model.tags.concat([a]);
      } else {
        model.tags[site] = mergeTag(model.tags[site], a);
      }
    });
  }

  selectPhrase (groups, model) {
    const phrases = this.flattenGroups(groups);
    if (phrases.length === 0) {
      if (this.audit) {
        console.log(groups);
        console.log(model);
      }
      throw new Error(`Ran out of phrases in ${groups} while generating ${this.__currentSnippet}`);
    }
    const chosen = phrases[Math.floor(Math.random() * phrases.length)];
    if (this.reincorporate) this.mergeTags(model, chosen[1]);
    if (Array.isArray(chosen[1])) {
      this.tagHistory = chosen[1].concat(this.tagHistory);
    }
    return chosen[0];
  }

  applyFiltersToGroup (group, model) {
    const that = this;
    let currentGroup = group;
    const output = { score: 0 };
    this.filters.forEach(function (cb) {
      if (output.score === null) return;
      const cbOutput = cb.call(that, currentGroup, model);
      let scoreOffset;
      if (Array.isArray(cbOutput)) {
        // We got a tuple, meaning the filter wants to modify the group before
        // moving on.
        scoreOffset = cbOutput[0];
        currentGroup = cbOutput[1];
      } else {
        scoreOffset = cbOutput;
      }
      if (scoreOffset === null) {
        output.score = null;
        return;
      }
      output.score += scoreOffset;
    });
    output.group = currentGroup;
    return output;
  }

  applyFilters (snippetName, model) {
    return this.snippets[snippetName].groups
      .map(group => this.applyFiltersToGroup(group, model))
      .filter(o => o.score !== null);
  }

  scoreFilter (groups) {
    // Filter out groups emptied out by dryness()
    const validGroups = groups.filter(g => g.group.phrases.length > 0);
    const maxScore = validGroups
      .reduce((currentMax, b) => b.score > currentMax ? b.score : currentMax,
      Number.NEGATIVE_INFINITY);
    const scoreThreshold = this.salienceFormula(maxScore);
    return validGroups.filter(o => o.score >= scoreThreshold);
  }

  flattenGroups (groups) {
    return groups
      .map(o => o.group.phrases.map(i => [i, o.group.tags]))
      .reduce((a, b) => a.concat(b), []);
  }

  clearHistory () { this.history = []; }

  clearTagHistory () { this.tagHistory = []; }

  instantiateAuditData () {
    /*
      Create and fill audit maps with starter data, ie zeroes.
    */
    this.__phraseAudit = new Map();
    const self = this;

    Object.keys(this.snippets).forEach(function (key) {
      self.phraseAudit.set(key, new Map());
      self.snippets[key].groups.forEach(function (group) {
        group.phrases.forEach(function (phrase) {
          self.__phraseAudit.get(key).set(phrase, 0);
        });
      });
    });
  }
}

import filters from './filters.js';

Improv.filters = filters;

export default Improv;
<commit_msg>Comments<commit_after>import template from './template.js';
import { merge } from 'lodash';

const defaults = {
  filters: [],
  reincorporate: false,
  persistence: true,
  audit: false,
  salienceFormula  (a) { return a; }
};

class Improv {

  constructor (snippets, options = {}) {
    /* Constructor for Improv generators. */
    /* We don't want to mutate the options object we've been given; we don't know
    where it's been. */
    const spec = {}; merge(spec, defaults, options);
    this.snippets = snippets;
    this.filters = spec.filters;
    this.reincorporate = Boolean(spec.reincorporate);
    this.persistence = Boolean(spec.persistence);
    this.audit = Boolean(spec.audit);
    this.salienceFormula = spec.salienceFormula;
    this.history = [];
    this.tagHistory = [];

    if (this.audit) this.instantiateAuditData();
  }

  __gen (snippet, model) {
    /*
      Actually generate text. Separate from #gen() because we don't want to clear
      history or error-handling data while a call to #gen() hasn't finished
      returning
    */
    /* For the sake of better error handling, we try to keep an accurate record
       of what snippet is being generated at any given time. */
    if (typeof model.bindings === 'object' && model.bindings[snippet]) {
      // The snippet already exists in the model's bindings.
      return model.bindings[snippet];
    }
    const previousSnippet = this.currentSnippet;
    this.__currentSnippet = snippet;
    const chosenPhrase =
      this.selectPhrase(this.scoreFilter(this.applyFilters(snippet, model)), model);
    this.history.unshift(chosenPhrase);

    this.__currentSnippet = previousSnippet;
    if (this.audit) {
      const phraseTotal = this.__phraseAudit.get(snippet).get(chosenPhrase);
      this.__phraseAudit.get(snippet).set(chosenPhrase, phraseTotal + 1);
    }
    const output = template(chosenPhrase, model, this.__gen.bind(this));
    if (this.snippets[snippet].bind) {
      // Make sure the model has a bindings property
      if (typeof model.bindings === 'undefined') model.bindings = {};
      model.bindings[snippet] = output;
    }
    return output;
  }

  get phraseAudit () {
    /* This is a getter so that the internals of how auditing data is stored
       and calculated can change without changing the API. */
    if (!this.audit) throw new Error('Tried retriving audit from generator not in auditing mode.');
    return this.__phraseAudit;
  }

  gen (snippet, model = {}) {
    /*
      Generate text (user-facing API). Since this function can recur, most of
      the heavy lifting is done in __gen().
    */
    // Make sure the model has a tag property.
    if (typeof model.tags === 'undefined') model.tags = [];
    if (typeof this.snippets[snippet] === 'undefined') {
      throw new Error(`Tried generating snippet "${snippet}", but no such snippet exists in spec`);
    }
    const output = this.__gen(snippet, model);
    if (!this.persistence) {
      this.clearHistory(); this.clearTagHistory();
    }
    return output;
  }

  mergeTags (model, groupTags) {
    /*
      Add a group's tags to the model, for reincorporation.
    */
    const mergeTag = function (a, b) {
      if (a.length < b.length) return b;
      return a;
    };
    groupTags.forEach(function (a) {
      const site = model.tags.findIndex(b => a[0] === b[0]);
      if (site === -1) {
        model.tags = model.tags.concat([a]);
      } else {
        model.tags[site] = mergeTag(model.tags[site], a);
      }
    });
  }

  selectPhrase (groups, model) {
    /*
      Once we have a list of suitable groups, finally select a phrase at random.
    */
    const phrases = this.flattenGroups(groups);
    if (phrases.length === 0) {
      if (this.audit) {
        console.log(groups);
        console.log(model);
      }
      throw new Error(`Ran out of phrases in ${groups} while generating ${this.__currentSnippet}`);
    }
    const chosen = phrases[Math.floor(Math.random() * phrases.length)];
    if (this.reincorporate) this.mergeTags(model, chosen[1]);
    if (Array.isArray(chosen[1])) {
      this.tagHistory = chosen[1].concat(this.tagHistory);
    }
    return chosen[0];
  }

  applyFiltersToGroup (group, model) {
    /*
      Run the filters through an individual group.
    */
    const that = this;
    let currentGroup = group;
    const output = { score: 0 };
    this.filters.forEach(function (cb) {
      if (output.score === null) return;
      const cbOutput = cb.call(that, currentGroup, model);
      let scoreOffset;
      if (Array.isArray(cbOutput)) {
        // We got a tuple, meaning the filter wants to modify the group before
        // moving on.
        scoreOffset = cbOutput[0];
        currentGroup = cbOutput[1];
      } else {
        scoreOffset = cbOutput;
      }
      if (scoreOffset === null) {
        output.score = null;
        return;
      }
      output.score += scoreOffset;
    });
    output.group = currentGroup;
    return output;
  }

  applyFilters (snippetName, model) {
    /*
      Starting with the raw list of groups, return a filtered list with
      scores.
    */
    return this.snippets[snippetName].groups
      .map(group => this.applyFiltersToGroup(group, model))
      .filter(o => o.score !== null);
  }

  scoreFilter (groups) {
    /*
      Starting with the scored list from applyFilters(), return a list that has
      invalid groups scrubbed out and only includes groups with a score past
      the threshold.
    */
    // Filter out groups emptied out by dryness()
    const validGroups = groups.filter(g => g.group.phrases.length > 0);
    const maxScore = validGroups
      .reduce((currentMax, b) => b.score > currentMax ? b.score : currentMax,
      Number.NEGATIVE_INFINITY);
    const scoreThreshold = this.salienceFormula(maxScore);
    return validGroups.filter(o => o.score >= scoreThreshold);
  }

  flattenGroups (groups) {
    /*
      Starting with a list of scored groups, flatten them into a simple list
      of phrases.
    */
    return groups
      .map(o => o.group.phrases.map(i => [i, o.group.tags]))
      .reduce((a, b) => a.concat(b), []);
  }

  clearHistory () { this.history = []; }

  clearTagHistory () { this.tagHistory = []; }

  instantiateAuditData () {
    /*
      Create and fill audit maps with starter data, ie zeroes.
    */
    this.__phraseAudit = new Map();
    const self = this;

    Object.keys(this.snippets).forEach(function (key) {
      self.phraseAudit.set(key, new Map());
      self.snippets[key].groups.forEach(function (group) {
        group.phrases.forEach(function (phrase) {
          self.__phraseAudit.get(key).set(phrase, 0);
        });
      });
    });
  }
}

import filters from './filters.js';

Improv.filters = filters;

export default Improv;
<|endoftext|>


<commit_before>'use strict';

require('mocha');
require('should');
var path = require('path');
var util = require('util');
var assert = require('assert');

// wrap `normalize` to log out results
function inspect(config) {
  var fn = require('..');
  config = config || {};
  return function(val) {
    var config = fn.apply(fn, arguments);
    if (config.debug === true) {
      console.log(util.inspect(config, null, 10));
    }
    return config;
  };
}

// change to `true` to log out results
var normalize = inspect({debug: false});

function toFile(file, dest) {
  file = file || {};
  if (typeof file === 'string') {
    var filepath = file;
    file = { path: filepath };
  }
  if (dest) file.dest = dest;
  file.relative = path.relative(process.cwd(), file.path);
  file.basename = path.basename(file.path);
  return file;
}

describe('normalize', function() {
  it('should throw an error on invalid arguments', function(cb) {
    try {
      normalize();
      cb(new Error('expected an error'));
    } catch(err) {
      assert(err);
      assert(err.message);
      assert(err.message === 'unsupported argument type: undefined');
      cb();
    }
  });

  it('should normalize src-dest mappings to a files array:', function() {
    var foo = normalize({'foo/': '*.js', 'bar/': '*.md'});
    var bar = normalize({'foo/': '*.js'});

    assert(Array.isArray(foo.files));
    assert(foo.files[0].src[0] === '*.js');
    assert(foo.files[0].dest === 'foo/');

    assert(bar.files[0].src[0] === '*.js');
    assert(bar.files[0].dest === 'foo/');

    assert(foo.files[1].src[0] === '*.md');
    assert(foo.files[1].dest === 'bar/');
  });

  it('should normalize a file object:', function() {
    var config = normalize(toFile(path.resolve('a/b/c.js'), 'dist/'));
    assert(Array.isArray(config.files));
    assert(config.files[0].src[0] === path.resolve('a/b/c.js'));
    assert(config.files[0].dest === 'dist/');
  });

  it('should normalize src-dest mappings on a files object:', function() {
    var config = normalize({
      files: {
        'foo/': '*.js',
        'bar/': '*.md'
      }
    });

    assert(Array.isArray(config.files));
    assert(config.files[0].src[0] === '*.js');
    assert(config.files[0].dest === 'foo/');

    assert(config.files[1].src[0] === '*.md');
    assert(config.files[1].dest === 'bar/');
  });

  it('should throw an error when `files` is an invalid type', function(cb) {
    try {
      normalize({files: 'foo'});
      cb(new Error('expected an error'));
    } catch (err) {
      assert(err);
      assert(err.message === 'expected "files" to be an array or object');
      cb();
    }
  });

  it('should normalize the first argument to src when it is a string:', function() {
    var config = normalize('*.js');
    assert(config.files[0].src[0] === '*.js');
  });

  it('should work when no src is defined:', function() {
    var config = normalize({dest: 'out/'});
    assert(config.files[0].dest === 'out/');
  });

  it('should normalize the first argument to src when it is an array:', function() {
    assert(normalize(['*.js']).files[0].src[0] === '*.js');
    assert(normalize(['foo', 'bar', '*.js']).files[0].src[0] === 'foo');
  });

  it('should normalize an array of src-dest mappings:', function() {
    var config = normalize([
      {'a/': ['a/*.js']},
      {'b/': ['b/*.js']},
      {'c/': ['c/*.js']}
    ]);

    assert(config.files[0].src[0] === 'a/*.js');
    assert(config.files[0].dest === 'a/');
    assert(config.files[1].src[0] === 'b/*.js');
    assert(config.files[1].dest === 'b/');
    assert(config.files[2].src[0] === 'c/*.js');
    assert(config.files[2].dest === 'c/');
  });

  it('should convert the second arg to dest when it is a string:', function() {
    var config = normalize('*.js', 'foo/');
    assert(config.files[0].src[0] === '*.js');
    assert(config.files[0].dest === 'foo/');
  });

  it('should dest from the second arg when it is an object:', function() {
    var config = normalize('*.js', {dest: 'foo/'});
    assert(config.files[0].src[0] === '*.js');
    assert(config.files[0].dest === 'foo/');
  });

  it('should convert the second arg to dest when the third args is an object:', function() {
    var config = normalize('*.js', 'foo/', {cwd: ''});
    assert(config.files[0].src[0] === '*.js');
    assert(config.files[0].dest === 'foo/');
    assert(config.files[0].options.cwd === '');
  });

  it('should arrayify src when args are converted:', function() {
    var config = normalize('*.js', 'foo/');

    assert(Array.isArray(config.files[0].src));
    assert(config.files[0].src[0] === '*.js');
  });

  it('should support src and dest being passed on options:', function() {
    // this allows a default src/dest to be passed from main options
    // of consuming libraries
    var config = normalize({options: {src: '*.js', dest: 'foo/'}});
    assert(Array.isArray(config.files[0].src));
    assert(config.files[0].src[0] === '*.js');
  });

  it('should flatten nested "options.options" objects:', function() {
    var config = normalize('*.js', 'dist/', {options: {cwd: 'foo'}});
    assert(config.files[0].options);
    assert(!config.files[0].options.options);
    assert(config.files[0].options.cwd === 'foo');
  });

  it('should not lose options when a second arg is passed:', function() {
    var config = normalize({
      options: {
        expand: true,
        cwd: 'a'
      },
      src: ['**/*.txt'],
      dest: 'dest'
    }, {});

    assert.equal(typeof config.options, 'object');
    assert.equal(Array.isArray(config.files), true);
    assert(config.options.expand === true);
    assert(config.options.cwd === 'a');
    assert(config.files.length === 1);
    assert(config.files[0].dest = 'dest');
  });

  it('should not lose options when a third arg is passed:', function() {
    var config = normalize({
      options: {
        expand: true,
        cwd: 'a'
      },
      src: ['**/*.txt'],
      dest: 'dest'
    }, {}, {});

    assert.equal(typeof config.options, 'object');
    assert.equal(Array.isArray(config.files), true);
    assert(config.options.expand === true);
    assert(config.options.cwd === 'a');
    assert(config.files.length === 1);
    assert(config.files[0].dest = 'dest');
  });

  it('should not lose options when dest is a string:', function() {
    var config = normalize({
      options: {
        expand: true,
        cwd: 'a'
      },
      src: ['**/*.txt']
    }, 'dest', {});

    assert.equal(typeof config.options, 'object');
    assert.equal(Array.isArray(config.files), true);
    assert(config.options.expand === true);
    assert(config.options.cwd === 'a');
    assert(config.files.length === 1);
    assert(config.files[0].dest = 'dest');
  });

  it('should extend options defined on first and last args', function() {
    var config = normalize({
      options: {
        expand: true,
        cwd: 'a'
      },
      src: ['**/*.txt']
    }, 'dest', {foo: 'bar'});

    assert.equal(typeof config.options, 'object');
    assert.equal(Array.isArray(config.files), true);
    assert(config.options.foo === 'bar');
    assert(config.options.expand === true);
    assert(config.options.cwd === 'a');
    assert(config.files.length === 1);
    assert(config.files[0].dest = 'dest');
  });

  it('should extend options defined on first and second args', function() {
    var config = normalize({
      options: {
        expand: true,
        cwd: 'a'
      },
      src: ['**/*.txt'],
      dest: 'dest'
    }, {foo: 'bar'});

    assert.equal(typeof config.options, 'object');
    assert.equal(Array.isArray(config.files), true);
    assert(config.options.foo === 'bar');
    assert(config.options.expand === true);
    assert(config.options.cwd === 'a');
    assert(config.files.length === 1);
    assert(config.files[0].dest = 'dest');
  });

  it('should convert an object with src-dest to a files array:', function() {
    var config = normalize({dest: 'foo/', src: '*.js'});
    assert(Array.isArray(config.files));
    assert(Array.isArray(config.files[0].src));
    assert(config.files[0].src[0] === '*.js');
    assert(config.files[0].dest === 'foo/');
  });

  it('should support files as an array:', function() {
    var config = normalize({files: ['*.js']});
    assert(config.files[0].src[0] === '*.js');
  });

  it('should support files as an object:', function() {
    var config = normalize({files: {'dist/': ['*.js']}});
    assert(config.files[0].src[0] === '*.js');
    assert(config.files[0].dest === 'dist/');
  });

  describe('options', function() {
    it('should get options from an options object:', function() {
      var config = normalize({dest: 'foo/', src: ['*.js'], options: {cwd: 'c'}});
      assert(config.options.cwd === 'c');
      assert(config.files[0].options.cwd === 'c');
    });

    it('should pick options properties from an object:', function() {
      var config = normalize({dest: 'foo/', src: '*.js', cwd: 'b'});
      assert(config.options.cwd === 'b');
      assert(config.files[0].options.cwd === 'b');
    });

    it('should pick options properties from a files array:', function() {
      var config = normalize({files: [{'foo/': '*.js', cwd: 'f'}]});
      assert(config.files[0].options.cwd === 'f');
    });

    it('should pick options properties from a files object:', function() {
      var config = normalize({files: {'foo/': '*.js', cwd: 'e'}});
      assert(config.files[0].options.cwd === 'e');
    });

    it('should pick options properties from src-dest mapping', function() {
      var config = normalize({'foo/': '*.js', cwd: 'a'});
      assert(config.options.cwd === 'a');
      assert(config.files[0].options.cwd === 'a');
    });

    it('should extend "target" options onto objects:', function() {
      var config = normalize({dest: 'foo/', src: '*.js'}, {process: true});

      assert(Array.isArray(config.files));
      assert(Array.isArray(config.files[0].src));
      assert(config.files[0].src[0] === '*.js');
      assert(config.files[0].dest === 'foo/');
      assert(config.options.process === true);
    });

    it('should extend "context" options onto config:', function() {
      var ctx = {options: {process: true}};
      var fn = require('..');
      var config = fn.call(ctx, {dest: 'foo/', src: '*.js'});

      assert(Array.isArray(config.files));
      assert(Array.isArray(config.files[0].src));
      assert(config.files[0].src[0] === '*.js');
      assert(config.files[0].dest === 'foo/');
      assert(config.options.process === true);
    });

    it('should not format files objects when `format` is false:', function() {
      var ctx = {options: {format: false}};
      var fn = require('..');
      var config = fn.call(ctx, {dest: 'foo/', src: '*.js'});

      assert(Array.isArray(config.files));
      assert(Array.isArray(config.files[0].src));
      assert(config.files[0].src[0] === '*.js');
      assert(config.files[0].dest === 'foo/');
      assert(config.options.format === false);
    });

    it('should format files objects by default:', function() {
      var config = normalize({dest: 'a/', src: '*.js', options: {cwd: 'b/'}});
      var keys = ['options', 'src', 'dest'];
      var i = -1;

      for (var key in config.files[0]) {
        assert(keys[++i] === key);
      }
    });
  });
});
<commit_msg>organizes unit tests, adds more related to arbitrary prop bugfix<commit_after>'use strict';

require('mocha');
require('should');
var path = require('path');
var util = require('util');
var assert = require('assert');

// wrap `normalize` to log out results
function inspect(config) {
  var fn = require('..');
  config = config || {};
  return function(val) {
    var config = fn.apply(fn, arguments);
    if (config.debug === true) {
      console.log(util.inspect(config, null, 10));
    }
    return config;
  };
}

// change to `true` to log out results
var normalize = inspect({debug: false});

function toFile(file, dest) {
  file = file || {};
  if (typeof file === 'string') {
    var filepath = file;
    file = { path: filepath };
  }
  if (dest) file.dest = dest;
  file.relative = path.relative(process.cwd(), file.path);
  file.basename = path.basename(file.path);
  return file;
}

describe('normalize', function() {
  describe('errors', function(cb) {
    it('should throw an error on invalid arguments', function(cb) {
      try {
        normalize();
        cb(new Error('expected an error'));
      } catch(err) {
        assert(err);
        assert(err.message);
        assert(err.message === 'unsupported argument type: undefined');
        cb();
      }
    });

    it('should throw an error when `files` is an invalid type', function(cb) {
      try {
        normalize({files: 'foo'});
        cb(new Error('expected an error'));
      } catch (err) {
        assert(err);
        assert(err.message === 'expected "files" to be an array or object');
        cb();
      }
    });
  });

  describe('arguments list', function() {
    it('should normalize the first argument to src when it is a string', function() {
      var config = normalize('*.js');
      assert(config.files[0].src[0] === '*.js');
    });

    it('should normalize the first argument to src when it is an array', function() {
      assert(normalize(['*.js']).files[0].src[0] === '*.js');
      assert(normalize(['foo', 'bar', '*.js']).files[0].src[0] === 'foo');
    });

    it('should convert the second arg to dest when it is a string', function() {
      var config = normalize('*.js', 'foo/');
      assert(config.files[0].src[0] === '*.js');
      assert(config.files[0].dest === 'foo/');
    });

    it('should dest from the second arg when it is an object', function() {
      var config = normalize('*.js', {dest: 'foo/'});
      assert(config.files[0].src[0] === '*.js');
      assert(config.files[0].dest === 'foo/');
    });

    it('should convert the second arg to dest when the third args is an object', function() {
      var config = normalize('*.js', 'foo/', {cwd: ''});
      assert(config.files[0].src[0] === '*.js');
      assert(config.files[0].dest === 'foo/');
      assert(config.files[0].options.cwd === '');
    });

    it('should arrayify src when args are converted', function() {
      var config = normalize('*.js', 'foo/');
      assert(Array.isArray(config.files[0].src));
      assert(config.files[0].src[0] === '*.js');
    });

    it('should flatten nested "options.options" objects', function() {
      var config = normalize('*.js', 'dist/', {options: {cwd: 'foo'}});
      assert(config.files[0].options);
      assert(!config.files[0].options.options);
      assert(config.files[0].options.cwd === 'foo');
    });
  });

  describe('src-dest on options', function() {
    it('should support src and dest defined on options', function() {
      // this allows a default src/dest to be passed from main options
      // of consuming libraries
      var config = normalize({options: {src: '*.js', dest: 'foo/'}});
      assert(Array.isArray(config.files[0].src));
      assert(config.files[0].src[0] === '*.js');
    });

    it('should support files objects defined on options', function() {
      var config = normalize({options: {files: {src: '*.js', dest: 'foo/'}}});
      assert(Array.isArray(config.files[0].src));
      assert(config.files[0].src[0] === '*.js');
    });

    it('should support files arrays defined on options', function() {
      var config = normalize({options: {files: [{src: '*.js', dest: 'foo/'}]}});
      assert(Array.isArray(config.files[0].src));
      assert(config.files[0].src[0] === '*.js');
    });
  });

  describe('src-dest mappings', function() {
    it('should normalize src-dest mappings to a files array', function() {
      var foo = normalize({'foo/': '*.js', 'bar/': '*.md'});
      var bar = normalize({'foo/': '*.js'});

      assert(Array.isArray(foo.files));
      assert(foo.files[0].src[0] === '*.js');
      assert(foo.files[0].dest === 'foo/');

      assert(bar.files[0].src[0] === '*.js');
      assert(bar.files[0].dest === 'foo/');

      assert(foo.files[1].src[0] === '*.md');
      assert(foo.files[1].dest === 'bar/');
    });

    it('should normalize a (vinyl-like) file object', function() {
      var file = toFile(path.resolve('a/b/c.js'), 'dist/');
      var config = normalize(file);
      assert(Array.isArray(config.files));
      assert(config.files[0].src[0] === path.resolve('a/b/c.js'));
      assert(config.files[0].dest === 'dist/');
    });

    it('should retail arbitrary properties', function() {
      var config = normalize({
        data: {title: 'My Site'},
        src: '*.js',
        dest: 'foo/'
      });
      assert(config.data);
      assert(config.data.title === 'My Site');
    });

    it('should work when no dest is defined', function() {
      var config = normalize({src: '*.js'});
      assert(config.files[0].src[0].length);
    });

    it('should work when no src is defined', function() {
      var config = normalize({dest: 'out/'});
      assert(config.files[0].dest === 'out/');
    });

    it('should keep options when a second arg is passed', function() {
      var config = normalize({
        options: {
          expand: true,
          cwd: 'a'
        },
        src: ['**/*.txt'],
        dest: 'dest'
      }, {});

      assert.equal(typeof config.options, 'object');
      assert.equal(Array.isArray(config.files), true);
      assert(config.options.expand === true);
      assert(config.options.cwd === 'a');
      assert(config.files.length === 1);
      assert(config.files[0].dest = 'dest');
    });

    it('should keep options when a third arg is passed', function() {
      var config = normalize({
        options: {
          expand: true,
          cwd: 'a'
        },
        src: ['**/*.txt'],
        dest: 'dest'
      }, {}, {});

      assert.equal(typeof config.options, 'object');
      assert.equal(Array.isArray(config.files), true);
      assert(config.options.expand === true);
      assert(config.options.cwd === 'a');
      assert(config.files.length === 1);
      assert(config.files[0].dest = 'dest');
    });

    it('should keep options when dest is a string', function() {
      var config = normalize({
        options: {
          expand: true,
          cwd: 'a'
        },
        src: ['**/*.txt']
      }, 'dest', {});

      assert.equal(typeof config.options, 'object');
      assert.equal(Array.isArray(config.files), true);
      assert(config.options.expand === true);
      assert(config.options.cwd === 'a');
      assert(config.files.length === 1);
      assert(config.files[0].dest = 'dest');
    });

    it('should extend options defined on first and last args', function() {
      var config = normalize({
        options: {
          expand: true,
          cwd: 'a'
        },
        src: ['**/*.txt']
      }, 'dest', {foo: 'bar'});

      assert.equal(typeof config.options, 'object');
      assert.equal(Array.isArray(config.files), true);
      assert(config.options.foo === 'bar');
      assert(config.options.expand === true);
      assert(config.options.cwd === 'a');
      assert(config.files.length === 1);
      assert(config.files[0].dest = 'dest');
    });

    it('should extend options defined on first and second args', function() {
      var config = normalize({
        options: {
          expand: true,
          cwd: 'a'
        },
        src: ['**/*.txt'],
        dest: 'dest'
      }, {foo: 'bar'});

      assert.equal(typeof config.options, 'object');
      assert.equal(Array.isArray(config.files), true);
      assert(config.options.foo === 'bar');
      assert(config.options.expand === true);
      assert(config.options.cwd === 'a');
      assert(config.files.length === 1);
      assert(config.files[0].dest = 'dest');
    });

    it('should convert an object with src-dest to a files array', function() {
      var config = normalize({dest: 'foo/', src: '*.js'});
      assert(Array.isArray(config.files));
      assert(Array.isArray(config.files[0].src));
      assert(config.files[0].src[0] === '*.js');
      assert(config.files[0].dest === 'foo/');
    });
  });

  describe('files objects', function() {
    it('should support files as an object', function() {
      var config = normalize({files: {'dist/': ['*.js']}});
      assert(config.files[0].src[0] === '*.js');
      assert(config.files[0].dest === 'dist/');
    });

    it('should retain arbitrary properties', function() {
      var config = normalize({
        data: {title: 'My Site'},
        files: {
          data: {title: 'My Blog'},
          src: '*.js',
          dest: 'foo/'
        }
      });

      assert(config.data);
      assert(config.data.title);
      assert(config.data.title === 'My Site');
      assert(config.files[0].data);
      assert(config.files[0].data.title);
      assert(config.files[0].data.title === 'My Blog');
    });
  });

  describe('files glob', function() {
    it('should support files as an array', function() {
      var config = normalize({files: ['*.js']});
      assert(config.files[0].src[0] === '*.js');
    });
  });

  describe('files object > src-dest mappings', function() {
    it('should normalize src-dest mappings on a files object', function() {
      var config = normalize({
        files: {
          'foo/': '*.js',
          'bar/': '*.md'
        }
      });

      assert(Array.isArray(config.files));
      assert(config.files[0].src[0] === '*.js');
      assert(config.files[0].dest === 'foo/');
      assert(config.files[1].src[0] === '*.md');
      assert(config.files[1].dest === 'bar/');
    });

    it('should retain arbitrary properties', function() {
      var config = normalize({
        data: {title: 'My Site'},
        files: {
          'foo/': '*.js',
          'bar/': '*.md'
        }
      });

      assert(config.data);
      assert(config.data.title);
      assert(Array.isArray(config.files));
      assert(config.files[0].src[0] === '*.js');
      assert(config.files[0].dest === 'foo/');
      assert(config.files[1].src[0] === '*.md');
      assert(config.files[1].dest === 'bar/');
    });
  });

  describe('files array > src-dest mappings', function() {
    it('should normalize src-dest mappings on a files array', function() {
      var config = normalize([
        {'a/': ['a/*.js']},
        {'b/': ['b/*.js']},
        {'c/': ['c/*.js']}
      ]);

      assert(config.files[0].src[0] === 'a/*.js');
      assert(config.files[0].dest === 'a/');
      assert(config.files[1].src[0] === 'b/*.js');
      assert(config.files[1].dest === 'b/');
      assert(config.files[2].src[0] === 'c/*.js');
      assert(config.files[2].dest === 'c/');
    });

    it('should retain arbitrary properties', function() {
      var config = normalize([
        {'a/': ['a/*.js']},
        {'b/': ['b/*.js']},
        {'c/': ['c/*.js']}
      ], {data: {title: 'My Site'}});

      assert(config.options.data);
      assert(config.options.data.title);
      assert(config.files[0].src[0] === 'a/*.js');
      assert(config.files[0].dest === 'a/');
      assert(config.files[1].src[0] === 'b/*.js');
      assert(config.files[1].dest === 'b/');
      assert(config.files[2].src[0] === 'c/*.js');
      assert(config.files[2].dest === 'c/');
    });
  });

  describe('files arrays', function() {
    it('should support files arrays', function() {
      var config = normalize({files: [{src: '*.js', dest: 'foo/'}]});
      assert(Array.isArray(config.files[0].src));
      assert(config.files[0].src[0] === '*.js');
    });

    it('should retain arbitrary properties', function() {
      var config = normalize({
        files: [
          {
            data: {title: 'My Blog'},
            src: '*.js',
            dest: 'foo/'
          }
        ]
      });

      assert(!config.data);
      assert(config.files[0].data);
      assert(config.files[0].data.title);
    });
  });

  describe('options', function() {
    it('should get options from an options object', function() {
      var config = normalize({dest: 'foo/', src: ['*.js'], options: {cwd: 'c'}});
      assert(config.options.cwd === 'c');
      assert(config.files[0].options.cwd === 'c');
    });

    it('should pick options properties from an object', function() {
      var config = normalize({dest: 'foo/', src: '*.js', cwd: 'b'});
      assert(config.options.cwd === 'b');
      assert(config.files[0].options.cwd === 'b');
    });

    it('should pick options properties from a files array', function() {
      var config = normalize({files: [{'foo/': '*.js', cwd: 'f'}]});
      assert(config.files[0].options.cwd === 'f');
    });

    it('should pick options properties from a files object', function() {
      var config = normalize({files: {'foo/': '*.js', cwd: 'e'}});
      assert(config.files[0].options.cwd === 'e');
    });

    it('should pick options properties from src-dest mapping', function() {
      var config = normalize({'foo/': '*.js', cwd: 'a'});
      assert(config.options.cwd === 'a');
      assert(config.files[0].options.cwd === 'a');
    });

    it('should extend "target" options onto objects', function() {
      var config = normalize({dest: 'foo/', src: '*.js'}, {process: true});

      assert(Array.isArray(config.files));
      assert(Array.isArray(config.files[0].src));
      assert(config.files[0].src[0] === '*.js');
      assert(config.files[0].dest === 'foo/');
      assert(config.options.process === true);
    });

    it('should extend "context" options onto config', function() {
      var ctx = {options: {process: true}};
      var fn = require('..');
      var config = fn.call(ctx, {dest: 'foo/', src: '*.js'});

      assert(Array.isArray(config.files));
      assert(Array.isArray(config.files[0].src));
      assert(config.files[0].src[0] === '*.js');
      assert(config.files[0].dest === 'foo/');
      assert(config.options.process === true);
    });

    it('should not format files objects when `format` is false', function() {
      var ctx = {options: {format: false}};
      var fn = require('..');
      var config = fn.call(ctx, {dest: 'foo/', src: '*.js'});

      assert(Array.isArray(config.files));
      assert(Array.isArray(config.files[0].src));
      assert(config.files[0].src[0] === '*.js');
      assert(config.files[0].dest === 'foo/');
      assert(config.options.format === false);
    });

    it('should format files objects by default', function() {
      var config = normalize({dest: 'a/', src: '*.js', options: {cwd: 'b/'}});
      var keys = ['options', 'src', 'dest'];
      var i = -1;

      for (var key in config.files[0]) {
        assert(keys[++i] === key);
      }
    });
  });
});
<|endoftext|>


<commit_before>"use strict";

var sass = require("node-sass");
var through = require("through2");
var path = require("path");
var extend = require('util')._extend;

module.exports = function (fileName, globalOptions) {
    if (!/(\.scss|\.css)$/i.test(fileName)) {
        return through();
    }

    var inputString = "";

    return through(
        function (chunk) {
            inputString += chunk;
        },
        function () {
            var options, css, moduleBody, self;

            self = this;

            // new copy of globalOptions for each file
            options = extend({}, globalOptions || {});
            options.includePaths = extend([], (globalOptions ? globalOptions.includePaths : {}) || []);

            options.data = inputString;
            options.includePaths.unshift(path.dirname(fileName));
            options.success = function(css) {
				var escapedCSS = JSON.stringify(css);

				moduleBody = options['auto-inject']
						? "var css = " + escapedCSS + "; (require("+JSON.stringify(__dirname)+"))(css); module.exports = css;"
						: "module.exports = " + escapedCSS;

				self.push(moduleBody);
				self.push(null);
			};

            try {
                sass.render(options);
            } catch (error) {
				console.log('error', error);
                self.emit('error', (error instanceof Error) ? error : new Error(error));
                return;
            }
        }
    );
};
<commit_msg>Edits to make this thing not-blocking. Browserify will hang when the next() callback is not called<commit_after>"use strict";

var sass = require("node-sass");
var through = require("through2");
var path = require("path");
var extend = require('util')._extend;

module.exports = function (fileName, globalOptions) {
    if (!/(\.scss|\.css)$/i.test(fileName)) {
        return through();
    }

    var buffer = "";

    return through(
        function (chunk, enc, next) {
            buffer += chunk;
            next();
        },
        function (done) {
            var options, css, moduleBody, self;

            self = this;

            // new copy of globalOptions for each file
            options = extend({}, globalOptions || {});
            options.includePaths = extend([], (globalOptions ? globalOptions.includePaths : {}) || []);

            options.data = buffer;
            options.includePaths.unshift(path.dirname(fileName));
            options.success = function (css) {
                var escapedCSS = JSON.stringify(css);

                moduleBody = options['auto-inject'] ? "var css = " + escapedCSS + "; (require(" + JSON.stringify(__dirname) + "))(css); module.exports = css;" : "module.exports = " + escapedCSS;

                self.push(moduleBody);
                self.push(null);
                done();
            };

            try {
                sass.render(options);
            } catch (error) {
                console.log('error', error);
                self.emit('error', (error instanceof Error) ? error : new Error(error));
                done();
            }
        }
    );
};<|endoftext|>


<commit_before>var expect = require('chai').expect;
var db = require(__dirname+'/../database');
var users = db.get('users');
var posts = db.get('posts');
var app = require(__dirname+'/../frozen-forest');

app.ready = function() {
  before(function (done) {
    users.insert({
      provider: 'localhost',
      identifier: '1337',
      email: 'test@localhost',
      name: 'testuser',
      apiKey: 'thetestuserapikey'
    });
    users.insert({
      provider: 'localhost',
      identifier: '1338',
      email: 'someone@localhost',
      name: 'someone else',
      apiKey: 'theotheruserapikey'
    });
    users.insert({
      provider: 'localhost',
      identifier: '1339',
      email: 'someoneelse@localhost',
      name: 'someone else',
      apiKey: 'yetanotherkey'

    }, function (err, testuser) {
      if (err) {
        done(err);
        return;
      }
      for (var lat = -90; lat < 90; lat+=2) {
        for (var long = -180; long < 180; long+=2) {
          posts.insert({
            type: 'Feature',
            geometry : {
              type: 'Point',
              coordinates: [long, lat]
            },
            properties: {
              message: 'Hello',
              tags: [],
              relevance: 100,
              user: {
                _id: testuser._id,
                name: testuser.name
              }
            }
          });
        }
      }
      done();
    });
  });

  after(function (done) {
    users.findOne({apiKey: 'thetestuserapikey'}, function (err, testuser) {
      posts.remove({user: testuser._id});
      users.remove(testuser);
      users.findOne({apiKey: 'theotheruserapikey'}, function (err, testuser) {
        posts.remove({user: testuser._id});
        users.remove(testuser);
        users.findOne({apiKey: 'yetanotherkey'}, function (err, testuser) {
          posts.remove({user: testuser._id});
          users.remove(testuser);
          done();
        });
      });
    });
  });
}
<commit_msg>the test users are now added to the database in the correct order<commit_after>var expect = require('chai').expect;
var db = require(__dirname+'/../database');
var users = db.get('users');
var posts = db.get('posts');
var app = require(__dirname+'/../frozen-forest');

app.ready = function() {
  before(function (done) {
    users.insert({
      provider: 'localhost',
      identifier: '1337',
      email: 'test@localhost',
      name: 'testuser',
      apiKey: 'thetestuserapikey'
    }, function(){
      users.insert({
        provider: 'localhost',
        identifier: '1338',
        email: 'someone@localhost',
        name: 'someone else',
        apiKey: 'theotheruserapikey'
      }, function(){
        users.insert({
          provider: 'localhost',
          identifier: '1339',
          email: 'someoneelse@localhost',
          name: 'someone else',
          apiKey: 'yetanotherkey'

        }, function (err, testuser) {
          if (err) {
            done(err);
            return;
          }
          for (var lat = -90; lat < 90; lat+=2) {
            for (var long = -180; long < 180; long+=2) {
              posts.insert({
                type: 'Feature',
                geometry : {
                  type: 'Point',
                  coordinates: [long, lat]
                },
                properties: {
                  message: 'Hello',
                  tags: [],
                  relevance: 100,
                  user: {
                    _id: testuser._id,
                    name: testuser.name
                  }
                }
              });
            }
          }
          done();
        });
      });
    });
  });

  after(function (done) {
    users.findOne({apiKey: 'thetestuserapikey'}, function (err, testuser) {
      posts.remove({user: testuser._id});
      users.remove(testuser);
      users.findOne({apiKey: 'theotheruserapikey'}, function (err, testuser) {
        posts.remove({user: testuser._id});
        users.remove(testuser);
        users.findOne({apiKey: 'yetanotherkey'}, function (err, testuser) {
          posts.remove({user: testuser._id});
          users.remove(testuser);
          done();
        });
      });
    });
  });
}
<|endoftext|>


<commit_before>
// shuffle for character bar

// function shuffle(o){
//     for(var j, x, i = o.length; i; j = parseInt(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x);
//     return o;
// };
//charbarkeys = shuffle(charbarkeys);

// calculate totals for percentages, then set up charbar
// check whether character is set up in characters, else don't add

$(document).ready(function() {

	var charstotal = 0;
	var colorspans = "";
	var isonlinespans = '
 > Clients connected (filtered)

';

	$.get("/charinfo.json", function(chars) {

		var charbarkeys = Object.keys(chars);

		for (var i = 0; i < charbarkeys.length; ++i) {
			try {
				var name = charbarkeys[i];
				var exists = characters[name].color;
				charstotal = charstotal + chars[charbarkeys[i]];
			} catch(e) {
				console.log("Error: " + e);
			}
		}
		for (var i = 0; i < charbarkeys.length; ++i) {
			var current = chars[charbarkeys[i]];
			var name = charbarkeys[i];
			var percent = (current / charstotal) * 100;
			try {
				uppername = name.replace(/^(\w)/, function(a,x){ return a.replace(x,x.toUpperCase()); });
				uppername = uppername.replace(/\s(\w)/, function(a,x){ return a.replace(x,x.toUpperCase()); });
				escapedname = name.replace(/[\(\)\/\s]/, '');
				colorspans = colorspans + '';
				isonlinespans = isonlinespans + ' x '+ current + ''
				} catch(e) {
					console.log("Error: " + e);
				}
		}

		$('#charbar').html(colorspans);
		$('#isonlineblock').html(isonlinespans);
			$(function(){
			   function slide_in(){
				  $('#charbar span').removeClass("slidein");
			   };
			   window.setTimeout( slide_in, 100 );
			});

		if($('input[name="picky"]').is(':checked')) {
				$('#isonlineblock .isonlinechar').hide();
				$('#isonlineblock .iofiltered').show();
				var pickySync = $('#picky-icon input[class="butty"]')
				for (i=0; i<pickySync.length; i++) {
					if($(pickySync[i]).is(':checked')) {
						$('#isonlineblock span[data-char="' + $(pickySync[i]).attr('name') + '"]').show();
					}
				}
			} else {
				$('#isonlineblock .isonlinechar').show();
				$('#isonlineblock .iofiltered').hide();
			}

	});
});<commit_msg>fixing the escaping on this regex<commit_after>
// shuffle for character bar

// function shuffle(o){
//     for(var j, x, i = o.length; i; j = parseInt(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x);
//     return o;
// };
//charbarkeys = shuffle(charbarkeys);

// calculate totals for percentages, then set up charbar
// check whether character is set up in characters, else don't add

$(document).ready(function() {

	var charstotal = 0;
	var colorspans = "";
	var isonlinespans = '
 > Clients connected (filtered)

';

	$.get("/charinfo.json", function(chars) {

		var charbarkeys = Object.keys(chars);

		for (var i = 0; i < charbarkeys.length; ++i) {
			try {
				var name = charbarkeys[i];
				var exists = characters[name].color;
				charstotal = charstotal + chars[charbarkeys[i]];
			} catch(e) {
				console.log("Error: " + e);
			}
		}
		for (var i = 0; i < charbarkeys.length; ++i) {
			var current = chars[charbarkeys[i]];
			var name = charbarkeys[i];
			var percent = (current / charstotal) * 100;
			try {
				uppername = name.replace(/^(\w)/, function(a,x){ return a.replace(x,x.toUpperCase()); });
				uppername = uppername.replace(/\s(\w)/, function(a,x){ return a.replace(x,x.toUpperCase()); });
				escapedname = name.replace(/[()/\s]/, '');
				colorspans = colorspans + '';
				isonlinespans = isonlinespans + ' x '+ current + ''
				} catch(e) {
					console.log("Error: " + e);
				}
		}

		$('#charbar').html(colorspans);
		$('#isonlineblock').html(isonlinespans);
			$(function(){
			   function slide_in(){
				  $('#charbar span').removeClass("slidein");
			   };
			   window.setTimeout( slide_in, 100 );
			});

		if($('input[name="picky"]').is(':checked')) {
				$('#isonlineblock .isonlinechar').hide();
				$('#isonlineblock .iofiltered').show();
				var pickySync = $('#picky-icon input[class="butty"]')
				for (i=0; i<pickySync.length; i++) {
					if($(pickySync[i]).is(':checked')) {
						$('#isonlineblock span[data-char="' + $(pickySync[i]).attr('name') + '"]').show();
					}
				}
			} else {
				$('#isonlineblock .isonlinechar').show();
				$('#isonlineblock .iofiltered').hide();
			}

	});
});<|endoftext|>


<commit_before>var assert = require("assert");
var express = require("express");
var r = require("supertest");
var parseString = require('xml2js').parseString;
var should = require('should');
/**
* Test
*
* @param {Object} req - The request value.
**/
process.env.PORT = 4000;
var app = require("../app.js");

describe('General incoming request', function(){

  it('should respond with xml', function(done){
    r(app)
    .post('/msg')
    .send({Body:"8004"})
    .set('Accept', 'application/xml')
    .expect(200)
    .end(function(err, res){
      if (err) throw err;
      done();
    });
  });

  it('for a light rail stop named 8004', function(done){
    r(app)
    .post('/msg')
    .send({Body:"8004"})
    .set('Accept', 'application/xml')
    .expect(200)
    .end(function(err, res){
      if (err) throw err;
      should.not.exist(err);

      // cleans utf8 parsing for xml in form
      // see http://www.multiasking.com/blog/xml2js-sax-js-non-whitespace-before-first-tag/
      var xml = res.text.replace("\ufeff", "");
      parseString(xml, function (err, ouput) {
         var parse = ouput.Response.Message[0];
         parse.should.startWith('Light rail ');
      });
      done();
    });
  });
  it('should decode a bus stop for an address in norfolk ', function(done){
    r(app)
    .post('/msg')
    .send({Body:"111 Granby street "})
    .set('Accept', 'application/xml')
    .expect(200)
    .end(function(err, res){
      if (err) throw err;
      should.not.exist(err);

      // cleans utf8 parsing for xml in form
      // see http://www.multiasking.com/blog/xml2js-sax-js-non-whitespace-before-first-tag/
      var xml = res.text.replace("\ufeff", "");
      parseString(xml, function (err, ouput) {
        var parse = ouput.Response.Message[0];
        parse.should.startWith('Light rail ');
      });
      done();
    });
  });
  it('should decode a full address', function(done){
    r(app)
    .post('/msg')
    .send({Body:"111 Granby street Norfolk VA 23508"})
    .set('Accept', 'application/xml')
    .expect(200)
    .end(function(err, res){
      if (err) throw err;
      should.not.exist(err);

      // cleans utf8 parsing for xml in form
      // see http://www.multiasking.com/blog/xml2js-sax-js-non-whitespace-before-first-tag/
      var xml = res.text.replace("\ufeff", "");
      parseString(xml, function (err, ouput) {
        var parse = ouput.Response.Message[0];
        parse.should.startWith('Light rail ');
      });
      done();
    });
  });

});

// #TODO Tests for
// Bounding Boxes
// Asking for help
// Checking for input a known address
// Checking for input a unknown/invalid address
// Check for known stop number
// Check for unknown/invalid stop number
// Check for addresses in 7 cities with generic typical names
<commit_msg>ask for help<commit_after>var assert = require("assert");
var express = require("express");
var r = require("supertest");
var parseString = require('xml2js').parseString;
var should = require('should');
/**
* Test
*
* @param {Object} req - The request value.
**/
process.env.PORT = 4000;
var app = require("../app.js");

describe('General incoming request', function(){

  it('should respond with xml', function(done){
    r(app)
    .post('/msg')
    .send({Body:"8004"})
    .set('Accept', 'application/xml')
    .expect(200)
    .end(function(err, res){
      if (err) throw err;
      done();
    });
  });

  it('for a light rail stop named 8004', function(done){
    r(app)
    .post('/msg')
    .send({Body:"8004"})
    .set('Accept', 'application/xml')
    .expect(200)
    .end(function(err, res){
      if (err) throw err;
      should.not.exist(err);

      // cleans utf8 parsing for xml in form
      // see http://www.multiasking.com/blog/xml2js-sax-js-non-whitespace-before-first-tag/
      var xml = res.text.replace("\ufeff", "");
      parseString(xml, function (err, ouput) {
         var parse = ouput.Response.Message[0];
         parse.should.startWith('Light rail ');
      });
      done();
    });
  });
  it('should decode a bus stop for an address in norfolk ', function(done){
    r(app)
    .post('/msg')
    .send({Body:"111 Granby street "})
    .set('Accept', 'application/xml')
    .expect(200)
    .end(function(err, res){
      if (err) throw err;
      should.not.exist(err);

      // cleans utf8 parsing for xml in form
      // see http://www.multiasking.com/blog/xml2js-sax-js-non-whitespace-before-first-tag/
      var xml = res.text.replace("\ufeff", "");
      parseString(xml, function (err, ouput) {
        var parse = ouput.Response.Message[0];
        parse.should.startWith('Light rail ');
      });
      done();
    });
  });
  it('should decode a full address', function(done){
    r(app)
    .post('/msg')
    .send({Body:"111 Granby street Norfolk VA 23508"})
    .set('Accept', 'application/xml')
    .expect(200)
    .end(function(err, res){
      if (err) throw err;
      should.not.exist(err);

      // cleans utf8 parsing for xml in form
      // see http://www.multiasking.com/blog/xml2js-sax-js-non-whitespace-before-first-tag/
      var xml = res.text.replace("\ufeff", "");
      parseString(xml, function (err, ouput) {
        var parse = ouput.Response.Message[0];
        parse.should.startWith('Light rail ');
      });
      done();
    });
  });

  it('respond to "help" with a useful message', function(done){
    r(app)
    .post('/msg')
    .send({Body:"help"})
    .set('Accept', 'application/xml')
    .expect(200)
    .end(function(err, res){
      if (err) throw err;
      should.not.exist(err);

      // cleans utf8 parsing for xml in form
      // see http://www.multiasking.com/blog/xml2js-sax-js-non-whitespace-before-first-tag/
      var xml = res.text.replace("\ufeff", "");
      parseString(xml, function (err, ouput) {
        var parse = ouput.Response.Message[0];
        parse.should.startWith('Hmm, I ');
      });
      done();
    });
  });

});

// #TODO Tests for
// Bounding Boxes
// Asking for help
// Checking for input a known address
// Checking for input a unknown/invalid address
// Check for known stop number
// Check for unknown/invalid stop number
// Check for addresses in 7 cities with generic typical names
<|endoftext|>