<commit_before>var assert = require('chai').assert;
var nodemock = require('nodemock');
var Deferred = require('jsdeferred').Deferred;

var utils = require('./test-utils');
var TypeOf = utils.TypeOf;
var InstanceOf = utils.InstanceOf;

var Connection = require('../lib/backend/connection').Connection;
var MsgPackReceiver = require('../lib/backend/receiver').MsgPackReceiver;

function createBackend() {
  var deferred = new Deferred();
  var backend = new MsgPackReceiver(utils.testSendPort);
  backend.received = [];
  backend.on('receive', function(data) {
    backend.received.push(data);
  });
  backend.listen(function() {
    return deferred.call(backend);
  });
  return deferred;
}

suite('Connection, initialization', function() {
  var connection;

  teardown(function() {
    if (connection) {
      connection.close();
      connection = undefined;
    }
  });

  function assertEventEmitter(object) {
    assert.equal(typeof object, 'object');
    assert.equal(typeof object.emit, 'function');
  }

  test('sender', function() {
    connection = new Connection({ tag: 'test' });
    assertEventEmitter(connection._sender);
  });

  test('receiver', function(done) {
    connection = new Connection({ tag: 'test' });
    assertEventEmitter(connection._receiver);
    assert.equal(connection.receivePort, undefined);

    Deferred
      .wait(0.01)
      .next(function() {
        assert.notEqual(connection.receivePort, undefined);
        done();
      })
      .error(function(error) {
        done(error);
      });
  });
});

suite('Connection, basic features', function() {
  var connection;
  var backend;

  setup(function(done) {
    createBackend()
      .next(function(newBackend) {
        backend = newBackend;
        connection = new Connection({
          tag:      'test',
          hostName: 'localhost',
          port:     utils.testSendPort,
          receivePort: utils.testReceivePort
        });
        done();
      });
  });

  teardown(function() {
    if (backend) {
      backend.close();
      backend = undefined;
    }
    if (connection) {
      connection.close();
      connection = undefined;
    }
  });

  function createExpectedEnvelope(type, body) {
    return {
      id:         TypeOf('string'),
      date:       InstanceOf(Date),
      replyTo:    'localhost:' + utils.testReceivePort,
      statusCode: 200,
      type:       type,
      body:       body
    };
  }

  function createReplyEnvelopeFor(message, type, body) {
    var now = new Date();
    var response = {
      id:         now.getTime(),
      date:       now.toISOString(),
      inReplyTo:  message.id,
      statusCode: 200,
      type:       type,
      body:       body
    };
    return response;
  }

  test('sending message without response (volatile message)', function(done) {
    var message;
    Deferred
      .wait(0.01)
      .next(function() {
        message = connection.emitMessage('testRequest', { command: 'foobar' });
        assert.envelopeEqual(message,
                             createExpectedEnvelope('testRequest', { command: 'foobar' }));
      })
      .wait(0.01)
      .next(function() {
        assert.equal(backend.received.length, 1);
        assert.deepEqual(backend.received[0][2], message);
        done();
      })
      .error(function(error) {
        done(error);
      });
  });

  function createMockedMessageCallback() {
    var mockedCallback = nodemock;
    var callback = function() {
      mockedCallback.receive.apply(mockedCallback, arguments);
    };
    callback.takes = function() {
      callback.assert = function() {
        mockedCallback.assertThrows();
      };
      mockedCallback = mockedCallback.mock('receive');
      mockedCallback = mockedCallback.takes.apply(mockedCallback, arguments);
    };
    callback.mock = mockedCallback;
    return callback;
  }

  test('receiving message from the backend', function(done) {
    var callback = createMockedMessageCallback();
    connection.on('message', callback);

    var now = new Date();
    var message = {
      id:         now.getTime(),
      date:       now.toISOString(),
      statusCode: 200,
      type:       'testResponse',
      body:       'first call'
    };
    callback.takes(message);
    var packet = { tag: 'test.message', data: message };
    utils.sendPacketTo(packet, utils.testReceivePort)
      .next(function() {
        callback.assert();

        message.body = 'second call';
        callback.takes(message);
        return utils.sendPacketTo(packet, utils.testReceivePort);
      })
      .next(function() {
        callback.assert();

        message.body = 'third call';
        connection.removeListener('message', callback);
        return utils.sendPacketTo(packet, utils.testReceivePort);
      })
      .next(function() {
        callback.assert();
        done();
      })
      .error(function(error) {
        done(error);
      });
  });

  test('sending message with one response, success', function(done) {
    var callback = createMockedMessageCallback();
    var message;
    var response;
    var packet;
    Deferred
      .wait(0.01)
      .next(function() {
        message = connection.emitMessage('testRequest', { command: 'foobar' }, callback);
        assert.envelopeEqual(message,
                             createExpectedEnvelope('testRequest', { command: 'foobar' }));
      })
      .wait(0.01)
      .next(function() {
        assert.equal(backend.received.length, 1);
        assert.deepEqual(backend.received[0][2], message);

        response = createReplyEnvelopeFor(message, 'testResponse', 'first call');
        callback.takes(null, response);
        packet = { tag: 'test.message', data: response };
        return utils.sendPacketTo(packet, utils.testReceivePort);
      })
      .next(function() {
        callback.assert();

        // Secondary and later messages are ignored.
        response.body = 'second call';
        return utils.sendPacketTo(packet, utils.testReceivePort);
      })
      .next(function() {
        callback.assert();
        done();
      })
      .error(function(error) {
        done(error);
      });
  });

  test('sending message with one response, with error', function(done) {
    var callback = createMockedMessageCallback();
    var message;
    var response;
    var packet;
    Deferred
      .wait(0.01)
      .next(function() {
        message = connection.emitMessage('testRequest', { command: 'foobar' }, callback);
        assert.envelopeEqual(message,
                             createExpectedEnvelope('testRequest', { command: 'foobar' }));
      })
      .wait(0.01)
      .next(function() {
        assert.equal(backend.received.length, 1);
        assert.deepEqual(backend.received[0][2], message);

        response = createReplyEnvelopeFor(message, 'testResponse', 'first call');
        response.statusCode = 503;
        callback.takes(503, response);
        packet = { tag: 'test.message', data: response };
        return utils.sendPacketTo(packet, utils.testReceivePort);
      })
      .next(function() {
        callback.assert();
        done();
      })
      .error(function(error) {
        done(error);
      });
  });

  test('sending message with one response, timeout (not timed out)', function(done) {
    var callback = createMockedMessageCallback();
    var message;
    var response;
    var packet;
    Deferred
      .wait(0.01)
      .next(function() {
        message = connection.emitMessage('testRequest', { command: 'foobar' }, callback, {
          timeout: 1000
        });
        assert.envelopeEqual(message,
                             createExpectedEnvelope('testRequest', { command: 'foobar' }));
      })
      .wait(0.01)
      .next(function() {
        assert.equal(backend.received.length, 1);
        assert.deepEqual(backend.received[0][2], message);
        assert.equal(connection.listeners('inReplyTo:' + message.id).length, 1);

        response = createReplyEnvelopeFor(message, 'testResponse', 'first call');
        callback.takes(null, response);
        packet = { tag: 'test.message', data: response };
        return utils.sendPacketTo(packet, utils.testReceivePort);
      })
      .next(function() {
        callback.assert();
        assert.equal(connection.listeners('inReplyTo:' + message.id).length, 0);
        done();
      })
      .error(function(error) {
        done(error);
      });
  });

  test('sending message with one response, timeout (timed out)', function(done) {
    var callback = createMockedMessageCallback();
    var message;
    var response;
    Deferred
      .wait(0.01)
      .next(function() {
        callback.takes(Connection.ERROR_GATEWAY_TIMEOUT, null);
        message = connection.emitMessage('testRequest', { command: 'foobar' }, callback, {
          timeout:  1,
          delay:    10
        });
        assert.envelopeEqual(message,
                             createExpectedEnvelope('testRequest', { command: 'foobar' }));
      })
      .wait(0.05)
      .next(function() {
        assert.equal(backend.received.length, 0);
        assert.equal(connection.listeners('inReplyTo:' + message.id).length, 0);
        callback.assert();
        done();
      })
      .error(function(error) {
        done(error);
      });
  });

  test('sending message with one response, timeout (ignored negative timeout)', function() {
    var callback = createMockedMessageCallback();
    var message;
    var response;
    var packet;
    Deferred
      .wait(0.01)
      .next(function() {
        message = connection.emitMessage('testRequest', { command: 'foobar' }, callback, {
          timeout: -1
        });
        assert.envelopeEqual(message,
                             createExpectedEnvelope('testRequest', { command: 'foobar' }));
      })
      .wait(0.01)
      .next(function() {
        assert.equal(backend.received.length, 1);
        assert.deepEqual(backend.received[0][2], message);
        assert.equal(connection.listeners('inReplyTo:' + message.id).length, 1);

        response = createReplyEnvelopeFor(message, 'testResponse', 'first call');
        callback.takes(null, response);
        packet = { tag: 'test.message', data: response };
        return utils.sendPacketTo(packet, utils.testReceivePort);
      })
      .next(function() {
        callback.assert();
        assert.equal(connection.listeners('inReplyTo:' + message.id).length, 0);
        done();
      })
      .error(function(error) {
        done(error);
      });
  });
});

suite('Connection, to backend', function() {
  var connection;
  var backend;

  setup(function(done) {
    createBackend()
      .next(function(newBackend) {
        backend = newBackend;
        connection = new Connection({
          tag:      'test',
          hostName: 'localhost',
          port:     utils.testSendPort
        });
        done();
      });
  });

  teardown(function() {
    if (backend) {
      backend.close();
      backend = undefined;
    }
    if (connection) {
      connection.close();
      connection = undefined;
    }
  });

  test('normal messaging', function(done) {
    Deferred
      .wait(0.01)
      .next(function() {
        connection.emitMessage({ message: true });
      })
      .wait(0.01)
      .next(function() {
        assert.equal(backend.received.length, 1);
        assert.equal(backend.received[0][0], 'test.message');
        done();
      })
      .error(function(error) {
        done(error);
      });
  });

  test('disconnected suddenly', function(done) {
    Deferred
      .wait(0.01)
      .next(function() {
        connection.emitMessage({ message: true });
      })
      .wait(0.01)
      .next(function() {
        assert.equal(backend.received.length, 1);
        assert.equal(backend.received[0][0], 'test.message');

        backend.close();
        connection.emitMessage({ message: true });
        assert.equal(backend.received.length, 1);
        done();
      })
      .error(function(error) {
        done(error);
      });
  });
});
<commit_msg>test: Add helpful messages to simple assertions<commit_after>var assert = require('chai').assert;
var nodemock = require('nodemock');
var Deferred = require('jsdeferred').Deferred;

var utils = require('./test-utils');
var TypeOf = utils.TypeOf;
var InstanceOf = utils.InstanceOf;

var Connection = require('../lib/backend/connection').Connection;
var MsgPackReceiver = require('../lib/backend/receiver').MsgPackReceiver;

function createBackend() {
  var deferred = new Deferred();
  var backend = new MsgPackReceiver(utils.testSendPort);
  backend.received = [];
  backend.on('receive', function(data) {
    backend.received.push(data);
  });
  backend.listen(function() {
    return deferred.call(backend);
  });
  return deferred;
}

suite('Connection, initialization', function() {
  var connection;

  teardown(function() {
    if (connection) {
      connection.close();
      connection = undefined;
    }
  });

  function assertEventEmitter(object) {
    assert.equal(typeof object, 'object');
    assert.equal(typeof object.emit, 'function');
  }

  test('sender', function() {
    connection = new Connection({ tag: 'test' });
    assertEventEmitter(connection._sender);
  });

  test('receiver', function(done) {
    connection = new Connection({ tag: 'test' });
    assertEventEmitter(connection._receiver);
    assert.equal(connection.receivePort, undefined);

    Deferred
      .wait(0.01)
      .next(function() {
        assert.notEqual(connection.receivePort, undefined);
        done();
      })
      .error(function(error) {
        done(error);
      });
  });
});

suite('Connection, basic features', function() {
  var connection;
  var backend;

  setup(function(done) {
    createBackend()
      .next(function(newBackend) {
        backend = newBackend;
        connection = new Connection({
          tag:      'test',
          hostName: 'localhost',
          port:     utils.testSendPort,
          receivePort: utils.testReceivePort
        });
        done();
      });
  });

  teardown(function() {
    if (backend) {
      backend.close();
      backend = undefined;
    }
    if (connection) {
      connection.close();
      connection = undefined;
    }
  });

  function createExpectedEnvelope(type, body) {
    return {
      id:         TypeOf('string'),
      date:       InstanceOf(Date),
      replyTo:    'localhost:' + utils.testReceivePort,
      statusCode: 200,
      type:       type,
      body:       body
    };
  }

  function createReplyEnvelopeFor(message, type, body) {
    var now = new Date();
    var response = {
      id:         now.getTime(),
      date:       now.toISOString(),
      inReplyTo:  message.id,
      statusCode: 200,
      type:       type,
      body:       body
    };
    return response;
  }

  test('sending message without response (volatile message)', function(done) {
    var message;
    Deferred
      .wait(0.01)
      .next(function() {
        message = connection.emitMessage('testRequest', { command: 'foobar' });
        assert.envelopeEqual(message,
                             createExpectedEnvelope('testRequest', { command: 'foobar' }));
      })
      .wait(0.01)
      .next(function() {
        assert.equal(backend.received.length, 1);
        assert.deepEqual(backend.received[0][2], message);
        done();
      })
      .error(function(error) {
        done(error);
      });
  });

  function createMockedMessageCallback() {
    var mockedCallback = nodemock;
    var callback = function() {
      mockedCallback.receive.apply(mockedCallback, arguments);
    };
    callback.takes = function() {
      callback.assert = function() {
        mockedCallback.assertThrows();
      };
      mockedCallback = mockedCallback.mock('receive');
      mockedCallback = mockedCallback.takes.apply(mockedCallback, arguments);
    };
    callback.mock = mockedCallback;
    return callback;
  }

  test('receiving message from the backend', function(done) {
    var callback = createMockedMessageCallback();
    connection.on('message', callback);

    var now = new Date();
    var message = {
      id:         now.getTime(),
      date:       now.toISOString(),
      statusCode: 200,
      type:       'testResponse',
      body:       'first call'
    };
    callback.takes(message);
    var packet = { tag: 'test.message', data: message };
    utils.sendPacketTo(packet, utils.testReceivePort)
      .next(function() {
        callback.assert();

        message.body = 'second call';
        callback.takes(message);
        return utils.sendPacketTo(packet, utils.testReceivePort);
      })
      .next(function() {
        callback.assert();

        message.body = 'third call';
        connection.removeListener('message', callback);
        return utils.sendPacketTo(packet, utils.testReceivePort);
      })
      .next(function() {
        callback.assert();
        done();
      })
      .error(function(error) {
        done(error);
      });
  });

  test('sending message with one response, success', function(done) {
    var callback = createMockedMessageCallback();
    var message;
    var response;
    var packet;
    Deferred
      .wait(0.01)
      .next(function() {
        message = connection.emitMessage('testRequest', { command: 'foobar' }, callback);
        assert.envelopeEqual(message,
                             createExpectedEnvelope('testRequest', { command: 'foobar' }));
      })
      .wait(0.01)
      .next(function() {
        assert.equal(backend.received.length, 1);
        assert.deepEqual(backend.received[0][2], message);

        response = createReplyEnvelopeFor(message, 'testResponse', 'first call');
        callback.takes(null, response);
        packet = { tag: 'test.message', data: response };
        return utils.sendPacketTo(packet, utils.testReceivePort);
      })
      .next(function() {
        callback.assert();

        // Secondary and later messages are ignored.
        response.body = 'second call';
        return utils.sendPacketTo(packet, utils.testReceivePort);
      })
      .next(function() {
        callback.assert();
        done();
      })
      .error(function(error) {
        done(error);
      });
  });

  test('sending message with one response, with error', function(done) {
    var callback = createMockedMessageCallback();
    var message;
    var response;
    var packet;
    Deferred
      .wait(0.01)
      .next(function() {
        message = connection.emitMessage('testRequest', { command: 'foobar' }, callback);
        assert.envelopeEqual(message,
                             createExpectedEnvelope('testRequest', { command: 'foobar' }));
      })
      .wait(0.01)
      .next(function() {
        assert.equal(backend.received.length, 1);
        assert.deepEqual(backend.received[0][2], message);

        response = createReplyEnvelopeFor(message, 'testResponse', 'first call');
        response.statusCode = 503;
        callback.takes(503, response);
        packet = { tag: 'test.message', data: response };
        return utils.sendPacketTo(packet, utils.testReceivePort);
      })
      .next(function() {
        callback.assert();
        done();
      })
      .error(function(error) {
        done(error);
      });
  });

  test('sending message with one response, timeout (not timed out)', function(done) {
    var callback = createMockedMessageCallback();
    var message;
    var response;
    var packet;
    Deferred
      .wait(0.01)
      .next(function() {
        message = connection.emitMessage('testRequest', { command: 'foobar' }, callback, {
          timeout: 1000
        });
        assert.envelopeEqual(message,
                             createExpectedEnvelope('testRequest', { command: 'foobar' }));
      })
      .wait(0.01)
      .next(function() {
        assert.equal(backend.received.length, 1);
        assert.deepEqual(backend.received[0][2], message);
        assert.equal(connection.listeners('inReplyTo:' + message.id).length, 1);

        response = createReplyEnvelopeFor(message, 'testResponse', 'first call');
        callback.takes(null, response);
        packet = { tag: 'test.message', data: response };
        return utils.sendPacketTo(packet, utils.testReceivePort);
      })
      .next(function() {
        callback.assert();
        assert.equal(connection.listeners('inReplyTo:' + message.id).length, 0);
        done();
      })
      .error(function(error) {
        done(error);
      });
  });

  test('sending message with one response, timeout (timed out)', function(done) {
    var callback = createMockedMessageCallback();
    var message;
    var response;
    Deferred
      .wait(0.01)
      .next(function() {
        callback.takes(Connection.ERROR_GATEWAY_TIMEOUT, null);
        message = connection.emitMessage('testRequest', { command: 'foobar' }, callback, {
          timeout:  1,
          delay:    10
        });
        assert.envelopeEqual(message,
                             createExpectedEnvelope('testRequest', { command: 'foobar' }));
      })
      .wait(0.05)
      .next(function() {
        assert.equal(backend.received.length, 0, 'no message should be sent');
        assert.equal(connection.listeners('inReplyTo:' + message.id).length,
                     0,
                     'no listener should be there');
        callback.assert();
        done();
      })
      .error(function(error) {
        done(error);
      });
  });

  test('sending message with one response, timeout (ignored negative timeout)', function() {
    var callback = createMockedMessageCallback();
    var message;
    var response;
    var packet;
    Deferred
      .wait(0.01)
      .next(function() {
        message = connection.emitMessage('testRequest', { command: 'foobar' }, callback, {
          timeout: -1
        });
        assert.envelopeEqual(message,
                             createExpectedEnvelope('testRequest', { command: 'foobar' }));
      })
      .wait(0.01)
      .next(function() {
        assert.equal(backend.received.length, 1);
        assert.deepEqual(backend.received[0][2], message);
        assert.equal(connection.listeners('inReplyTo:' + message.id).length, 1);

        response = createReplyEnvelopeFor(message, 'testResponse', 'first call');
        callback.takes(null, response);
        packet = { tag: 'test.message', data: response };
        return utils.sendPacketTo(packet, utils.testReceivePort);
      })
      .next(function() {
        callback.assert();
        assert.equal(connection.listeners('inReplyTo:' + message.id).length, 0);
        done();
      })
      .error(function(error) {
        done(error);
      });
  });
});

suite('Connection, to backend', function() {
  var connection;
  var backend;

  setup(function(done) {
    createBackend()
      .next(function(newBackend) {
        backend = newBackend;
        connection = new Connection({
          tag:      'test',
          hostName: 'localhost',
          port:     utils.testSendPort
        });
        done();
      });
  });

  teardown(function() {
    if (backend) {
      backend.close();
      backend = undefined;
    }
    if (connection) {
      connection.close();
      connection = undefined;
    }
  });

  test('normal messaging', function(done) {
    Deferred
      .wait(0.01)
      .next(function() {
        connection.emitMessage({ message: true });
      })
      .wait(0.01)
      .next(function() {
        assert.equal(backend.received.length, 1);
        assert.equal(backend.received[0][0], 'test.message');
        done();
      })
      .error(function(error) {
        done(error);
      });
  });

  test('disconnected suddenly', function(done) {
    Deferred
      .wait(0.01)
      .next(function() {
        connection.emitMessage({ message: true });
      })
      .wait(0.01)
      .next(function() {
        assert.equal(backend.received.length, 1);
        assert.equal(backend.received[0][0], 'test.message');

        backend.close();
        connection.emitMessage({ message: true });
        assert.equal(backend.received.length, 1);
        done();
      })
      .error(function(error) {
        done(error);
      });
  });
});
<|endoftext|>


<commit_before>import Collection, { CursorObservable } from 'marsdb';
import Cursor from 'marsdb/dist/Cursor';
import * as utils from '../../lib/utils';
import ExecutionContext from '../../lib/ExecutionContext';
import chai, {expect} from 'chai';
import sinon from 'sinon';
chai.use(require('chai-as-promised'));
chai.use(require('sinon-chai'));
chai.should();

describe('QueryExecutor', function () {
  describe('#execute', function () {

  });

  describe('#stop', function () {

  });

  describe('#updateVariables', function () {

  });

  describe('#_handleDataChanges', function () {

  });

  describe('#_doHandleDataChanges', function () {

  });
});
<commit_msg>added tests for constructor and execute methods of QueryExecutor<commit_after>import Collection, { CursorObservable } from 'marsdb';
import Cursor from 'marsdb/dist/Cursor';
import * as utils from '../../lib/utils';
import createContainer from '../../lib/createContainer';
import QueryExecutor from '../../lib/QueryExecutor';
import chai, { expect } from 'chai';
import sinon from 'sinon';
chai.use(require('chai-as-promised'));
chai.use(require('sinon-chai'));
chai.should();

describe('QueryExecutor', function () {

  describe('#constructor', function () {
    it('should overwrite variables by given initial vars object', function () {
      class TestComponent {}
      const containerClass = createContainer(TestComponent, {
        initialVariables: { testVar: 'val' },
        fragments: { test: ({testVar}) => testVar() + 'val' },
      });
      const query = containerClass.getQuery({ testVar: 'another_val' });
      query.execute();
      query.result.test().should.be.equal('another_valval');
    });

    it('should properly handle null values variables', function () {
      class TestComponent {}
      const containerClass = createContainer(TestComponent, {
        initialVariables: { testVar: 'val' },
        fragments: { test: ({testVar}) => testVar() + 'val' },
      });
      let query = containerClass.getQuery({ testVar: null });
      let res = query.execute();
      query.result.test().should.be.equal('nullval');

      query = containerClass.getQuery({ testVar: undefined });
      res = query.execute();
      query.result.test().should.be.equal('undefinedval');

      query = containerClass.getQuery({ testVar: '' });
      res = query.execute();
      query.result.test().should.be.equal('val');

      query = containerClass.getQuery({ testVar: 0 });
      res = query.execute();
      query.result.test().should.be.equal('0val');
    });
  });

  describe('#execute', function () {
    it('should return a promise that resolved when all data revceived', function () {
      class TestComponent {}
      const containerClass = createContainer(TestComponent, {
        initialVariables: { testVar: 'val' },
        fragments: { test: ({testVar}) => testVar() + 'val' },
      });
      const query = containerClass.getQuery();
      expect(query.result).to.be.undefined;
      const res = query.execute();
      query.result.test().should.be.equal('valval');
      return res.then(() => {
        query.result.test().should.be.equal('valval');
      });
    });

    it('should return the same promise until prev is not resolved', function () {
      const db = new Collection('test');
      return db.insert({a: 1, _id: '1'}).then(() => {
        class TestComponent {}
        const containerClass = createContainer(TestComponent, {
          initialVariables: { testVar: 'val' },
          fragments: { test: ({testVar}) => db.findOne() },
        });
        const query = containerClass.getQuery();
        expect(query.result).to.be.undefined;
        const res = query.execute();
        query.execute().should.be.equal(res);
        expect(query.result.test()).to.be.null;
        return res.then(() => {
          query.result.test().should.be.deep.equal({a: 1, _id: '1'});
          query.execute().should.be.equal(res);
        });
      });
    });

    it('should emit an update event when data is ready', function () {
      const db = new Collection('test');
      const cb = sinon.spy();

      return db.insert({a: 1, _id: '1'}).then(() => {
        class TestComponent {}
        const containerClass = createContainer(TestComponent, {
          initialVariables: { testVar: 'val' },
          fragments: { test: ({testVar}) => db.findOne() },
        });
        const query = containerClass.getQuery();
        query.on('update', cb);
        expect(query.result).to.be.undefined;
        const res = query.execute();
        expect(query.result.test()).to.be.null;
        cb.should.have.been.callCount(0);
        return res.then(() => {
          cb.should.have.been.callCount(1);
        });
      });
    });
  });

  describe('#stop', function () {

  });

  describe('#updateVariables', function () {

  });

  describe('#_handleDataChanges', function () {

  });

  describe('#_doHandleDataChanges', function () {

  });
});
<|endoftext|>


<commit_before>var buster = require("buster");
var assert = buster.assert;
var refute = buster.refute;
var captureMiddleware = require("./../lib/capture/capture-middleware");
var captureMiddlewareClient = require("./../lib/capture/captured-client");
var resourceMiddleware = require("./../lib/resources/resource-middleware");
var busterServer = require("./../lib/buster-server");

var fs = require("fs");
var http = require("http");
var h = require("./test-helper");

buster.testCase("Client middleware", {
    setUp: function (done) {
        var self = this;
        this.httpServer = http.createServer(function (req, res) {
            res.writeHead(h.NO_RESPONSE_STATUS_CODE);
            res.end();
        });

        this.httpServer.listen(h.SERVER_PORT, done);

        this.busterServer = busterServer.create();
        this.busterServer.attach(this.httpServer);
        this.cm = this.busterServer.capture;
    },

    tearDown: function (done) {
        this.httpServer.on("close", done);
        this.httpServer.close();
    },

    "test creating/capturing client": function (done) {
        this.stub(captureMiddlewareClient, "startSession");
        this.cm.oncapture =  function (req, res, client) {
            assert(typeof(client), "object");
            assert.isFalse(client.startSession.called);
            done();
        };
        this.cm.captureClient();
    },

    "test capturing client with session in progress": function (done) {
        this.cm.startSession({});
        this.stub(captureMiddlewareClient, "startSession");
        this.cm.oncapture = function (req, res, client) {
            assert(client.startSession.calledOnce);
            done();
        };
        this.cm.captureClient();
    },

    "test different clients gets different URLs": function (done) {
        var clients = [];
        this.cm.oncapture = function (req, res, client) {
            clients.push(client);

            if (clients.length == 2) {
                refute.equals(clients[0].url, clients[1].url);
                done();
            }
        };

        this.cm.captureClient();
        this.cm.captureClient();
    },

    "test default capture URL": function (done) {
        this.cm.oncapture = function (req, res, client) {
            res.end();
            done();
        };

        h.request({ path: this.cm.capturePath, method: "GET" }, function () {}).end();
        assert(true);
    },

    "test custom capture URL": function (done) {
        this.cm.oncapture = function (req, res, client) {
            res.end();
            done();
        };

        this.cm.capturePath = "/foo";
        h.request({ path: "/foo", method: "GET" }, function () {}).end();
        assert(true);
    },

    "test creating client without oncapture handler": function (done) {
        try {
            this.cm.captureClient();
        } catch (e) {
            assert.match(e.message, "'oncapture' handler");
            assert.equals(this.cm.capturedClients.length, 0);
            done();
        }
    },

    "test first client on new server gets different id": function (done) {
        var otherCm = Object.create(captureMiddleware);
        otherCm.server = this.busterServer;
        otherCm.resourceMiddleware = Object.create(resourceMiddleware);

        var clients = [];
        var captureHandler = function (req, res, client) {
            clients.push(client);

            if (clients.length == 2) {
                refute.equals(clients[0].id, clients[1].id);
                done();
            }
        };

        this.cm.oncapture = captureHandler;
        this.cm.captureClient();
        otherCm.oncapture = captureHandler;
        otherCm.captureClient();
    },

    "client with header resource": {
        setUp: function (done) {
            var self = this;

            this.cm.header(80, {
                resources: {"/": {content: "Hello, World!"}}
            });

            this.cm.oncapture = function (req, res, client) {
                delete self.cm.oncapture;
                self.client = client;
                done();
            };
            this.cm.captureClient();
        },

        "test serves frameset": function (done) {
            h.request({path: this.client.url, method: "GET"}, function (res, body) {
                buster.assert.equals(res.statusCode, 200);
                buster.assert.match(body, '<frame src="/clientHeader/" />');
                buster.assert.match(body, '<frameset rows="0px,80px,*"');
                done();
            }).end();
        },

        "test creates resource set": function (done) {
            h.request({path: "/clientHeader/", method: "GET"}, function (res, body) {
                buster.assert.equals(res.statusCode, 200);
                buster.assert.equals(body, "Hello, World!");
                done();
            }).end();
        }
    },

    "with a client": {
        setUp: function (done) {
            var self = this;
            this.cm.oncapture = function (req, res, client) {
                delete self.cm.oncapture;
                self.client = client;
                done();
            };
            this.cm.captureClient();
        },

        "index page": {
            setUp: function (done) {
                var self = this;
                h.request({path: this.client.url}, function (res, body) {
                    self.res = res;
                    self.body = body;
                    done();
                }).end();
            },

            "should be served as text/html": function () {
                assert.equals(this.res.statusCode, 200);
                assert.equals(this.res.headers["content-type"], "text/html");
            },

            "should serve frameset": function () {
                assert.match(this.body, "<frameset");
            },

            "should serve control frame": function () {
                assert.match(this.body, '<frame src="' + this.client.url + '/control_frame.html" id="control_frame" />');
            },

            "should serve session frame with no session loaded": function () {
                assert.match(this.body, '<frame id="client_frame" />');
            },
        },

        "serving env.js": {
            setUp: function (done) {
                var self = this;
                h.request({path: this.client.url + "/env.js", headers: {host: "foo.local:1234"}}, function (res, body) {
                    self.res = res;
                    self.body = body;

                    done();
                }).end();
            },

            "test responds with 200 OK": function () {
                assert.equals(this.res.statusCode, 200);
            },

            "test serves with correct content-type": function () {
                assert.equals(this.res.headers["content-type"], "application/javascript");
            },

            "test in clean scope": function () {
                var scope = {};
                require("vm").runInNewContext(this.body, scope);

                assert("buster" in scope);
                assert("env" in scope.buster);
                assert.equals(typeof(scope.buster.env), "object");
                assert.equals(scope.buster.env.bayeuxUrl, "http://foo.local:1234/sessions/messaging");
                assert.equals(this.client.id, scope.buster.env.clientId);
            },

            "test in scope where buster is already defined": function () {
                var scope = {buster: {}};
                require("vm").runInNewContext(this.body, scope);
                assert("buster" in scope);
                assert("env" in scope.buster);
                assert.equals(typeof(scope.buster.env), "object");
                assert.equals(scope.buster.env.bayeuxUrl, "http://foo.local:1234/sessions/messaging");
            }
        },

        "test setting custom env variables": function (done) {
            this.client.env.foo = "bar";

            h.request({path: this.client.url + "/env.js"}, function (res, body) {
                assert.equals(res.statusCode, 200);
                assert.equals(res.headers["content-type"], "application/javascript");

                var scope = {};
                require("vm").runInNewContext(body, scope);
                assert.equals("bar", scope.buster.env.foo);
                done();
            }).end();
        },

        "test control_frame.html loads all scripts": function (done) {
            var self = this;
            this.client.resourceSet.load = [
                "/foo.js",
                "/bar.js",
                "/baz/maz.js"
            ];

            h.request({path: this.client.url + "/control_frame.html"}, function (res, body) {
                assert.equals(res.statusCode, 200);
                assert.equals(res.headers["content-type"], "text/html");
                assert.match(body, self.client.url + "/foo.js");
                assert.match(body, self.client.url + "/bar.js");
                assert.match(body, self.client.url + "/baz/maz.js");
                done();
            }).end();
        },

        "test client serves all scripts": function (done) {
            var self = this;

            this.client.resourceSet.load = ["/foo.js", "/bar/baz.js"];
            this.client.resourceSet.addResource("/foo.js", {content:"doing it"});
            this.client.resourceSet.addResource("/bar/baz.js", {content:"buster yo"});

            h.request({path: this.client.url + "/foo.js", method: "GET"}, function (res, body) {
                assert.equals(200, res.statusCode);
                assert.equals("doing it", body);

                h.request({path: self.client.url + "/bar/baz.js", method: "GET"}, function (res, body) {
                    assert.equals(200, res.statusCode);
                    assert.equals("buster yo", body);
                    done();
                }).end();
            }).end();
        },

        "test client serves all built-in scripts": function (done) {
            var self = this;
            var numResponses = 0;
            var handler = function (res, script) {
                assert.equals(200, res.statusCode, "Built-in script '" + script + "' failed to load");
                numResponses++;
                if (numResponses == self.client.resourceSet.load.length) done();
            }

            for (var i = 0, ii = this.client.resourceSet.load.length; i < ii; i++) {
                (function (script) {
                    h.request({path: self.client.url + script, method: "GET"}, function (res, body) {
                        handler(res, script);
                    }).end();
                }(this.client.resourceSet.load[i]));
            }
        },

        "test binding to session middleware": function () {
            var session = {foo: "test"};
            var sessionMiddleware = Object.create(buster.eventEmitter);
            this.cm.bindToSessionMiddleware(sessionMiddleware);

            this.stub(this.cm, "startSession");
            sessionMiddleware.emit("session:start", session);
            assert(this.cm.startSession.calledOnce);
            assert(this.cm.startSession.calledWithExactly(session));

            this.stub(this.cm, "endSession");
            sessionMiddleware.emit("session:end");
            assert(this.cm.endSession.calledOnce);
        },

        "test publishes /session/start when session is present and is ready": function (done) {
            this.busterServer.bayeux.subscribe("/" + this.client.id + "/session/start", function (sess) {
                assert.equals(sess, {foo: "bar"});
                done();
            });

            this.client.startSession({toJSON: function () { return {foo: "bar"}}});
            this.client.ready();
        },

        "test ready event broadcasts session": function (done) {
            this.client.ready = function () {
                assert(true);
                done();
            };

            this.busterServer.bayeux.publish("/" + this.client.id + "/ready", 1);
        }
    }
});<commit_msg>Improving tests to not be aware of private 'ready' method.<commit_after>var buster = require("buster");
var assert = buster.assert;
var refute = buster.refute;
var captureMiddleware = require("./../lib/capture/capture-middleware");
var captureMiddlewareClient = require("./../lib/capture/captured-client");
var resourceMiddleware = require("./../lib/resources/resource-middleware");
var busterServer = require("./../lib/buster-server");

var fs = require("fs");
var http = require("http");
var h = require("./test-helper");

buster.testCase("Client middleware", {
    setUp: function (done) {
        var self = this;
        this.httpServer = http.createServer(function (req, res) {
            res.writeHead(h.NO_RESPONSE_STATUS_CODE);
            res.end();
        });

        this.httpServer.listen(h.SERVER_PORT, done);

        this.busterServer = busterServer.create();
        this.busterServer.attach(this.httpServer);
        this.cm = this.busterServer.capture;
    },

    tearDown: function (done) {
        this.httpServer.on("close", done);
        this.httpServer.close();
    },

    "test creating/capturing client": function (done) {
        this.stub(captureMiddlewareClient, "startSession");
        this.cm.oncapture =  function (req, res, client) {
            assert(typeof(client), "object");
            assert.isFalse(client.startSession.called);
            done();
        };
        this.cm.captureClient();
    },

    "test capturing client with session in progress": function (done) {
        this.cm.startSession({});
        this.stub(captureMiddlewareClient, "startSession");
        this.cm.oncapture = function (req, res, client) {
            assert(client.startSession.calledOnce);
            done();
        };
        this.cm.captureClient();
    },

    "test different clients gets different URLs": function (done) {
        var clients = [];
        this.cm.oncapture = function (req, res, client) {
            clients.push(client);

            if (clients.length == 2) {
                refute.equals(clients[0].url, clients[1].url);
                done();
            }
        };

        this.cm.captureClient();
        this.cm.captureClient();
    },

    "test default capture URL": function (done) {
        this.cm.oncapture = function (req, res, client) {
            res.end();
            done();
        };

        h.request({ path: this.cm.capturePath, method: "GET" }, function () {}).end();
        assert(true);
    },

    "test custom capture URL": function (done) {
        this.cm.oncapture = function (req, res, client) {
            res.end();
            done();
        };

        this.cm.capturePath = "/foo";
        h.request({ path: "/foo", method: "GET" }, function () {}).end();
        assert(true);
    },

    "test creating client without oncapture handler": function (done) {
        try {
            this.cm.captureClient();
        } catch (e) {
            assert.match(e.message, "'oncapture' handler");
            assert.equals(this.cm.capturedClients.length, 0);
            done();
        }
    },

    "test first client on new server gets different id": function (done) {
        var otherCm = Object.create(captureMiddleware);
        otherCm.server = this.busterServer;
        otherCm.resourceMiddleware = Object.create(resourceMiddleware);

        var clients = [];
        var captureHandler = function (req, res, client) {
            clients.push(client);

            if (clients.length == 2) {
                refute.equals(clients[0].id, clients[1].id);
                done();
            }
        };

        this.cm.oncapture = captureHandler;
        this.cm.captureClient();
        otherCm.oncapture = captureHandler;
        otherCm.captureClient();
    },

    "client with header resource": {
        setUp: function (done) {
            var self = this;

            this.cm.header(80, {
                resources: {"/": {content: "Hello, World!"}}
            });

            this.cm.oncapture = function (req, res, client) {
                delete self.cm.oncapture;
                self.client = client;
                done();
            };
            this.cm.captureClient();
        },

        "test serves frameset": function (done) {
            h.request({path: this.client.url, method: "GET"}, function (res, body) {
                buster.assert.equals(res.statusCode, 200);
                buster.assert.match(body, '<frame src="/clientHeader/" />');
                buster.assert.match(body, '<frameset rows="0px,80px,*"');
                done();
            }).end();
        },

        "test creates resource set": function (done) {
            h.request({path: "/clientHeader/", method: "GET"}, function (res, body) {
                buster.assert.equals(res.statusCode, 200);
                buster.assert.equals(body, "Hello, World!");
                done();
            }).end();
        }
    },

    "with a client": {
        setUp: function (done) {
            var self = this;
            this.cm.oncapture = function (req, res, client) {
                delete self.cm.oncapture;
                self.client = client;
                done();
            };
            this.cm.captureClient();
        },

        "index page": {
            setUp: function (done) {
                var self = this;
                h.request({path: this.client.url}, function (res, body) {
                    self.res = res;
                    self.body = body;
                    done();
                }).end();
            },

            "should be served as text/html": function () {
                assert.equals(this.res.statusCode, 200);
                assert.equals(this.res.headers["content-type"], "text/html");
            },

            "should serve frameset": function () {
                assert.match(this.body, "<frameset");
            },

            "should serve control frame": function () {
                assert.match(this.body, '<frame src="' + this.client.url + '/control_frame.html" id="control_frame" />');
            },

            "should serve session frame with no session loaded": function () {
                assert.match(this.body, '<frame id="client_frame" />');
            },
        },

        "serving env.js": {
            setUp: function (done) {
                var self = this;
                h.request({path: this.client.url + "/env.js", headers: {host: "foo.local:1234"}}, function (res, body) {
                    self.res = res;
                    self.body = body;

                    done();
                }).end();
            },

            "test responds with 200 OK": function () {
                assert.equals(this.res.statusCode, 200);
            },

            "test serves with correct content-type": function () {
                assert.equals(this.res.headers["content-type"], "application/javascript");
            },

            "test in clean scope": function () {
                var scope = {};
                require("vm").runInNewContext(this.body, scope);

                assert("buster" in scope);
                assert("env" in scope.buster);
                assert.equals(typeof(scope.buster.env), "object");
                assert.equals(scope.buster.env.bayeuxUrl, "http://foo.local:1234/sessions/messaging");
                assert.equals(this.client.id, scope.buster.env.clientId);
            },

            "test in scope where buster is already defined": function () {
                var scope = {buster: {}};
                require("vm").runInNewContext(this.body, scope);
                assert("buster" in scope);
                assert("env" in scope.buster);
                assert.equals(typeof(scope.buster.env), "object");
                assert.equals(scope.buster.env.bayeuxUrl, "http://foo.local:1234/sessions/messaging");
            }
        },

        "test setting custom env variables": function (done) {
            this.client.env.foo = "bar";

            h.request({path: this.client.url + "/env.js"}, function (res, body) {
                assert.equals(res.statusCode, 200);
                assert.equals(res.headers["content-type"], "application/javascript");

                var scope = {};
                require("vm").runInNewContext(body, scope);
                assert.equals("bar", scope.buster.env.foo);
                done();
            }).end();
        },

        "test control_frame.html loads all scripts": function (done) {
            var self = this;
            this.client.resourceSet.load = [
                "/foo.js",
                "/bar.js",
                "/baz/maz.js"
            ];

            h.request({path: this.client.url + "/control_frame.html"}, function (res, body) {
                assert.equals(res.statusCode, 200);
                assert.equals(res.headers["content-type"], "text/html");
                assert.match(body, self.client.url + "/foo.js");
                assert.match(body, self.client.url + "/bar.js");
                assert.match(body, self.client.url + "/baz/maz.js");
                done();
            }).end();
        },

        "test client serves all scripts": function (done) {
            var self = this;

            this.client.resourceSet.load = ["/foo.js", "/bar/baz.js"];
            this.client.resourceSet.addResource("/foo.js", {content:"doing it"});
            this.client.resourceSet.addResource("/bar/baz.js", {content:"buster yo"});

            h.request({path: this.client.url + "/foo.js", method: "GET"}, function (res, body) {
                assert.equals(200, res.statusCode);
                assert.equals("doing it", body);

                h.request({path: self.client.url + "/bar/baz.js", method: "GET"}, function (res, body) {
                    assert.equals(200, res.statusCode);
                    assert.equals("buster yo", body);
                    done();
                }).end();
            }).end();
        },

        "test client serves all built-in scripts": function (done) {
            var self = this;
            var numResponses = 0;
            var handler = function (res, script) {
                assert.equals(200, res.statusCode, "Built-in script '" + script + "' failed to load");
                numResponses++;
                if (numResponses == self.client.resourceSet.load.length) done();
            }

            for (var i = 0, ii = this.client.resourceSet.load.length; i < ii; i++) {
                (function (script) {
                    h.request({path: self.client.url + script, method: "GET"}, function (res, body) {
                        handler(res, script);
                    }).end();
                }(this.client.resourceSet.load[i]));
            }
        },

        "test binding to session middleware": function () {
            var session = {foo: "test"};
            var sessionMiddleware = Object.create(buster.eventEmitter);
            this.cm.bindToSessionMiddleware(sessionMiddleware);

            this.stub(this.cm, "startSession");
            sessionMiddleware.emit("session:start", session);
            assert(this.cm.startSession.calledOnce);
            assert(this.cm.startSession.calledWithExactly(session));

            this.stub(this.cm, "endSession");
            sessionMiddleware.emit("session:end");
            assert(this.cm.endSession.calledOnce);
        },

        "test publishes /session/start when session is present and is ready": function (done) {
            this.busterServer.bayeux.subscribe("/" + this.client.id + "/session/start", function (sess) {
                assert.equals(sess, {foo: "bar"});
                done();
            });

            this.client.startSession({toJSON: function () { return {foo: "bar"}}});
            this.client.bayeuxClient.publish("/" + this.client.id + "/ready", {});
        },

        "test ready event broadcasts session": function (done) {
            this.busterServer.bayeux.subscribe("/" + this.client.id + "/session/start", function (sess) {
                assert(true);
                done();
            });

            this.client.currentSession = {toJSON: function () { return {foo: "bar"}}};
            this.busterServer.bayeux.publish("/" + this.client.id + "/ready", 1);
        }
    }
});<|endoftext|>


<commit_before>(function (temp) {
  // Default global var name will be newT
  // can be overridden by passing something different
  // into the self executing wrapper function
  temp = temp || "newT";

  // internally refer to it as T for brevity sake
  var T = function() {
    this.init();
  }

  T.prototype = {
    constructor: T.prototype.constructor,
    init: function(data) {
      this.templates = {};
      this.__createMethods();
      return this;
    },
    // simple function to save the passed in template
    save: function(name, template) {
      this.templates[name] = template;
      return this;
    },
    // create the elements for the template
    // and if an exisiting root el was passed in, append it to that root
    // either way, return the newly created element(s)
    render: function(name, data, opts) {
      opts = opts || {};
      opts.scope = opts.scope || null;
      opts.data = data;

      // if a preprocessing function is specified in the options, call it
      // use either the specified scope, or the default of null (set earlier)
      // params
      if (opts.preData) { opts.data = opts.preData.call(opts.scope, opts.data); }
      if (opts.pre) { var ret = opts.pre.call(opts.scope, opts.data); }

      var new_el = this.templates[name](opts.data);

      if(opts.el) {
        opts.el.appendChild(new_el);
      }

      // if a posprocessing function is specified in the options, call it
      // use either the specified scope, or the default of null (set earlier)
      if (opts.post) { opts.post.call(opts.scope, new_el, opts.data); }
      return new_el;
    },
    // function to iterate over a collection and render a template
    // for each item in the collection
    // uses a document fragment to collect each element and pass it back
    each_render: function(data, template, opts) {
      opts = opts || {};
      var frag = document.createDocumentFragment();
      opts.el = frag;
      for(var i in data) {
        if(data.hasOwnProperty(i)) {
          this.render(template, data[i], opts);
        }
      }
      return frag;
    },
    // more free form iterator function that allows passing an ad-hoc
    // rendering function to be evaluated for each item in the collection
    // uses a document fragment to collect each element and pass it back
    each: function(data, func) {
      var frag = document.createDocumentFragment();
      for(var i in data) {
        if(data.hasOwnProperty(i)) {
          frag.appendChild(func(data[i]));
        }
      }
      return frag;
    },
    // function that gets called in initializing the class... loops through
    // list of allowed html elements, and creates a helper function on the prototype
    // to allow easy creation of that element simply by calling its name as a function
    __createMethods: function() {
      var el_list = "a abbr acronym address applet area b base basefont bdo bgsound big blockquote body br button caption center cite code col colgroup comment custom dd del dfn dir div dl dt em embed fieldset font form frame frameset head h1 h2 h3 h4 h5 h6 hn hr html i iframe img input input ins isindex kbd label legend li link listing map marquee menu meta nobr noframes noscript object ol optgroup option p param plaintext pre q rt ruby s samp script select small span strike strong style sub sup table tbody td textarea tfoot th thead title tr tt u ul var wbr xml xmp";
      var els = el_list.split(" ");

      // extra helper for just grouping a bunch together without a specific parent
      els.push("frag");

      var _this = this;
      for(var i=0, len=els.length; i<len; i++) (function(el) {
        T.prototype[el] = function() {
          var args = Array.prototype.slice.call(arguments);
          args.unshift(el);
          return T.prototype.__createElGeneric.apply(_this, args);
        }
      })(els[i]);
      return this;
    },
    // generic version of the function used to build the element specific creation functions
    // type -> name of element to create
    // attributes (optional) -> object with key/value pairs for attributes to be added to the element
    //                          to avoid silliness with using class as an object key
    //                          you must use "clss" to set class.  yuck
    // content (optional) -> arbitrarily many pieces of content to be added within the element
    //                       can be strings, domElements, or anything that evaluates to either of those
    __createElGeneric: function(type, attributes, content) {
      var args = Array.prototype.slice.call(arguments).slice(1);

      var el = (type==="frag" ? document.createDocumentFragment() : document.createElement(type));
      if(args.length) {
        content = args;
      }
      else {
        return el;
      }

      if (args[0].toString() === "[object Object]") {
        attributes = content.shift();
      }
      else {
        attributes = null;
      }

      if(attributes) {
        for(attr in attributes) {
          if(attr === "clss") {
            el.className = attributes[attr];
          }
          else {
            el.setAttribute(attr, attributes[attr]);
          }
        }
      }

      for(var i=0, len=content.length; i<len; i++) {
        // if the content is a string, create a Text Node to hold it and append
        // unless (for now) there are html tags or entities in it... then just innerHTML it
        if(typeof content[i] === "string") {
          var re = /\<[^\>]+\>|\&[^ ]+;/;
          if(content[i].match(re)) {
            el.innerHTML += content[i];
          }
          else {
            el.appendChild(document.createTextNode(content[i]));
          }

        }
        else if(typeof content[i] === "function") {
          el.appendChild(content[i]());
        }
        else {
          el.appendChild(content[i]);
        }
      }
      return el;
    }
  }
  window[temp] = new T();
})();
<commit_msg>fixed handling style attribute... though i may need to switch back. and handled numbers in addition to strings<commit_after>(function (temp) {
  // Default global var name will be newT
  // can be overridden by passing something different
  // into the self executing wrapper function
  temp = temp || "newT";

  // internally refer to it as T for brevity sake
  var T = function() {
    this.init();
  }

  T.prototype = {
    constructor: T.prototype.constructor,
    init: function(data) {
      this.templates = {};
      this.__createMethods();
      return this;
    },
    // simple function to save the passed in template
    save: function(name, template) {
      this.templates[name] = template;
      return this;
    },
    // create the elements for the template
    // and if an exisiting root el was passed in, append it to that root
    // either way, return the newly created element(s)
    render: function(name, data, opts) {
      opts = opts || {};
      opts.scope = opts.scope || null;
      opts.data = data;

      // if a preprocessing function is specified in the options, call it
      // use either the specified scope, or the default of null (set earlier)
      // params
      if (opts.preData) { opts.data = opts.preData.call(opts.scope, opts.data); }
      if (opts.pre) { var ret = opts.pre.call(opts.scope, opts.data); }

      var new_el = this.templates[name](opts.data);

      if(opts.el) {
        opts.el.appendChild(new_el);
      }

      // if a posprocessing function is specified in the options, call it
      // use either the specified scope, or the default of null (set earlier)
      if (opts.post) { opts.post.call(opts.scope, new_el, opts.data); }
      return new_el;
    },
    // function to iterate over a collection and render a template
    // for each item in the collection
    // uses a document fragment to collect each element and pass it back
    each_render: function(data, template, opts) {
      opts = opts || {};
      var frag = document.createDocumentFragment();
      opts.el = frag;
      for(var i in data) {
        if(data.hasOwnProperty(i)) {
          this.render(template, data[i], opts);
        }
      }
      return frag;
    },
    // more free form iterator function that allows passing an ad-hoc
    // rendering function to be evaluated for each item in the collection
    // uses a document fragment to collect each element and pass it back
    each: function(data, func) {
      var frag = document.createDocumentFragment();
      for(var i in data) {
        if(data.hasOwnProperty(i)) {
          frag.appendChild(func(data[i]));
        }
      }
      return frag;
    },
    // function that gets called in initializing the class... loops through
    // list of allowed html elements, and creates a helper function on the prototype
    // to allow easy creation of that element simply by calling its name as a function
    __createMethods: function() {
      var el_list = "a abbr acronym address applet area b base basefont bdo bgsound big blockquote body br button caption center cite code col colgroup comment custom dd del dfn dir div dl dt em embed fieldset font form frame frameset head h1 h2 h3 h4 h5 h6 hn hr html i iframe img input input ins isindex kbd label legend li link listing map marquee menu meta nobr noframes noscript object ol optgroup option p param plaintext pre q rt ruby s samp script select small span strike strong style sub sup table tbody td textarea tfoot th thead title tr tt u ul var wbr xml xmp";
      var els = el_list.split(" ");

      // extra helper for just grouping a bunch together without a specific parent
      els.push("frag");

      var _this = this;
      for(var i=0, len=els.length; i<len; i++) (function(el) {
        T.prototype[el] = function() {
          var args = Array.prototype.slice.call(arguments);
          args.unshift(el);
          return T.prototype.__createElGeneric.apply(_this, args);
        }
      })(els[i]);
      return this;
    },
    // generic version of the function used to build the element specific creation functions
    // type -> name of element to create
    // attributes (optional) -> object with key/value pairs for attributes to be added to the element
    //                          to avoid silliness with using class as an object key
    //                          you must use "clss" to set class.  yuck
    // content (optional) -> arbitrarily many pieces of content to be added within the element
    //                       can be strings, domElements, or anything that evaluates to either of those
    __createElGeneric: function(type, attributes, content) {
      var args = Array.prototype.slice.call(arguments).slice(1);

      var el = (type==="frag" ? document.createDocumentFragment() : document.createElement(type));
      if(args.length) {
        content = args;
      }
      else {
        return el;
      }

      if (args[0].toString() === "[object Object]") {
        attributes = content.shift();
      }
      else {
        attributes = null;
      }

      if(attributes) {
        for(attr in attributes) {
          switch(attr) {
            case "clss":
              el.className = attributes[attr];
              break;
            case "style":
              el.cssText = el.style.cssText = attributes[attr];
              break;
            default:
              el.setAttribute(attr, attributes[attr]);
          }
        }
      }

      for(var i=0, len=content.length; i<len; i++) {
        // if the content is a string, create a Text Node to hold it and append
        // unless (for now) there are html tags or entities in it... then just innerHTML it
        if(typeof content[i] === "string") {
          var re = /\<[^\>]+\>|\&[^ ]+;/;
          if(content[i].match(re)) {
            el.innerHTML += content[i];
          }
          else {
            el.appendChild(document.createTextNode(content[i]));
          }

        }
        else if (typeof content[i] === "number") {
          el.appendChild(document.createTextNode(content[i]));
        }
        else if(typeof content[i] === "function") {
          el.appendChild(content[i]());
        }
        else {
          el.appendChild(content[i]);
        }
      }
      return el;
    }
  }
  window[temp] = new T();
})();
<|endoftext|>


<commit_before>;(function (window) {
    'use strict';

    /**
     * @description
     * ngMe constructor fn.
     *
     * @param  {Object} params
     * @public
     */
    function ngMe (params) {
        this.params = params || {};
        this.modules = {};
    };

    /**
     * @description
     * Run fn on DOM ready.
     *
     * @param  {Function} cb
     * @return {Function}
     * @public
     */
    ngMe.prototype.run = function (cb) {
        document.addEventListener('DOMContentLoaded', function () {
            if (typeof cb === 'function') return cb();
        });
    };

    /**
     * @description
     * Instantiate module.
     *
     * @param  {String} moduleName
     * @param  {Array} deps
     * @return {Object}
     * @public
     */
    ngMe.prototype.module = function (moduleName, deps) {
        var __super = this;

        if (this.isString(moduleName) && this.isArray(deps)) {

            /**
             * @description
             * Module dependency constructor fn.
             *
             * @param {Array} deps
             * @public
             */
            function ModuleConstructor (deps) {
                this.requires = deps;
            }

            /**
             * @description
             * Instantiate module's controller.
             *
             * @param  {String} vm
             * @param  {Function} scope
             * @return {Object}
             * @public
             */
            ModuleConstructor.prototype.controller = function (vm, Scope) {
                var _this = this;

                /**
                 * @description
                 * Module constructor fn.
                 *
                 * @param {String} moduleName
                 * @param {String} vm
                 * @param {Function} scope
                 * @public
                 */
                function Module (moduleName, vm, scope) {
                    this.name = moduleName;
                    this[vm] = scope;
                    this.requires = _this.requires;
                };

                /**
                 * @description
                 * Invoke controller's scope.
                 *
                 * @return {Object}
                 * @public
                 */
                Module.prototype.$$scope = function () {
                    var _this = this;
                    var _arguments = Array.prototype.slice.call(arguments);
                    var requires = [];

                    _arguments[0].forEach(function (arg) {
                        requires.push(__super.modules[arg]);
                    });

                    _this[vm].apply(_this[vm], requires);
                    return _this;
                }

                __super.modules[moduleName] = Scope;

                return (new Module(moduleName, vm, Scope)).$$scope(deps);
            };

            return new ModuleConstructor(Array.prototype.slice.call(deps));
        }

        return {};
    };

    /**
     * @description
     * Check if param is array.
     *
     * @param  {*} param
     * @return {Boolean}
     * @public
     */
    ngMe.prototype.isArray = function (param) {
        return Object.prototype.toString.call(param) === '[object Array]';
    };

    /**
     * @description
     * Check if param is string.
     *
     * @param  {*} param
     * @return {Boolean}
     * @public
     */
    ngMe.prototype.isString = function (param) {
        return typeof param === 'string';
    };

    window.ngMe = new ngMe();
})(window);

;(function () {
    'use strict';

    ngMe.run(function () {

        var aModule = ngMe.module('aModule', []);

        aModule.controller('AController', AController);
        function AController () {
            var vm = this;

            vm.fnA = fnA;

            function fnA () {
                console.log('fnA called from bModule');
            };
        }

        var cModule = ngMe.module('cModule', [])
            .controller('CController', CController);

        function CController () {
            var vm = this;

            console.log('CCC');
            vm.fnC = fnC;

            function fnC () {
                console.log('fn C');
            }
        }

        var bModule = ngMe.module('bModule', ['cModule', 'aModule'])
            .controller('BController', BController);

        function BController (cModule, aModule) {
            var vm = this;

            vm.fnB = fnB;

            init();

            function init () {
                setTimeout(function () {
                    vm.fnB();
                }, 2000);

            }

            function fnB () {
                aModule.fnA();
                document.addEventListener('click', function () {
                    cModule.fnC();
                });

            };
        }
    });
})();
<commit_msg>Updating dependency injection.<commit_after>;(function (window) {
    'use strict';

    /**
     * @description
     * ngMe constructor fn.
     *
     * @param  {Object} params
     * @public
     */
    function ngMe (params) {
        this.params = params || {};
        this.modules = {};
    };

    /**
     * @description
     * Run fn on DOM ready.
     *
     * @param  {Function} cb
     * @return {Function}
     * @public
     */
    ngMe.prototype.run = function (cb) {
        if (typeof cb === 'function') return cb();
    };

    /**
     * @description
     * Instantiate module.
     *
     * @param  {String} moduleName
     * @param  {Array} deps
     * @return {Object}
     * @public
     */
    ngMe.prototype.module = function (moduleName, deps) {
        var __super = this;

        function _resolveDependencies (arr, cb) {
            var resolved = (function () {
                    var requires = [];

                    arr.forEach(function (item) {
                        requires.push(__super.modules[item] || null);
                    });

                    return (requires.indexOf(null) !== -1) ? false : requires;
                })();

            if (resolved) {
                return cb(resolved);
            } else {
                var timeout = setTimeout(function () {
                    clearTimeout(timeout);
                    _resolveDependencies(arr, cb);
                }, 0);
            }

        }

        if (this.isString(moduleName) && this.isArray(deps)) {

            /**
             * @description
             * Module dependency constructor fn.
             *
             * @param {Array} deps
             * @public
             */
            function ModuleConstructor (deps) {
                this.requires = deps;
            }

            /**
             * @description
             * Instantiate module's controller.
             *
             * @param  {String} vm
             * @param  {Function} scope
             * @return {Object}
             * @public
             */
            ModuleConstructor.prototype.controller = function (vm, Scope) {
                var _this = this;

                /**
                 * @description
                 * Module constructor fn.
                 *
                 * @param {String} moduleName
                 * @param {String} vm
                 * @param {Function} scope
                 * @public
                 */
                function Module (moduleName, vm, scope) {
                    this.name = moduleName;
                    this[vm] = scope;
                    this.requires = _this.requires;
                };

                /**
                 * @description
                 * Invoke controller's scope.
                 *
                 * @return {Object}
                 * @public
                 */
                Module.prototype.$$scope = function () {
                    var _this = this;
                    var _args = Array.prototype.slice.call(arguments)[0];

                    document.addEventListener('DOMContentLoaded', function () {
                        _resolveDependencies(_args, function (requires) {
                            _this[vm].apply(_this[vm], requires);
                            return _this;
                        });
                    });
                }

                __super.modules[moduleName] = Scope;

                return (new Module(moduleName, vm, Scope)).$$scope(deps);
            };

            return new ModuleConstructor(Array.prototype.slice.call(deps));
        }

        return {};
    };

    /**
     * @description
     * Check if param is array.
     *
     * @param  {*} param
     * @return {Boolean}
     * @public
     */
    ngMe.prototype.isArray = function (param) {
        return Object.prototype.toString.call(param) === '[object Array]';
    };

    /**
     * @description
     * Check if param is string.
     *
     * @param  {*} param
     * @return {Boolean}
     * @public
     */
    ngMe.prototype.isString = function (param) {
        return typeof param === 'string';
    };

    window.ngMe = new ngMe();
})(window);

;(function () {
    'use strict';

    ngMe.run(function () {

        var bModule = ngMe.module('bModule', ['cModule', 'aModule'])
            .controller('BController', BController);

        function BController (cModule, aModule) {
            var vm = this;

            vm.fnB = fnB;
            vm.callFromA = callFromA;

            init();

            function init () {
                setTimeout(function () {
                    vm.fnB();
                }, 2000);

            }

            function fnB () {
                aModule.fnA();
                document.addEventListener('click', function () {
                    cModule.fnC();
                });

            };

            function callFromA () {
                console.log('called from moduleA');
            }
        }

        ngMe.module('aModule', ['bModule'])
            .controller('AController', AController);

        function AController (bModule) {
            var vm = this;

            vm.fnA = fnA;

            init();

            function init () {
                fnA();
            }

            function fnA () {
                bModule.callFromA();
            };
        }

        var cModule = ngMe.module('cModule', [])
            .controller('CController', CController);

        function CController () {
            var vm = this;

            vm.fnC = fnC;

            function fnC () {
                console.log('fn C');
            }
        }

    });
})();
<|endoftext|>