<commit_before>$(document).ready(function() {

  var view;

  module("Backbone.View", {

    setup: function() {
      view = new Backbone.View({
        id        : 'test-view',
        className : 'test-view'
      });
    }

  });

  test("View: constructor", 4, function() {
    equal(view.el.id, 'test-view');
    equal(view.el.className, 'test-view');
    equal(view.options.id, 'test-view');
    equal(view.options.className, 'test-view');
  });

  test("View: jQuery", 2, function() {
    view.setElement(document.body);
    ok(view.$('#qunit-header a').get(0).innerHTML.match(/Backbone Test Suite/));
    ok(view.$('#qunit-header a').get(1).innerHTML.match(/Backbone Speed Suite/));
  });

  test("View: make", 3, function() {
    var div = view.make('div', {id: 'test-div'}, "one two three");
    equal(div.tagName.toLowerCase(), 'div');
    equal(div.id, 'test-div');
    equal($(div).text(), 'one two three');
  });

  test("View: make can take falsy values for content", 2, function() {
    var div = view.make('div', {id: 'test-div'}, 0);
    equal($(div).text(), '0');

    var div = view.make('div', {id: 'test-div'}, '');
    equal($(div).text(), '');
  });

  test("View: initialize", 1, function() {
    var View = Backbone.View.extend({
      initialize: function() {
        this.one = 1;
      }
    });
    var view = new View;
    equal(view.one, 1);
  });

  test("View: delegateEvents", 6, function() {
    var counter = 0;
    var counter2 = 0;
    view.setElement(document.body);
    view.increment = function(){ counter++; };
    view.$el.bind('click', function(){ counter2++; });
    var events = {"click #qunit-banner": "increment"};
    view.delegateEvents(events);
    $('#qunit-banner').trigger('click');
    equal(counter, 1);
    equal(counter2, 1);
    $('#qunit-banner').trigger('click');
    equal(counter, 2);
    equal(counter2, 2);
    view.delegateEvents(events);
    $('#qunit-banner').trigger('click');
    equal(counter, 3);
    equal(counter2, 3);
  });

  test("View: delegateEvents allows functions for callbacks", 3, function() {
    view.counter = 0;
    view.setElement("#qunit-banner");
    var events = {"click": function() { this.counter++; }};
    view.delegateEvents(events);
    $('#qunit-banner').trigger('click');
    equal(view.counter, 1);
    $('#qunit-banner').trigger('click');
    equal(view.counter, 2);
    view.delegateEvents(events);
    $('#qunit-banner').trigger('click');
    equal(view.counter, 3);
  });

  test("View: undelegateEvents", 6, function() {
    var counter = 0;
    var counter2 = 0;
    view.setElement(document.body);
    view.increment = function(){ counter++; };
    $(view.el).unbind('click');
    $(view.el).bind('click', function(){ counter2++; });
    var events = {"click #qunit-userAgent": "increment"};
    view.delegateEvents(events);
    $('#qunit-userAgent').trigger('click');
    equal(counter, 1);
    equal(counter2, 1);
    view.undelegateEvents();
    $('#qunit-userAgent').trigger('click');
    equal(counter, 1);
    equal(counter2, 2);
    view.delegateEvents(events);
    $('#qunit-userAgent').trigger('click');
    equal(counter, 2);
    equal(counter2, 3);
  });

  test("View: _ensureElement with DOM node el", 1, function() {
    var ViewClass = Backbone.View.extend({
      el: document.body
    });
    var view = new ViewClass;
    equal(view.el, document.body);
  });

  test("View: _ensureElement with string el", 3, function() {
    var ViewClass = Backbone.View.extend({
      el: "body"
    });
    var view = new ViewClass;
    strictEqual(view.el, document.body);

    ViewClass = Backbone.View.extend({
      el: "#testElement > h1"
    });
    view = new ViewClass;
    strictEqual(view.el, $("#testElement > h1").get(0));

    ViewClass = Backbone.View.extend({
      el: "#nonexistent"
    });
    view = new ViewClass;
    ok(!view.el);
  });

  test("View: with className and id functions", 2, function() {
    var viewClass = Backbone.View.extend({
      className: function() {
        return 'one';
      },
      id: function() {
        return 'two';
      }
    });
    equal((new viewClass).el.className, 'one');
    equal((new viewClass).el.id, 'two');
  });

  test("View: with attributes", 2, function() {
    var view = new Backbone.View({attributes : {'class': 'one', id: 'two'}});
    equal(view.el.className, 'one');
    equal(view.el.id, 'two');
  });

  test("View: with attributes as a function", 1, function() {
    var viewClass = Backbone.View.extend({
      attributes: function() {
        return {'class': 'dynamic'};
      }
    });
    equal((new viewClass).el.className, 'dynamic');
  });

  test("View: multiple views per element", 3, function() {
    var count = 0, ViewClass = Backbone.View.extend({
      el: $("body"),
      events: {
        "click": "click"
      },
      click: function() {
        count++;
      }
    });

    var view1 = new ViewClass;
    $("body").trigger("click");
    equal(1, count);

    var view2 = new ViewClass;
    $("body").trigger("click");
    equal(3, count);

    view1.delegateEvents();
    $("body").trigger("click");
    equal(5, count);
  });

  test("View: custom events, with namespaces", 2, function() {
    var count = 0;
    var ViewClass = Backbone.View.extend({
      el: $('body'),
      events: function() {
        return {"fake$event.namespaced": "run"};
      },
      run: function() {
        count++;
      }
    });

    var view = new ViewClass;
    $('body').trigger('fake$event').trigger('fake$event');
    equal(count, 2);
    $('body').unbind('.namespaced');
    $('body').trigger('fake$event');
    equal(count, 2);
  });

  test("#1048 - setElement uses provided object.", 2, function() {
    var $el = $('body');
    var view = new Backbone.View({el: $el});
    ok(view.$el === $el);
    view.setElement($el = $($el));
    ok(view.$el === $el);
  });

  test("#986 - Undelegate before changing element.", 1, function() {
    var a = $('<button></button>');
    var b = $('<button></button>');
    var View = Backbone.View.extend({
      events: {click: function(e) { ok(view.el === e.target); }}
    });
    var view = new View({el: a});
    view.setElement(b);
    a.trigger('click');
    b.trigger('click');
  });

  test("#1172 - Clone attributes object", 2, function() {
    var View = Backbone.View.extend({attributes: {foo: 'bar'}});
    var v1 = new View({id: 'foo'});
    strictEqual(v1.el.id, 'foo');
    var v2 = new View();
    ok(!v2.el.id);
  });

  test("#1228 - tagName can be provided as a function", 1, function() {
    var View = Backbone.View.extend({tagName: function(){ return 'p'; }});
    ok(new View().$el.is('p'));
  });

});
<commit_msg>Tweak id/className test.<commit_after>$(document).ready(function() {

  var view;

  module("Backbone.View", {

    setup: function() {
      view = new Backbone.View({
        id        : 'test-view',
        className : 'test-view'
      });
    }

  });

  test("View: constructor", 4, function() {
    equal(view.el.id, 'test-view');
    equal(view.el.className, 'test-view');
    equal(view.options.id, 'test-view');
    equal(view.options.className, 'test-view');
  });

  test("View: jQuery", 2, function() {
    view.setElement(document.body);
    ok(view.$('#qunit-header a').get(0).innerHTML.match(/Backbone Test Suite/));
    ok(view.$('#qunit-header a').get(1).innerHTML.match(/Backbone Speed Suite/));
  });

  test("View: make", 3, function() {
    var div = view.make('div', {id: 'test-div'}, "one two three");
    equal(div.tagName.toLowerCase(), 'div');
    equal(div.id, 'test-div');
    equal($(div).text(), 'one two three');
  });

  test("View: make can take falsy values for content", 2, function() {
    var div = view.make('div', {id: 'test-div'}, 0);
    equal($(div).text(), '0');

    var div = view.make('div', {id: 'test-div'}, '');
    equal($(div).text(), '');
  });

  test("View: initialize", 1, function() {
    var View = Backbone.View.extend({
      initialize: function() {
        this.one = 1;
      }
    });
    var view = new View;
    equal(view.one, 1);
  });

  test("View: delegateEvents", 6, function() {
    var counter = 0;
    var counter2 = 0;
    view.setElement(document.body);
    view.increment = function(){ counter++; };
    view.$el.bind('click', function(){ counter2++; });
    var events = {"click #qunit-banner": "increment"};
    view.delegateEvents(events);
    $('#qunit-banner').trigger('click');
    equal(counter, 1);
    equal(counter2, 1);
    $('#qunit-banner').trigger('click');
    equal(counter, 2);
    equal(counter2, 2);
    view.delegateEvents(events);
    $('#qunit-banner').trigger('click');
    equal(counter, 3);
    equal(counter2, 3);
  });

  test("View: delegateEvents allows functions for callbacks", 3, function() {
    view.counter = 0;
    view.setElement("#qunit-banner");
    var events = {"click": function() { this.counter++; }};
    view.delegateEvents(events);
    $('#qunit-banner').trigger('click');
    equal(view.counter, 1);
    $('#qunit-banner').trigger('click');
    equal(view.counter, 2);
    view.delegateEvents(events);
    $('#qunit-banner').trigger('click');
    equal(view.counter, 3);
  });

  test("View: undelegateEvents", 6, function() {
    var counter = 0;
    var counter2 = 0;
    view.setElement(document.body);
    view.increment = function(){ counter++; };
    $(view.el).unbind('click');
    $(view.el).bind('click', function(){ counter2++; });
    var events = {"click #qunit-userAgent": "increment"};
    view.delegateEvents(events);
    $('#qunit-userAgent').trigger('click');
    equal(counter, 1);
    equal(counter2, 1);
    view.undelegateEvents();
    $('#qunit-userAgent').trigger('click');
    equal(counter, 1);
    equal(counter2, 2);
    view.delegateEvents(events);
    $('#qunit-userAgent').trigger('click');
    equal(counter, 2);
    equal(counter2, 3);
  });

  test("View: _ensureElement with DOM node el", 1, function() {
    var ViewClass = Backbone.View.extend({
      el: document.body
    });
    var view = new ViewClass;
    equal(view.el, document.body);
  });

  test("View: _ensureElement with string el", 3, function() {
    var ViewClass = Backbone.View.extend({
      el: "body"
    });
    var view = new ViewClass;
    strictEqual(view.el, document.body);

    ViewClass = Backbone.View.extend({
      el: "#testElement > h1"
    });
    view = new ViewClass;
    strictEqual(view.el, $("#testElement > h1").get(0));

    ViewClass = Backbone.View.extend({
      el: "#nonexistent"
    });
    view = new ViewClass;
    ok(!view.el);
  });

  test("View: with className and id functions", 2, function() {
    var View = Backbone.View.extend({
      className: function() {
        return 'className';
      },
      id: function() {
        return 'id';
      }
    });
    var view = new View();
    strictEqual(view.el.className, 'className');
    strictEqual(view.el.id, 'id');
  });

  test("View: with attributes", 2, function() {
    var view = new Backbone.View({attributes : {'class': 'one', id: 'two'}});
    equal(view.el.className, 'one');
    equal(view.el.id, 'two');
  });

  test("View: with attributes as a function", 1, function() {
    var viewClass = Backbone.View.extend({
      attributes: function() {
        return {'class': 'dynamic'};
      }
    });
    equal((new viewClass).el.className, 'dynamic');
  });

  test("View: multiple views per element", 3, function() {
    var count = 0, ViewClass = Backbone.View.extend({
      el: $("body"),
      events: {
        "click": "click"
      },
      click: function() {
        count++;
      }
    });

    var view1 = new ViewClass;
    $("body").trigger("click");
    equal(1, count);

    var view2 = new ViewClass;
    $("body").trigger("click");
    equal(3, count);

    view1.delegateEvents();
    $("body").trigger("click");
    equal(5, count);
  });

  test("View: custom events, with namespaces", 2, function() {
    var count = 0;
    var ViewClass = Backbone.View.extend({
      el: $('body'),
      events: function() {
        return {"fake$event.namespaced": "run"};
      },
      run: function() {
        count++;
      }
    });

    var view = new ViewClass;
    $('body').trigger('fake$event').trigger('fake$event');
    equal(count, 2);
    $('body').unbind('.namespaced');
    $('body').trigger('fake$event');
    equal(count, 2);
  });

  test("#1048 - setElement uses provided object.", 2, function() {
    var $el = $('body');
    var view = new Backbone.View({el: $el});
    ok(view.$el === $el);
    view.setElement($el = $($el));
    ok(view.$el === $el);
  });

  test("#986 - Undelegate before changing element.", 1, function() {
    var a = $('<button></button>');
    var b = $('<button></button>');
    var View = Backbone.View.extend({
      events: {click: function(e) { ok(view.el === e.target); }}
    });
    var view = new View({el: a});
    view.setElement(b);
    a.trigger('click');
    b.trigger('click');
  });

  test("#1172 - Clone attributes object", 2, function() {
    var View = Backbone.View.extend({attributes: {foo: 'bar'}});
    var v1 = new View({id: 'foo'});
    strictEqual(v1.el.id, 'foo');
    var v2 = new View();
    ok(!v2.el.id);
  });

  test("#1228 - tagName can be provided as a function", 1, function() {
    var View = Backbone.View.extend({tagName: function(){ return 'p'; }});
    ok(new View().$el.is('p'));
  });

});
<|endoftext|>


<commit_before>'use strict';

var debug = require('debug')('amqp10-test_utilities'),
    expect = require('chai').expect,

    constants = require('../../lib/constants'),
    u = require('../../lib/utilities'),
    DescribedType = require('../../lib/types/described_type'),
    Fields = require('../../lib/types/amqp_composites').Fields,
    AMQPSymbol = require('../../lib/types/amqp_symbol'),
    ST = require('../../lib/types/source_target'),
    Source = ST.Source,
    Target = ST.Target,
    tu = require('./testing_utils');

describe('Utilities', function() {
  describe('#contains()', function() {
    it('should find value when contained', function() {
      expect(u.contains([1, 2, 3], 2)).to.be.true;
    });

    it('should not find value when missing', function() {
      expect(u.contains([1, 2, 3], 4)).to.be.false;
    });

    it('should cope with null/empty arrays', function() {
      expect(u.contains(null, 2)).to.be.false;
      expect(u.contains([], 2)).to.be.false;
    });
  });

  describe('#bufferEquals()', function() {
    it('should succeed when equal', function() {
      var b1 = tu.buildBuffer([1, 2, 3, 4]);
      var b2 = tu.buildBuffer([1, 2, 3, 4]);
      expect(u.bufferEquals(b1, b2)).to.be.true;
    });
    it('should only operate on slices expected', function() {
      var b1 = tu.buildBuffer([1, 2, 3, 4, 5]);
      var b2 = tu.buildBuffer([2, 3, 4, 5, 6]);
      expect(u.bufferEquals(b1, b2, 1, 0, 4)).to.be.true;
    });
    it('should return false quickly on unequal size buffers', function() {
      // Ideally, I'd use two huge buffers, set the timeout low, and ensure the test passes in the time allotted,
      //  but that's (a) a pain, and (b) prone to sporadic failures, so just ensuring it at least gives the right answer.
      var b1 = tu.buildBuffer([1]);
      var b2 = tu.buildBuffer([1, 2]);
      expect(u.bufferEquals(b1, b2)).to.be.false;
    });
  });

  describe('#coerce()', function() {
    it('should coerce strings into symbols', function() {
      var result = u.coerce('en-US', AMQPSymbol);
      expect(result).to.be.an.instanceOf(AMQPSymbol);
    });

    it('should ignore if of same type', function() {
      var result = u.coerce(new AMQPSymbol('en-US'), AMQPSymbol);
      expect(result).to.be.an.instanceOf(AMQPSymbol);
      expect(result.contents).to.be.a('string');
    });

    it('should coerce array of values', function() {
      var result = u.coerce(['a', 'b', 'c'], AMQPSymbol);
      expect(result).to.be.an.instanceOf(Array);
      expect(result).to.have.length(3);
      expect(result[0]).to.be.an.instanceOf(AMQPSymbol);
    });

    it('should pass through nulls', function() {
      var result = u.coerce(null, AMQPSymbol);
      expect(result).to.be.null;
    });
  });

  describe('#deepMerge()', function() {
    it('should work for flat', function() {
      var flat = { foo: 1, bar: 2 };
      var defaults = { bar: 3, baz: 4 };
      var merged = u.deepMerge(flat, defaults);
      expect(merged).to.eql({ foo: 1, bar: 2, baz: 4 });
    });

    it('should work for nested', function() {
      var nested = { foo: { bar: 1, baz: 2 }, bat: 3 };
      var defaults = { foo: { zoop: 1 }, dubin: { a: 1 } };
      var merged = u.deepMerge(nested, defaults);
      expect(merged).to.eql({ foo: { bar: 1, baz: 2, zoop: 1 }, bat: 3, dubin: { a: 1 }});
    });

    // @todo Fix deepMerge to preserve object __proto__ identity.
    it('should work for nested with custom types', function() {
      var nested = { foo: { bar: new AMQPSymbol('s1') } };
      var defaults = { foo: { baz: new AMQPSymbol('s2') }, bat: new AMQPSymbol('s3') };
      var merged = u.deepMerge(nested, defaults);
      expect(merged.bat).to.be.an.instanceOf(AMQPSymbol);
      expect(merged.foo.bar).to.be.an.instanceOf(AMQPSymbol);
      expect(merged.foo.baz).to.be.an.instanceOf(AMQPSymbol);
    });

    it('should work for described types', function() {
      var dt = new DescribedType(new AMQPSymbol('keyname'), 'value string');
      var merged = u.deepMerge({ options: dt });
      expect(merged.options).to.be.an.instanceOf(DescribedType);
      expect(merged.options.descriptor).to.be.an.instanceOf(AMQPSymbol);
      expect(merged.options.descriptor.contents).to.eql('keyname');
      expect(merged.options.value).to.eql('value string');
    });

    it('should work for attach frame details', function() {
      var input = { options: {
        name: 'recv',
                    role: constants.linkRole.receiver,
                    source: new Source({
          address: 'recv',
          filter: new Fields({
                        'apache.org:selector-filter:string' :
                            new DescribedType(new AMQPSymbol('apache.org:selector-filter:string'),
                                "amqp.annotation.x-opt-offset > '" + 1000 + "'")
          })
        }),
                    target: new Target({
          address: 'localhost'
        }),
                    senderSettleMode: constants.senderSettleMode.settled,
                    receiverSettleMode: constants.receiverSettleMode.autoSettle,
                    maxMessageSize: 10000,
                    initialDeliveryCount: 1
      }};
      var merged = u.deepMerge(input);
      expect(merged).to.eql(input);
    });

    it('should work for chains', function() {
      var last = { a: 1, b: 1, c: 1 };
      var middle = { b: 2, c: 2 };
      var first = { c: 3 };
      var merged = u.deepMerge(first, middle, last);
      expect(merged).to.eql({ a: 1, b: 2, c: 3 });
    });
  });

  describe('#parseAddress()', function() {

    it('should match amqp(|s) no port no route', function() {
      var addr = 'amqp://localhost';
      var result = u.parseAddress(addr);
      expect(result.protocol).to.eql('amqp');
      expect(result.host).to.eql('localhost');
      expect(result.port).to.eql(5672);
      expect(result.path).to.eql('/');

      addr = 'amqps://127.0.0.1';
      result = u.parseAddress(addr);
      expect(result).to.eql({
        protocol: 'amqps',
        host: '127.0.0.1',
        port: 5671,
        rootUri: 'amqps://127.0.0.1:5671',
        path: '/'
      });
    });

    it('should match with port and with/without route', function() {
      var addr = 'amqp://localhost:1234';
      var result = u.parseAddress(addr);
      expect(result).to.eql({
        protocol: 'amqp',
        host: 'localhost',
        port: 1234,
        rootUri: 'amqp://localhost:1234',
        path: '/'
      });

      addr = 'amqps://mq.myhost.com:1235/myroute?with=arguments&multiple=arguments';
      result = u.parseAddress(addr);
      expect(result).to.eql({
        protocol: 'amqps',
        host: 'mq.myhost.com',
        port: 1235,
        rootUri: 'amqps://mq.myhost.com:1235',
        path: '/myroute?with=arguments&multiple=arguments'
      });
    });

    it('should match ip + port', function() {
      var addr = 'amqp://10.42.1.193:5672/testqueue';
      var result = u.parseAddress(addr);
      expect(result).to.eql({
        protocol: 'amqp',
        host: '10.42.1.193',
        port: 5672,
        rootUri: 'amqp://10.42.1.193:5672',
        path: '/testqueue'
      });
    });

    it('should match credentials no port no route', function() {
      var addr = 'amqp://username:password@my.amqp.server';
      var result = u.parseAddress(addr);
      expect(result).to.eql({
        protocol: 'amqp',
        host: 'my.amqp.server',
        port: 5672,
        path: '/',
        user: 'username',
        pass: 'password',
        rootUri: 'amqp://username:password@my.amqp.server:5672'
      });
    });

    it('should match credentials with port and route', function() {
      var addr = 'amqps://username:password@192.168.1.1:1234/myroute';
      var result = u.parseAddress(addr);
      expect(result).to.eql({
        protocol: 'amqps',
        user: 'username',
        pass: 'password',
        host: '192.168.1.1',
        port: 1234,
        path: '/myroute',
        rootUri: 'amqps://username:password@192.168.1.1:1234'
      });
    });

    it('should throw error on invalid address', function() {
      var addr = 'invalid://localhost';
      expect(function() {
        u.parseAddress(addr);
      }).to.throw(Error, null, 'Should validate protocol');

      addr = 'amqp://host:non-numeric';
      expect(function() {
        u.parseAddress(addr);
      }).to.throw(Error, null, 'Should validate port');

      addr = 'amqp://host:123:what-is-this?';
      expect(function() {
        u.parseAddress(addr);
      }).to.throw(Error, null, 'Bad regex match');
    });
  });

  describe('#generateTimeouts', function() {
    it('should generate a fibonacci sequence of timeouts', function() {
      var options = {
        retries: 10,
        strategy: 'fibonacci',
      };

      var timeouts = u.generateTimeouts(options);
      expect(timeouts).to.eql(
        [0, 1, 1, 2, 3, 5, 8, 13, 21, 34].map(function(i) { return i * 1000; })
      );
    });

    it('should generate an exponential sequence of timeouts', function() {
      var options = {
        retries: 10,
        strategy: 'exponential',
      };

      var timeouts = u.generateTimeouts(options);
      expect(timeouts).to.eql(
        [1, 2, 4, 8, 16, 32, 64, 128, 256, 512].map(function(i) { return i * 1000; })
      );
    });
  });
});
<commit_msg>test(utilities): refactor parseAddress tests<commit_after>'use strict';

var debug = require('debug')('amqp10-test_utilities'),
    expect = require('chai').expect,

    constants = require('../../lib/constants'),
    u = require('../../lib/utilities'),
    DescribedType = require('../../lib/types/described_type'),
    Fields = require('../../lib/types/amqp_composites').Fields,
    AMQPSymbol = require('../../lib/types/amqp_symbol'),
    ST = require('../../lib/types/source_target'),
    Source = ST.Source,
    Target = ST.Target,
    tu = require('./testing_utils');

describe('Utilities', function() {
  describe('#contains()', function() {
    it('should find value when contained', function() {
      expect(u.contains([1, 2, 3], 2)).to.be.true;
    });

    it('should not find value when missing', function() {
      expect(u.contains([1, 2, 3], 4)).to.be.false;
    });

    it('should cope with null/empty arrays', function() {
      expect(u.contains(null, 2)).to.be.false;
      expect(u.contains([], 2)).to.be.false;
    });
  });

  describe('#bufferEquals()', function() {
    it('should succeed when equal', function() {
      var b1 = tu.buildBuffer([1, 2, 3, 4]);
      var b2 = tu.buildBuffer([1, 2, 3, 4]);
      expect(u.bufferEquals(b1, b2)).to.be.true;
    });
    it('should only operate on slices expected', function() {
      var b1 = tu.buildBuffer([1, 2, 3, 4, 5]);
      var b2 = tu.buildBuffer([2, 3, 4, 5, 6]);
      expect(u.bufferEquals(b1, b2, 1, 0, 4)).to.be.true;
    });
    it('should return false quickly on unequal size buffers', function() {
      // Ideally, I'd use two huge buffers, set the timeout low, and ensure the test passes in the time allotted,
      //  but that's (a) a pain, and (b) prone to sporadic failures, so just ensuring it at least gives the right answer.
      var b1 = tu.buildBuffer([1]);
      var b2 = tu.buildBuffer([1, 2]);
      expect(u.bufferEquals(b1, b2)).to.be.false;
    });
  });

  describe('#coerce()', function() {
    it('should coerce strings into symbols', function() {
      var result = u.coerce('en-US', AMQPSymbol);
      expect(result).to.be.an.instanceOf(AMQPSymbol);
    });

    it('should ignore if of same type', function() {
      var result = u.coerce(new AMQPSymbol('en-US'), AMQPSymbol);
      expect(result).to.be.an.instanceOf(AMQPSymbol);
      expect(result.contents).to.be.a('string');
    });

    it('should coerce array of values', function() {
      var result = u.coerce(['a', 'b', 'c'], AMQPSymbol);
      expect(result).to.be.an.instanceOf(Array);
      expect(result).to.have.length(3);
      expect(result[0]).to.be.an.instanceOf(AMQPSymbol);
    });

    it('should pass through nulls', function() {
      var result = u.coerce(null, AMQPSymbol);
      expect(result).to.be.null;
    });
  });

  describe('#deepMerge()', function() {
    it('should work for flat', function() {
      var flat = { foo: 1, bar: 2 };
      var defaults = { bar: 3, baz: 4 };
      var merged = u.deepMerge(flat, defaults);
      expect(merged).to.eql({ foo: 1, bar: 2, baz: 4 });
    });

    it('should work for nested', function() {
      var nested = { foo: { bar: 1, baz: 2 }, bat: 3 };
      var defaults = { foo: { zoop: 1 }, dubin: { a: 1 } };
      var merged = u.deepMerge(nested, defaults);
      expect(merged).to.eql({ foo: { bar: 1, baz: 2, zoop: 1 }, bat: 3, dubin: { a: 1 }});
    });

    // @todo Fix deepMerge to preserve object __proto__ identity.
    it('should work for nested with custom types', function() {
      var nested = { foo: { bar: new AMQPSymbol('s1') } };
      var defaults = { foo: { baz: new AMQPSymbol('s2') }, bat: new AMQPSymbol('s3') };
      var merged = u.deepMerge(nested, defaults);
      expect(merged.bat).to.be.an.instanceOf(AMQPSymbol);
      expect(merged.foo.bar).to.be.an.instanceOf(AMQPSymbol);
      expect(merged.foo.baz).to.be.an.instanceOf(AMQPSymbol);
    });

    it('should work for described types', function() {
      var dt = new DescribedType(new AMQPSymbol('keyname'), 'value string');
      var merged = u.deepMerge({ options: dt });
      expect(merged.options).to.be.an.instanceOf(DescribedType);
      expect(merged.options.descriptor).to.be.an.instanceOf(AMQPSymbol);
      expect(merged.options.descriptor.contents).to.eql('keyname');
      expect(merged.options.value).to.eql('value string');
    });

    it('should work for attach frame details', function() {
      var input = { options: {
        name: 'recv',
                    role: constants.linkRole.receiver,
                    source: new Source({
          address: 'recv',
          filter: new Fields({
                        'apache.org:selector-filter:string' :
                            new DescribedType(new AMQPSymbol('apache.org:selector-filter:string'),
                                "amqp.annotation.x-opt-offset > '" + 1000 + "'")
          })
        }),
                    target: new Target({
          address: 'localhost'
        }),
                    senderSettleMode: constants.senderSettleMode.settled,
                    receiverSettleMode: constants.receiverSettleMode.autoSettle,
                    maxMessageSize: 10000,
                    initialDeliveryCount: 1
      }};
      var merged = u.deepMerge(input);
      expect(merged).to.eql(input);
    });

    it('should work for chains', function() {
      var last = { a: 1, b: 1, c: 1 };
      var middle = { b: 2, c: 2 };
      var first = { c: 3 };
      var merged = u.deepMerge(first, middle, last);
      expect(merged).to.eql({ a: 1, b: 2, c: 3 });
    });
  });

  describe('#parseAddress()', function() {
    [
      {
        description: 'amqp no port no route',
        address: 'amqp://127.0.0.1',
        expected: {
          protocol: 'amqp', host: '127.0.0.1', port: 5672, path: '/',
          rootUri: 'amqp://127.0.0.1:5672'
        }
      },
      {
        description: 'amqps no port no route',
        address: 'amqps://localhost',
        expected: {
          protocol: 'amqps', host: 'localhost', port: 5671, path: '/',
          rootUri: 'amqps://localhost:5671'
        }
      },
      {
        description: 'should match with port and with/without route (1)',
        address: 'amqp://localhost:1234',
        expected: {
          protocol: 'amqp', host: 'localhost', port: 1234, path: '/',
          rootUri: 'amqp://localhost:1234'
        }
      },
      {
        description: 'should match with port and with/without route (2)',
        address: 'amqps://mq.myhost.com:1235/myroute?with=arguments&multiple=arguments',
        expected: {
          protocol: 'amqps', host: 'mq.myhost.com', port: 1235,
          path: '/myroute?with=arguments&multiple=arguments',
          rootUri: 'amqps://mq.myhost.com:1235'
        }
      },
      {
        description: 'should match ip + port',
        address: 'amqp://10.42.1.193:8118/testqueue',
        expected: {
          protocol: 'amqp', host: '10.42.1.193', port: 8118, path: '/testqueue',
          rootUri: 'amqp://10.42.1.193:8118'
        }
      },
      {
        description: 'should match credentials no port no route',
        address: 'amqp://username:password@my.amqp.server',
        expected: {
          protocol: 'amqp', host: 'my.amqp.server', port: 5672, path: '/',
          user: 'username', pass: 'password',
          rootUri: 'amqp://username:password@my.amqp.server:5672'
        }
      },
      {
        description: 'should match credentials with port and route',
        address: 'amqps://username:password@192.168.1.1:1234/myroute',
        expected: {
          protocol: 'amqps', host: '192.168.1.1', port: 1234, path: '/myroute',
          user: 'username', pass: 'password',
          rootUri: 'amqps://username:password@192.168.1.1:1234'
        }
      }
    ].forEach(function(testCase) {
      it('should match ' + testCase.description, function() {
        var result = u.parseAddress(testCase.address);
        expect(result).to.eql(testCase.expected);
      });
    });

    [
      { address: 'invalid://localhost', error: 'Should validate protocol' },
      { address: 'amqp://host:non-numeric', error: 'Should validate port' },
      { address: 'amqp://host:123:what-is-this?', error: 'Bad regex match' },

    ].forEach(function(testCase, idx) {
      it('should throw error on invalid address (' + (idx+1) + ')', function() {
        expect(function() {
          u.parseAddress(testCase.address);
        }).to.throw(Error, null, testCase.error);
      });
    });

  });

  describe('#generateTimeouts', function() {
    it('should generate a fibonacci sequence of timeouts', function() {
      var options = {
        retries: 10,
        strategy: 'fibonacci',
      };

      var timeouts = u.generateTimeouts(options);
      expect(timeouts).to.eql(
        [0, 1, 1, 2, 3, 5, 8, 13, 21, 34].map(function(i) { return i * 1000; })
      );
    });

    it('should generate an exponential sequence of timeouts', function() {
      var options = {
        retries: 10,
        strategy: 'exponential',
      };

      var timeouts = u.generateTimeouts(options);
      expect(timeouts).to.eql(
        [1, 2, 4, 8, 16, 32, 64, 128, 256, 512].map(function(i) { return i * 1000; })
      );
    });
  });
});
<|endoftext|>


<commit_before>let React = require("react")
let {errorList, sizeClassNames, formGroupCx, label} = require("../util.js")
let {div, textarea} = React.DOM
let cx = require("classnames")

export default class extends React.Component {

  static displayName = "Frig.friggingBootstrap.Text"

  static defaultProps = Object.assign(require("../default_props.js"))

  constructor(props) {
    super(props)

    this.state = {
      errors: undefined,
      edited: false,
    }
  }

  _inputHtml() {
  	return Object.assign({}, this.props.inputHtml, {
  		className: `${this.props.className || ""} form-control`.trim(),
  	})
  }

  _cx() {
    return cx({
      "form-group": true,
      "has-error": this.state.errors != null,
      "has-success": this.state.edited && this.state.errors == null,
    })
  }

  _errorList() {
    if (this.state.errors == null) return ""
    return errorList(this.state.errors)
  }

  _label() {
    if (this.props.label == null) return ""
    return label(this.props.labelHtml, this.props.label)
  }

  render() {
    return div({className: cx(sizeClassNames(this.props))},
      div({className: this._cx()},
        this._label(),
        div({className: "controls"},
          textarea(this._inputHtml()),
        ),
        this._errorList(),
      ),
    )
  }

}
<commit_msg>Add Value Link Prop To Textarea Component<commit_after>let React = require("react")
let {errorList, sizeClassNames, formGroupCx, label} = require("../util.js")
let {div, textarea} = React.DOM
let cx = require("classnames")

export default class extends React.Component {

  static displayName = "Frig.friggingBootstrap.Text"

  static defaultProps = Object.assign(require("../default_props.js"))

  constructor(props) {
    super(props)

    this.state = {
      errors: undefined,
      edited: false,
    }
  }

  _inputHtml() {
  	return Object.assign({}, this.props.inputHtml, {
  		className: `${this.props.className || ""} form-control`.trim(),
  		valueLink: this.props.valueLink,
  	})
  }

  _cx() {
    return cx({
      "form-group": true,
      "has-error": this.state.errors != null,
      "has-success": this.state.edited && this.state.errors == null,
    })
  }

  _errorList() {
    if (this.state.errors == null) return ""
    return errorList(this.state.errors)
  }

  _label() {
    if (this.props.label == null) return ""
    return label(this.props.labelHtml, this.props.label)
  }

  render() {
    return div({className: cx(sizeClassNames(this.props))},
      div({className: this._cx()},
        this._label(),
        div({className: "controls"},
          textarea(this._inputHtml()),
        ),
        this._errorList(),
      ),
    )
  }

}
<|endoftext|>


<commit_before>Package.describe({
	name: 'rocketchat:webrtc',
	version: '0.0.1',
	summary: 'Package WebRTC for Meteor server',
	git: ''
});

Package.onUse(function(api) {
	api.versionsFrom('1.0');

	api.use([
		'coffeescript',
		'rocketchat:lib@0.0.1'
	]);

	api.addFiles('common.js');
	api.addFiles('adapter.js', ['client']);
	api.addFiles('webrtc.js', ['client']);
	api.addFiles('server.js', ['server']);

	api.export('webrtc')
});

Package.onTest(function(api) {});
<commit_msg>fixed dependence<commit_after>Package.describe({
	name: 'rocketchat:webrtc',
	version: '0.0.1',
	summary: 'Package WebRTC for Meteor server',
	git: ''
});

Package.onUse(function(api) {
	api.versionsFrom('1.0');

	api.use([
		'coffeescript',
		'arunoda:streams@0.1.17',
		'rocketchat:lib@0.0.1'
	]);

	api.addFiles('common.js');
	api.addFiles('adapter.js', ['client']);
	api.addFiles('webrtc.js', ['client']);
	api.addFiles('server.js', ['server']);

	api.export('webrtc')
});

Package.onTest(function(api) {});
<|endoftext|>


<commit_before>import templates from '../../templates';
import GeneticsUtils from '../../utilities/genetics-utils';
import { range, shuffle, assign } from 'lodash';
import AuthoringUtils from '../../utilities/authoring-utils';
import { notificationType } from '../../modules/notifications';

/**
 * Tolerant splitter into a list of strings.
 * @param list - null, "one, two" or ["one", "two"]
 * returns ["one", "two"]
 */
function split(list) {
  if (list && list.split) return list.split(",").map(item => item.trim());
  if (Array.isArray(list)) return list;
  return [];
}

function templateFromAuthoredChallenge(authoredChallenge) {
  const templateName = authoredChallenge.template,
        template = templateName && templates[templateName];
  return template;
}

function trialFromState(state) {
  return state.trial || 0;
}

function processAuthoredBaskets(authoredChallenge, state) {
  const baskets = authoredChallenge && authoredChallenge.baskets;
  return baskets || state.baskets;
}

function processAuthoredGametes(authoredChallenge, drakes, state) {
  const template = templateFromAuthoredChallenge(authoredChallenge),
        trial = trialFromState(state),
        parentPools = template.authoredGametesToGametePools &&
                        template.authoredGametesToGametePools(authoredChallenge, drakes, trial);
  return parentPools
            ? state.gametes.merge({ parentPools })
            : state.gametes;
}

function processAuthoredDrakes(authoredChallenge, authoredTrialNumber, template, trialNumber) {
  // takes authored list of named drakes ("mother", etc) and returns an
  // array specific for this template
  const authoredDrakesArray = template.authoredDrakesToDrakeArray(authoredChallenge, authoredTrialNumber, trialNumber);
  let   alleleString = null,
        linkedGeneDrake = null;

  // turn authored alleles into completely-specified alleleStrings
  let drakes = authoredDrakesArray.map(function(drakeDef, i) {
    if (!drakeDef) return null;
    // Keep the drake as female until the end, so no sex-linked information is lost for linked drakes
    let femaleDrake = new BioLogica.Organism(BioLogica.Species.Drake, drakeDef.alleles, BioLogica.FEMALE);

    alleleString = femaleDrake.getAlleleString();
    if (authoredChallenge.linkedGenes) {
      if (i === authoredChallenge.linkedGenes.drakes[0]) {
        linkedGeneDrake = femaleDrake;
      } else if (authoredChallenge.linkedGenes.drakes.indexOf(i)) {
        let linkedGenes = split(authoredChallenge.linkedGenes.genes);
        for (let gene of linkedGenes) {
          let copyIntoGenes = femaleDrake.genetics.genotype.getAlleleString([gene], femaleDrake.genetics);
          let masterGenes = linkedGeneDrake.genetics.genotype.getAlleleString([gene], femaleDrake.genetics);
          alleleString = alleleString.replace(copyIntoGenes, masterGenes);
        }
      }
    }
    let fixedDrake = new BioLogica.Organism(BioLogica.Species.Drake, alleleString, drakeDef.sex);

    let secondXAlleles = null;
    if (drakeDef.sex === BioLogica.MALE) {
      // Store any sex-linked alleles from the authoring document which would be lost because the drake is male
      let fixedFemaleDrake = new BioLogica.Organism(BioLogica.Species.Drake, alleleString, BioLogica.FEMALE);
      secondXAlleles = GeneticsUtils.computeExtraAlleles(fixedFemaleDrake, fixedDrake);
    }

    return assign({}, secondXAlleles ? {secondXAlleles: secondXAlleles} : null, {
      alleleString: fixedDrake.getAlleleString(),
      sex: fixedDrake.sex,
    });

  });
  return drakes;
}

// Returns an array [0...len], optionally shuffled
function createTrialOrder(trial, trials, currentTrialOrder, doShuffle) {
  if (trial > 0)
    return currentTrialOrder;
  if (!trials)
    return [0];
  if (doShuffle)
    return shuffle( range(trials.length) );
  return range(trials.length);
}

export function loadStateFromAuthoring(state, authoring) {
  let trial = state.trial ? state.trial : 0;

  const challenges = AuthoringUtils.getChallengeCount(authoring, state.routeSpec.level, state.routeSpec.mission),
        authoredChallenge = AuthoringUtils.getChallengeDefinition(authoring, state.routeSpec),
        authoredChallengeMetadata = AuthoringUtils.getChallengeMeta(authoring, state.routeSpec);
  if (!authoredChallenge) return state;

  const templateName = authoredChallenge.template,
        template = templateName && templates[templateName];
  if (!template) return state;

  let userChangeableGenes = authoredChallenge.userChangeableGenes;
  // Changeable genes are either authored in the form "wings, legs" or [{mother: "wings", father:""}, {mother: "", father: "wings"}]
  if (typeof userChangeableGenes === "object") {
    let userChangeableGenesByTrial = [];
    for (let trial = 0; trial < userChangeableGenes.length; trial++) {
      userChangeableGenesByTrial.push({
        mother: split(userChangeableGenes[trial].mother),
        father: split(userChangeableGenes[trial].father)
      });
    }
    userChangeableGenes = userChangeableGenesByTrial;
  } else {
    userChangeableGenes = split(userChangeableGenes);
  }

  const challengeType = authoredChallenge.challengeType,
        interactionType = authoredChallenge.interactionType,
        instructions = authoredChallenge.instructions,
        visibleGenes = split(authoredChallenge.visibleGenes),
        hiddenAlleles = split(authoredChallenge.hiddenAlleles),
        baskets = processAuthoredBaskets(authoredChallenge, state),
        showUserDrake = (authoredChallenge.showUserDrake != null) ? authoredChallenge.showUserDrake : false,
        trials = authoredChallenge.targetDrakes,
        numTrials = authoredChallenge.numTrials || (trials ? trials.length : 1),
        trialOrder = createTrialOrder(trial, trials, state.trialOrder, authoredChallenge.randomizeTrials),
        drakes = processAuthoredDrakes(authoredChallenge, trialOrder[trial], template, trial),
        gametes = processAuthoredGametes(authoredChallenge, drakes, state),
        zoomUrl = authoredChallenge.zoomUrl,
        room = authoredChallengeMetadata.room || "simroom",
        roomInfo = (authoring && authoring.rooms) ? authoring.rooms[room] : {},
        location = {id: room, ...roomInfo},
        showingRoom = trial === 0,
        dialog = authoredChallengeMetadata.dialog;

  let goalMoves = null;
  if (template.calculateGoalMoves) {
    goalMoves = template.calculateGoalMoves(drakes);
  } else if (authoredChallenge.goalMoves) {
    goalMoves = authoredChallenge.goalMoves[trial];
  } else {
    goalMoves = -1;
  }

  let messages = [],
      closeButton = null;
  if (dialog) {
    messages = dialog.map( (d) => ({type: notificationType.NARRATIVE, ...d}));
    closeButton = {action: "enterChallengeFromRoom"};
  }

  let authoredState = {
    template: templateName,
    challengeType,
    interactionType,
    instructions,
    showUserDrake,
    userChangeableGenes,
    visibleGenes,
    hiddenAlleles,
    baskets,
    gametes,
    drakes,
    trial,
    trials,
    numTrials,
    trialOrder,
    challenges,
    correct: 0,
    errors: 0,
    moves: 0,
    goalMoves,
    userDrakeHidden: true,
    trialSuccess: false,
    initialDrakes: [...drakes],
    zoomUrl,
    location,
    showingRoom,
    notifications: {
      messages,
      closeButton
    }
  };

  // remove all undefined or null keys
  Object.keys(authoredState).forEach((key) => (authoredState[key] == null) && delete authoredState[key]);

  return state.merge(authoredState);
}

export function loadHome(state, authoring, showMissionEndDialog) {
  let room = "home",
      roomInfo = (authoring && authoring.rooms) ? authoring.rooms[room] : {},
      location = {id: room, ...roomInfo},
      { level, mission, started } = AuthoringUtils.getCurrentMissionFromGems(authoring, state.gems),
      dialogDefs = authoring.application.levels[level].missions[mission].dialog,
      messages = [];

  if (dialogDefs) {
    let whichDialog = started ? "middle" : "start",
        dialog = dialogDefs[whichDialog];

    if (!started && showMissionEndDialog) {
      let previousMission = AuthoringUtils.getPreviousMission(authoring, level, mission);
      if (previousMission) {
        let endDialog = authoring.application.levels[previousMission.level].missions[previousMission.mission].dialog["end"] || [];
        dialog = endDialog.concat(dialog);
      }
    }

    messages = dialog.map( (d) => ({type: notificationType.DIALOG, ...d}));
  }

  let authoredState = {
    location,
    showingRoom: true,
    notifications: {
      messages,
      closeButton: false
    }
  };

  // remove all undefined or null keys
  Object.keys(authoredState).forEach((key) => (authoredState[key] == null) && delete authoredState[key]);

  return state.merge(authoredState);
}

export function loadNextTrial(state, authoring) {
  let trial = state.trial;
  if (state.trialSuccess){
    trial = (state.trial < state.numTrials) ? (trial+1) : 0;
  }
  let nextState = state.merge({
    trial: trial
  });

  return  loadStateFromAuthoring(nextState, authoring);
}
<commit_msg>Fix bug where dialog is showing up between trials<commit_after>import templates from '../../templates';
import GeneticsUtils from '../../utilities/genetics-utils';
import { range, shuffle, assign } from 'lodash';
import AuthoringUtils from '../../utilities/authoring-utils';
import { notificationType } from '../../modules/notifications';

/**
 * Tolerant splitter into a list of strings.
 * @param list - null, "one, two" or ["one", "two"]
 * returns ["one", "two"]
 */
function split(list) {
  if (list && list.split) return list.split(",").map(item => item.trim());
  if (Array.isArray(list)) return list;
  return [];
}

function templateFromAuthoredChallenge(authoredChallenge) {
  const templateName = authoredChallenge.template,
        template = templateName && templates[templateName];
  return template;
}

function trialFromState(state) {
  return state.trial || 0;
}

function processAuthoredBaskets(authoredChallenge, state) {
  const baskets = authoredChallenge && authoredChallenge.baskets;
  return baskets || state.baskets;
}

function processAuthoredGametes(authoredChallenge, drakes, state) {
  const template = templateFromAuthoredChallenge(authoredChallenge),
        trial = trialFromState(state),
        parentPools = template.authoredGametesToGametePools &&
                        template.authoredGametesToGametePools(authoredChallenge, drakes, trial);
  return parentPools
            ? state.gametes.merge({ parentPools })
            : state.gametes;
}

function processAuthoredDrakes(authoredChallenge, authoredTrialNumber, template, trialNumber) {
  // takes authored list of named drakes ("mother", etc) and returns an
  // array specific for this template
  const authoredDrakesArray = template.authoredDrakesToDrakeArray(authoredChallenge, authoredTrialNumber, trialNumber);
  let   alleleString = null,
        linkedGeneDrake = null;

  // turn authored alleles into completely-specified alleleStrings
  let drakes = authoredDrakesArray.map(function(drakeDef, i) {
    if (!drakeDef) return null;
    // Keep the drake as female until the end, so no sex-linked information is lost for linked drakes
    let femaleDrake = new BioLogica.Organism(BioLogica.Species.Drake, drakeDef.alleles, BioLogica.FEMALE);

    alleleString = femaleDrake.getAlleleString();
    if (authoredChallenge.linkedGenes) {
      if (i === authoredChallenge.linkedGenes.drakes[0]) {
        linkedGeneDrake = femaleDrake;
      } else if (authoredChallenge.linkedGenes.drakes.indexOf(i)) {
        let linkedGenes = split(authoredChallenge.linkedGenes.genes);
        for (let gene of linkedGenes) {
          let copyIntoGenes = femaleDrake.genetics.genotype.getAlleleString([gene], femaleDrake.genetics);
          let masterGenes = linkedGeneDrake.genetics.genotype.getAlleleString([gene], femaleDrake.genetics);
          alleleString = alleleString.replace(copyIntoGenes, masterGenes);
        }
      }
    }
    let fixedDrake = new BioLogica.Organism(BioLogica.Species.Drake, alleleString, drakeDef.sex);

    let secondXAlleles = null;
    if (drakeDef.sex === BioLogica.MALE) {
      // Store any sex-linked alleles from the authoring document which would be lost because the drake is male
      let fixedFemaleDrake = new BioLogica.Organism(BioLogica.Species.Drake, alleleString, BioLogica.FEMALE);
      secondXAlleles = GeneticsUtils.computeExtraAlleles(fixedFemaleDrake, fixedDrake);
    }

    return assign({}, secondXAlleles ? {secondXAlleles: secondXAlleles} : null, {
      alleleString: fixedDrake.getAlleleString(),
      sex: fixedDrake.sex,
    });

  });
  return drakes;
}

// Returns an array [0...len], optionally shuffled
function createTrialOrder(trial, trials, currentTrialOrder, doShuffle) {
  if (trial > 0)
    return currentTrialOrder;
  if (!trials)
    return [0];
  if (doShuffle)
    return shuffle( range(trials.length) );
  return range(trials.length);
}

export function loadStateFromAuthoring(state, authoring) {
  let trial = state.trial ? state.trial : 0;

  const challenges = AuthoringUtils.getChallengeCount(authoring, state.routeSpec.level, state.routeSpec.mission),
        authoredChallenge = AuthoringUtils.getChallengeDefinition(authoring, state.routeSpec),
        authoredChallengeMetadata = AuthoringUtils.getChallengeMeta(authoring, state.routeSpec);
  if (!authoredChallenge) return state;

  const templateName = authoredChallenge.template,
        template = templateName && templates[templateName];
  if (!template) return state;

  let userChangeableGenes = authoredChallenge.userChangeableGenes;
  // Changeable genes are either authored in the form "wings, legs" or [{mother: "wings", father:""}, {mother: "", father: "wings"}]
  if (typeof userChangeableGenes === "object") {
    let userChangeableGenesByTrial = [];
    for (let trial = 0; trial < userChangeableGenes.length; trial++) {
      userChangeableGenesByTrial.push({
        mother: split(userChangeableGenes[trial].mother),
        father: split(userChangeableGenes[trial].father)
      });
    }
    userChangeableGenes = userChangeableGenesByTrial;
  } else {
    userChangeableGenes = split(userChangeableGenes);
  }

  const challengeType = authoredChallenge.challengeType,
        interactionType = authoredChallenge.interactionType,
        instructions = authoredChallenge.instructions,
        visibleGenes = split(authoredChallenge.visibleGenes),
        hiddenAlleles = split(authoredChallenge.hiddenAlleles),
        baskets = processAuthoredBaskets(authoredChallenge, state),
        showUserDrake = (authoredChallenge.showUserDrake != null) ? authoredChallenge.showUserDrake : false,
        trials = authoredChallenge.targetDrakes,
        numTrials = authoredChallenge.numTrials || (trials ? trials.length : 1),
        trialOrder = createTrialOrder(trial, trials, state.trialOrder, authoredChallenge.randomizeTrials),
        drakes = processAuthoredDrakes(authoredChallenge, trialOrder[trial], template, trial),
        gametes = processAuthoredGametes(authoredChallenge, drakes, state),
        zoomUrl = authoredChallenge.zoomUrl,
        room = authoredChallengeMetadata.room || "simroom",
        roomInfo = (authoring && authoring.rooms) ? authoring.rooms[room] : {},
        location = {id: room, ...roomInfo},
        showingRoom = trial === 0,
        dialog = authoredChallengeMetadata.dialog;

  let goalMoves = null;
  if (template.calculateGoalMoves) {
    goalMoves = template.calculateGoalMoves(drakes);
  } else if (authoredChallenge.goalMoves) {
    goalMoves = authoredChallenge.goalMoves[trial];
  } else {
    goalMoves = -1;
  }

  let messages = [],
      closeButton = null;
  if (showingRoom && dialog) {
    messages = dialog.map( (d) => ({type: notificationType.NARRATIVE, ...d}));
    closeButton = {action: "enterChallengeFromRoom"};
  }

  let authoredState = {
    template: templateName,
    challengeType,
    interactionType,
    instructions,
    showUserDrake,
    userChangeableGenes,
    visibleGenes,
    hiddenAlleles,
    baskets,
    gametes,
    drakes,
    trial,
    trials,
    numTrials,
    trialOrder,
    challenges,
    correct: 0,
    errors: 0,
    moves: 0,
    goalMoves,
    userDrakeHidden: true,
    trialSuccess: false,
    initialDrakes: [...drakes],
    zoomUrl,
    location,
    showingRoom,
    notifications: {
      messages,
      closeButton
    }
  };

  // remove all undefined or null keys
  Object.keys(authoredState).forEach((key) => (authoredState[key] == null) && delete authoredState[key]);

  return state.merge(authoredState);
}

export function loadHome(state, authoring, showMissionEndDialog) {
  let room = "home",
      roomInfo = (authoring && authoring.rooms) ? authoring.rooms[room] : {},
      location = {id: room, ...roomInfo},
      { level, mission, started } = AuthoringUtils.getCurrentMissionFromGems(authoring, state.gems),
      dialogDefs = authoring.application.levels[level].missions[mission].dialog,
      messages = [];

  if (dialogDefs) {
    let whichDialog = started ? "middle" : "start",
        dialog = dialogDefs[whichDialog];

    if (!started && showMissionEndDialog) {
      let previousMission = AuthoringUtils.getPreviousMission(authoring, level, mission);
      if (previousMission) {
        let endDialog = authoring.application.levels[previousMission.level].missions[previousMission.mission].dialog["end"] || [];
        dialog = endDialog.concat(dialog);
      }
    }

    messages = dialog.map( (d) => ({type: notificationType.DIALOG, ...d}));
  }

  let authoredState = {
    location,
    showingRoom: true,
    notifications: {
      messages,
      closeButton: false
    }
  };

  // remove all undefined or null keys
  Object.keys(authoredState).forEach((key) => (authoredState[key] == null) && delete authoredState[key]);

  return state.merge(authoredState);
}

export function loadNextTrial(state, authoring) {
  let trial = state.trial;
  if (state.trialSuccess){
    trial = (state.trial < state.numTrials) ? (trial+1) : 0;
  }
  let nextState = state.merge({
    trial: trial
  });

  return  loadStateFromAuthoring(nextState, authoring);
}
<|endoftext|>


<commit_before>module.exports = function(grunt) {
  'use strict';

  require('load-grunt-tasks')(grunt);
  require('google-closure-compiler').grunt(grunt);

  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    changelog: 'Changelog.md',

    'gh-release': {},

    'closure-compiler': {
      minify: {
        requiresConfig: 'git-revision',
        files: {
          '.tmp/build/axs_testing.js': [
              './lib/closure-library/closure/goog/base.js',
              './src/js/axs.js',
              './src/js/BrowserUtils.js',
              './src/js/Constants.js',
              './src/js/Color.js',
              './src/js/DOMUtils.js',
              './src/js/AccessibilityUtils.js',
              './src/js/Properties.js',
              './src/js/AuditRule.js',
              './src/js/AuditRules.js',
              './src/js/AuditResults.js',
              './src/js/Audit.js',
              './src/audits/*'
          ]
        },
        options: {
          'language_in': 'ECMASCRIPT5',
          'formatting': 'PRETTY_PRINT',
          'summary_detail_level': 3,
          'warning_level': 'VERBOSE',
          'compilation_level': 'SIMPLE_OPTIMIZATIONS',
          'output_wrapper': "<%= grunt.file.read('scripts/output_wrapper.txt') %>",
          'externs': './src/js/externs/externs.js'
        }
      }
    },

    qunit: {
      all: ['test/index.html']
    },

    copy: {
      dist: {
        expand: true,
        cwd: '.tmp/build',
        src: '**/*',
        dest: 'dist/js'
      }
    },

    clean: {
      local: ['.tmp'],
      dist: ['dist']
    },

    bump: {
      options: {
        prereleaseName: 'rc',
        files: ['package.json', 'bower.json'],
        updateConfigs: ['pkg'],
        pushTo: "<%= grunt.config.get('gh-release.remote') %>",
        commitFiles: ['package.json', "<%= grunt.config.get('changelog') %>", 'bower.json', 'dist']
      }
    },

    coffee: {
      compile: {
        files: {
          '.tmp/util/gh_repo.js': 'scripts/gh_repo.coffee'
        }
      }
    },

    eslint: {
        options: {
            configFile: '.eslintrc'
        },
        target: ['./src/js/', './src/audits/', './Gruntfile.js', './main.js']
    },

    prompt: {
      'gh-release': {
        options: {
          questions: [
            {
              config: 'gh-release.remote',
              type: 'input',
              message: 'Git Remote (usually upstream or origin)',
              default: 'upstream',
              validate: function(val) {
                return (grunt.util._.size(val) > 0);
              }
            },
            {
              config: 'gh-release.repo',
              type: 'input',
              message: 'Github Repository',
              default: 'GoogleChrome/accessibility-developer-tools',
              validate: function(val) {
                return (grunt.util._.size(val) > 0);
              }
            },
            {
              config: 'gh-release.username',
              type: 'input',
              message: 'Github Username',
              validate: function(val) {
                return (grunt.util._.size(val) > 0);
              }
            },
            {
              config: 'gh-release.password',
              type: 'password',
              message: 'Github Password or Token',
              validate: function(val) {
                return (grunt.util._.size(val) > 0);
              }
            }
          ]
        }
      }
    }
  });

  grunt.registerTask('changelog', function(type) {
    grunt.task.requires('bump-only:' + type);

    var dryRun = grunt.option('dry-run');
    var config = {
      data: {
        version: grunt.config.get('pkg.version'),
        releaseDate: grunt.template.today("yyyy-mm-dd")
      }
    };

    var stopRegex = /^\#\#\ [0-9]+.*$/m;
    var stopIndex = 0;
    var releaseNotes = '';
    var dest = grunt.config.get('changelog');
    var contents = grunt.file.read(dest);
    var headerTpl = "## <%= version %> - <%= releaseDate %>\n\n";
    var header = grunt.template.process(headerTpl, config);

    grunt.log.ok('changelog: Extracting release notes.');
    if (contents.length > 0) {
      if ((stopIndex = contents.search(stopRegex)) !== -1) {
        releaseNotes = contents.slice(0, stopIndex);
      }
    }

    grunt.config.set("gh-release.release-notes", releaseNotes);

    if (dryRun) {
      grunt.log.ok('changelog (dry): Prepending header to ' + dest);
      grunt.log.writeln(header);
    } else {
      grunt.file.write(dest, "" + header + contents);
    }

    grunt.log.writeln("Release Notes:\n" + releaseNotes);
    grunt.log.ok('changelog: Task completed.');
  });

  grunt.registerTask('gh-release', function() {
    // Compile and load GH Repo manager.
    grunt.task.requires('coffee:compile');
    var GHRepo = require('./.tmp/util/gh_repo');

    var dryRun = grunt.option('dry-run');
    var done = this.async();
    var config = grunt.config.get('gh-release');
    var pkg = grunt.config.get('pkg');
    var currentRelease = 'v' + pkg.version;
    var nextRelease = currentRelease.replace(/-rc\.[0-9]+/, '');
    var repo = new GHRepo(config);
    repo.log = function() { grunt.log.writeln.apply(grunt, arguments); };

    var payload = {
      tag_name: currentRelease,
      name: nextRelease,
      body: config['release-notes'],
      draft: true
    };

    grunt.log.writeln("gh-release: Searching for existing Github release:", nextRelease);
    repo.getReleaseByName(nextRelease)
      .then(function(release) {
        if (release) {
          if (dryRun) {
            grunt.log.ok('gh-release (dry): Updating existing Github release: ' + nextRelease);
            done();
          } else {
            payload.body += "\n" + release.body;
            repo.updateRelease(release, payload).then(function() {
              grunt.log.ok('Github release ' + nextRelease + ' updated successfully.');
              done();
            });
          }
        } else {
          if (dryRun) {
            grunt.log.ok('gh-release (dry): Creating new Github release: ' + nextRelease);
            done();
          } else {
            repo.createRelease(payload).then(function() {
              grunt.log.ok('Github release ' + nextRelease + ' created successfully');
              done();
            });
          }
        }
      })
      .catch(function(err) {
        throw err;
      });
  });

  grunt.registerTask('git-describe', function() {
    // Start async task
    var done = this.async();

    grunt.util.spawn({
      'cmd' : 'git',
      'args' : [ 'rev-parse', 'HEAD' ],
      'opts' : {
        'cwd' : '.'
      }
    }, function(err, result) {
      if (err) {
          grunt.log.error(err).verbose.error(result);
          done();
          return;
      }

      grunt.event.emit('git-describe', result.stdout);
      done();
    });
  });

  grunt.registerTask('release', function(releaseType) {
    if (typeof releaseType === 'undefined' || releaseType === null) {
      grunt.fail.fatal('You must specify a release type. i.e. grunt release:prerelease');
    }

    var dryRun = grunt.option('dry-run');

    var tasks = ['prompt:gh-release'];

    if (dryRun) {
      grunt.log.ok('Skipping build, clean:dist and copy:dist tasks in dry-run');
    } else {
      tasks.push('build', 'clean:dist', 'copy:dist');
    }

    tasks = tasks.concat([
      'test:unit',
      'bump-only:' + releaseType,
      'changelog:' + releaseType,
      'bump-commit',
      'coffee:compile',
      'gh-release'
    ]);

    grunt.task.run(tasks);
  });

  grunt.registerTask('save-revision', function() {
    grunt.event.once('git-describe', function (rev) {
      grunt.log.writeln('Git Revision: ' + rev);
      grunt.config.set('git-revision', rev);
    });
    grunt.task.run('git-describe');
  });

  grunt.registerTask('build', ['clean:local', 'save-revision', 'closure-compiler:minify']);
  grunt.registerTask('lint', ['eslint']);
  grunt.registerTask('test:unit', ['qunit']);
  grunt.registerTask('dist', ['clean:dist', 'build', 'copy:dist']);
  grunt.registerTask('travis', ['closurecompiler:minify', 'test:unit']);
  grunt.registerTask('default', ['build', 'test:unit']);
};
<commit_msg>Update travis config<commit_after>module.exports = function(grunt) {
  'use strict';

  require('load-grunt-tasks')(grunt);
  require('google-closure-compiler').grunt(grunt);

  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    changelog: 'Changelog.md',

    'gh-release': {},

    'closure-compiler': {
      minify: {
        requiresConfig: 'git-revision',
        files: {
          '.tmp/build/axs_testing.js': [
              './lib/closure-library/closure/goog/base.js',
              './src/js/axs.js',
              './src/js/BrowserUtils.js',
              './src/js/Constants.js',
              './src/js/Color.js',
              './src/js/DOMUtils.js',
              './src/js/AccessibilityUtils.js',
              './src/js/Properties.js',
              './src/js/AuditRule.js',
              './src/js/AuditRules.js',
              './src/js/AuditResults.js',
              './src/js/Audit.js',
              './src/audits/*'
          ]
        },
        options: {
          'language_in': 'ECMASCRIPT5',
          'formatting': 'PRETTY_PRINT',
          'summary_detail_level': 3,
          'warning_level': 'VERBOSE',
          'compilation_level': 'SIMPLE_OPTIMIZATIONS',
          'output_wrapper': "<%= grunt.file.read('scripts/output_wrapper.txt') %>",
          'externs': './src/js/externs/externs.js'
        }
      }
    },

    qunit: {
      all: ['test/index.html']
    },

    copy: {
      dist: {
        expand: true,
        cwd: '.tmp/build',
        src: '**/*',
        dest: 'dist/js'
      }
    },

    clean: {
      local: ['.tmp'],
      dist: ['dist']
    },

    bump: {
      options: {
        prereleaseName: 'rc',
        files: ['package.json', 'bower.json'],
        updateConfigs: ['pkg'],
        pushTo: "<%= grunt.config.get('gh-release.remote') %>",
        commitFiles: ['package.json', "<%= grunt.config.get('changelog') %>", 'bower.json', 'dist']
      }
    },

    coffee: {
      compile: {
        files: {
          '.tmp/util/gh_repo.js': 'scripts/gh_repo.coffee'
        }
      }
    },

    eslint: {
        options: {
            configFile: '.eslintrc'
        },
        target: ['./src/js/', './src/audits/', './Gruntfile.js', './main.js']
    },

    prompt: {
      'gh-release': {
        options: {
          questions: [
            {
              config: 'gh-release.remote',
              type: 'input',
              message: 'Git Remote (usually upstream or origin)',
              default: 'upstream',
              validate: function(val) {
                return (grunt.util._.size(val) > 0);
              }
            },
            {
              config: 'gh-release.repo',
              type: 'input',
              message: 'Github Repository',
              default: 'GoogleChrome/accessibility-developer-tools',
              validate: function(val) {
                return (grunt.util._.size(val) > 0);
              }
            },
            {
              config: 'gh-release.username',
              type: 'input',
              message: 'Github Username',
              validate: function(val) {
                return (grunt.util._.size(val) > 0);
              }
            },
            {
              config: 'gh-release.password',
              type: 'password',
              message: 'Github Password or Token',
              validate: function(val) {
                return (grunt.util._.size(val) > 0);
              }
            }
          ]
        }
      }
    }
  });

  grunt.registerTask('changelog', function(type) {
    grunt.task.requires('bump-only:' + type);

    var dryRun = grunt.option('dry-run');
    var config = {
      data: {
        version: grunt.config.get('pkg.version'),
        releaseDate: grunt.template.today("yyyy-mm-dd")
      }
    };

    var stopRegex = /^\#\#\ [0-9]+.*$/m;
    var stopIndex = 0;
    var releaseNotes = '';
    var dest = grunt.config.get('changelog');
    var contents = grunt.file.read(dest);
    var headerTpl = "## <%= version %> - <%= releaseDate %>\n\n";
    var header = grunt.template.process(headerTpl, config);

    grunt.log.ok('changelog: Extracting release notes.');
    if (contents.length > 0) {
      if ((stopIndex = contents.search(stopRegex)) !== -1) {
        releaseNotes = contents.slice(0, stopIndex);
      }
    }

    grunt.config.set("gh-release.release-notes", releaseNotes);

    if (dryRun) {
      grunt.log.ok('changelog (dry): Prepending header to ' + dest);
      grunt.log.writeln(header);
    } else {
      grunt.file.write(dest, "" + header + contents);
    }

    grunt.log.writeln("Release Notes:\n" + releaseNotes);
    grunt.log.ok('changelog: Task completed.');
  });

  grunt.registerTask('gh-release', function() {
    // Compile and load GH Repo manager.
    grunt.task.requires('coffee:compile');
    var GHRepo = require('./.tmp/util/gh_repo');

    var dryRun = grunt.option('dry-run');
    var done = this.async();
    var config = grunt.config.get('gh-release');
    var pkg = grunt.config.get('pkg');
    var currentRelease = 'v' + pkg.version;
    var nextRelease = currentRelease.replace(/-rc\.[0-9]+/, '');
    var repo = new GHRepo(config);
    repo.log = function() { grunt.log.writeln.apply(grunt, arguments); };

    var payload = {
      tag_name: currentRelease,
      name: nextRelease,
      body: config['release-notes'],
      draft: true
    };

    grunt.log.writeln("gh-release: Searching for existing Github release:", nextRelease);
    repo.getReleaseByName(nextRelease)
      .then(function(release) {
        if (release) {
          if (dryRun) {
            grunt.log.ok('gh-release (dry): Updating existing Github release: ' + nextRelease);
            done();
          } else {
            payload.body += "\n" + release.body;
            repo.updateRelease(release, payload).then(function() {
              grunt.log.ok('Github release ' + nextRelease + ' updated successfully.');
              done();
            });
          }
        } else {
          if (dryRun) {
            grunt.log.ok('gh-release (dry): Creating new Github release: ' + nextRelease);
            done();
          } else {
            repo.createRelease(payload).then(function() {
              grunt.log.ok('Github release ' + nextRelease + ' created successfully');
              done();
            });
          }
        }
      })
      .catch(function(err) {
        throw err;
      });
  });

  grunt.registerTask('git-describe', function() {
    // Start async task
    var done = this.async();

    grunt.util.spawn({
      'cmd' : 'git',
      'args' : [ 'rev-parse', 'HEAD' ],
      'opts' : {
        'cwd' : '.'
      }
    }, function(err, result) {
      if (err) {
          grunt.log.error(err).verbose.error(result);
          done();
          return;
      }

      grunt.event.emit('git-describe', result.stdout);
      done();
    });
  });

  grunt.registerTask('release', function(releaseType) {
    if (typeof releaseType === 'undefined' || releaseType === null) {
      grunt.fail.fatal('You must specify a release type. i.e. grunt release:prerelease');
    }

    var dryRun = grunt.option('dry-run');

    var tasks = ['prompt:gh-release'];

    if (dryRun) {
      grunt.log.ok('Skipping build, clean:dist and copy:dist tasks in dry-run');
    } else {
      tasks.push('build', 'clean:dist', 'copy:dist');
    }

    tasks = tasks.concat([
      'test:unit',
      'bump-only:' + releaseType,
      'changelog:' + releaseType,
      'bump-commit',
      'coffee:compile',
      'gh-release'
    ]);

    grunt.task.run(tasks);
  });

  grunt.registerTask('save-revision', function() {
    grunt.event.once('git-describe', function (rev) {
      grunt.log.writeln('Git Revision: ' + rev);
      grunt.config.set('git-revision', rev);
    });
    grunt.task.run('git-describe');
  });

  grunt.registerTask('build', ['clean:local', 'save-revision', 'closure-compiler:minify']);
  grunt.registerTask('lint', ['eslint']);
  grunt.registerTask('test:unit', ['qunit']);
  grunt.registerTask('dist', ['clean:dist', 'build', 'copy:dist']);
  grunt.registerTask('travis', ['closure-compiler:minify', 'test:unit']);
  grunt.registerTask('default', ['build', 'test:unit']);
};
<|endoftext|>


<commit_before>module.exports = function(grunt) {
    grunt.initConfig({
        qunit: {
            files: ['test/tests.html']
        }
    });
    grunt.registerTask('test', 'qunit');
};

<commit_msg>maybe this'll do it?<commit_after>module.exports = function(grunt) {
    grunt.initConfig({
        qunit: {
            files: ['test/tests.html']
        }
    });
    grunt.registerTask('test', 'qunit');
    grunt.loadNpmTasks('grunt-contrib-qunit');
};

<|endoftext|>


<commit_before>/* jshint node:true, laxbreak: true */
'use strict';

module.exports = function(grunt) {
    ///////////////////////////////////////////////////////////////////////////
    // Required Modules
    ///////////////////////////////////////////////////////////////////////////

    require('load-grunt-tasks')(grunt);
    require('nopt-grunt')(grunt);

    /**
     * Any modules needed before setting up Grunt should be included here.
     */

    ///////////////////////////////////////////////////////////////////////////
    // Grunt Options
    ///////////////////////////////////////////////////////////////////////////

    grunt.initOptions({
        prod: {
            info: 'Production build in progress',
            type: Boolean
        },

        dev: {
            info: 'Development build in progress',
            type: Boolean
        }
    });

    // Ensure we in dev mod by default.
    grunt.option('dev', !grunt.option('prod'));

    ///////////////////////////////////////////////////////////////////////////
    // Grunt Configuration
    ///////////////////////////////////////////////////////////////////////////

    grunt.initConfig({
        ///////////////////////////////////////////////////////////////////////
        // CONFIG VARIABLES
        ///////////////////////////////////////////////////////////////////////

        /**
         * Load up our package.json file so we can use the variables
         * we we build out the messages and banners.
         */
        pkg: require('./package.json'),

        /**
         * Our build configuration.
         */
        buildConfig: require('./build-config'),

        ///////////////////////////////////////////////////////////////////////
        // STARTUP TASKS
        ///////////////////////////////////////////////////////////////////////

        /**
         * Cleans out all of the directories that were generated during
         * the Grunt build process. This will keep each build fresh!
         */
        clean: {
            options: {
                force: true
            },
            dest: ['<%= buildConfig.DIR_DEST %>'],
            tmp: ['<%= buildConfig.DIR_TMP %>']
        },

        /**
         * Copies files into our destination folder defined in the
         * BuildConfig class.
         */
        copy: {
            css: {
                files: [{
                    expand: true,
                    cwd: '<%= buildConfig.DIR_SRC %>',
                    dest: '<%= buildConfig.DIR_DEST %>',
                    src: ['assets/{css,vendors}/**/*.css']
                }]
            },

            markup: {
                files: [{
                    expand: true,
                    cwd: '<%= buildConfig.DIR_SRC %>',
                    dest: '<%= buildConfig.DIR_DEST %>',
                    src: ['**/*.html', '!assets/vendors/**']
                }]
            },

            media: {
                files: [{
                    expand: true,
                    cwd: '<%= buildConfig.DIR_SRC %>',
                    dest: '<%= buildConfig.DIR_DEST %>',
                    src: ['assets/media/**']
                }]
            },

            scripts: {
                files: [{
                    expand: true,
                    cwd: '<%= buildConfig.DIR_SRC %>',
                    dest: '<%= buildConfig.DIR_DEST %>',
                    src: [
                        'assets/scripts/**/*.js',
                        'assets/vendors/**/*.js'
                    ]
                }]
            }
        },

        ///////////////////////////////////////////////////////////////////////
        // OPTIMIZE TASKS
        ///////////////////////////////////////////////////////////////////////

        /**
         * Handles configuring the RequireJS build to optimize and minify
         * the application javascript files.
         */
        requirejs: {
            options: {
                baseUrl: '<%= buildConfig.DIR_SRC %>/assets/scripts',
                useStrict: true,
                optimize: grunt.option('dev') ? 'none' : 'uglify2',
                uglify2: {
                    output: {
                        beautify: false,
                        comments: false
                    },
                    compress: {
                        sequences: false
                    },
                    warnings: false,
                    mangle: true
                }
            },
            main: {
                options: {
                    mainConfigFile: '<%= buildConfig.DIR_SRC %>/assets/scripts/config.js',
                    name: 'main',
                    out: '<%= buildConfig.DIR_DEST %>/assets/scripts/main.js'
                }
            }
        },

        ///////////////////////////////////////////////////////////////////////
        // STYLE TASKS
        ///////////////////////////////////////////////////////////////////////

        sass: {
            compile: {
                options: {
                    style: 'expanded'
                },
                files: [{
                    expand: true,
                    cwd: '<%= buildConfig.DIR_SRC %>/assets/scss',
                    src: ['*.scss'],
                    dest: '<%= buildConfig.DIR_TMP %>/assets/css',
                    ext: '.css'
                }]
            }
        },

        cssmin: {
            all: {
                files: [{
                    expand: true,
                    cwd: '<%= buildConfig.DIR_TMP %>/assets/css',
                    src: ['*.css'],
                    dest: '<%= buildConfig.DIR_DEST %>/assets/css',
                    ext: '.min.css'
                }]
            }
        },

        ///////////////////////////////////////////////////////////////////////
        // LINTING TASKS
        ///////////////////////////////////////////////////////////////////////

        csslint: {
            options: {
                csslintrc: '.csslintrc'
            },
            all: {
                src: [
                    '<%= buildConfig.DIR_TMP %>/css/**/*.css'
                ]
            }
        },

        jshint: {
            options: {
                jshintrc: '.jshintrc',
                force: true
            },
            all: {
                src: [
                    'Gruntfile.js',
                    '<%= env.DIR_SRC %>/scripts/**/*.js'
                ]
            }
        },

        ///////////////////////////////////////////////////////////////////////
        // HELPER TASKS
        ///////////////////////////////////////////////////////////////////////

        /**
         * The grunt-banner allows us to place a banner on generated files
         */
        usebanner: {
            options: {
                position: 'top',
                linebreak: true
            },

            css: {
                options: {
                    banner: '/*\n<%= buildConfig.FILE_BANNER %> */\n'
                },
                files: {
                    src: ['<%= buildConfig.DIR_DEST %>/assets/css/**/*.css']
                }
            },

            markup: {
                options: {
                    banner: '<!--\n <%= buildConfig.FILE_BANNER %>\n -->\n'
                },
                files: {
                    src: ['<%= buildConfig.DIR_DEST %>/**/*.html']
                }
            },

            scripts: {
                options: {
                    banner: '/*\n<%= buildConfig.FILE_BANNER %> */\n'
                },
                files: {
                    src: ['<%= buildConfig.DIR_DEST %>/assets/scripts/**/*.js']
                }
            }
        },

        /**
         * This task allows us to run grunt watch and have our files
         * compiled upon changes.
         */
        watch: {
            options: {
                event: 'all'
            },
            grunt: {
                files: ['Gruntfile.js'],
                tasks: ['build', 'notify:build']
            },
            media: {
                files: ['<%= buildConfig.DIR_SRC %>/assets/media/**'],
                tasks: ['media', 'clean:tmp', 'notify:media']
            },
            css: {
                files: ['<%= buildConfig.DIR_SRC %>/assets/{scss,vendors}/**/*.scss'],
                tasks: ['css', 'clean:tmp', 'notify:css']
            },
            scripts: {
                files: ['<%= buildConfig.DIR_SRC %>/assets/{scripts,vendors}/**/*.js'],
                tasks: ['scripts', 'clean:tmp', 'notify:scripts']
            },
            markup: {
                files: ['<%= buildConfig.DIR_SRC %>/**/*.html'],
                tasks: ['markup', 'clean:tmp', 'notify:markup']
            }
        },

        /**
         * Notify messages when in the grunt watch mode so that we can
         * know when the build process has been executed.
         */
        notify: {
            build: {
                options: {
                    title: 'Grunt Build Complete',
                    message: 'Build Tasks Finished'
                }
            },
            media: {
                options: {
                    title: 'Grunt Build Complete',
                    message: 'Media Tasks Finished'
                }
            },
            css: {
                options: {
                    title: 'Grunt Build Complete',
                    message: 'CSS Tasks Finished'
                }
            },
            scripts: {
                options: {
                    title: 'Grunt Build Complete',
                    message: 'Scripts Tasks Finished'
                }
            },
            markup: {
                options: {
                    title: 'Grunt Build Complete',
                    message: 'Markup Tasks Finished'
                }
            }
        }
    });

    ///////////////////////////////////////////////////////////////////////////
    // REGISTER TASKS
    ///////////////////////////////////////////////////////////////////////////

    /**
     * Define our default task based upon our environment.
     */
    if (grunt.option('prod')) {
        grunt.registerTask('default', ['build', 'lint']);
    } else {
        grunt.registerTask('default', ['build']);
    }

    /**
     * Custom tasks.
     */
    grunt.registerTask('build', ['clean:dest', 'media', 'markup', 'css', 'scripts', 'clean:tmp']);
    grunt.registerTask('lint', ['csslint', 'jshint']);
    grunt.registerTask('media', ['copy:media']);
    grunt.registerTask('markup', ['copy:markup']);

    if (grunt.option('prod')) {
        grunt.registerTask('css', ['sass', 'cssmin', 'usebanner:css']);
        grunt.registerTask('scripts', ['requirejs:main', 'copy:scripts', 'userbanner:scripts']);
    } else {
        grunt.registerTask('css', ['sass', 'cssmin', 'usebanner:css']);
        grunt.registerTask('scripts', ['copy:scripts', 'usebanner:scripts']);
    }
};
<commit_msg>Updated requirejs output file name<commit_after>/* jshint node:true, laxbreak: true */
'use strict';

module.exports = function(grunt) {
    ///////////////////////////////////////////////////////////////////////////
    // Required Modules
    ///////////////////////////////////////////////////////////////////////////

    require('load-grunt-tasks')(grunt);
    require('nopt-grunt')(grunt);

    /**
     * Any modules needed before setting up Grunt should be included here.
     */

    ///////////////////////////////////////////////////////////////////////////
    // Grunt Options
    ///////////////////////////////////////////////////////////////////////////

    grunt.initOptions({
        prod: {
            info: 'Production build in progress',
            type: Boolean
        },

        dev: {
            info: 'Development build in progress',
            type: Boolean
        }
    });

    // Ensure we in dev mod by default.
    grunt.option('dev', !grunt.option('prod'));

    ///////////////////////////////////////////////////////////////////////////
    // Grunt Configuration
    ///////////////////////////////////////////////////////////////////////////

    grunt.initConfig({
        ///////////////////////////////////////////////////////////////////////
        // CONFIG VARIABLES
        ///////////////////////////////////////////////////////////////////////

        /**
         * Load up our package.json file so we can use the variables
         * we we build out the messages and banners.
         */
        pkg: require('./package.json'),

        /**
         * Our build configuration.
         */
        buildConfig: require('./build-config'),

        ///////////////////////////////////////////////////////////////////////
        // STARTUP TASKS
        ///////////////////////////////////////////////////////////////////////

        /**
         * Cleans out all of the directories that were generated during
         * the Grunt build process. This will keep each build fresh!
         */
        clean: {
            options: {
                force: true
            },
            dest: ['<%= buildConfig.DIR_DEST %>'],
            tmp: ['<%= buildConfig.DIR_TMP %>']
        },

        /**
         * Copies files into our destination folder defined in the
         * BuildConfig class.
         */
        copy: {
            css: {
                files: [{
                    expand: true,
                    cwd: '<%= buildConfig.DIR_SRC %>',
                    dest: '<%= buildConfig.DIR_DEST %>',
                    src: ['assets/{css,vendors}/**/*.css']
                }]
            },

            markup: {
                files: [{
                    expand: true,
                    cwd: '<%= buildConfig.DIR_SRC %>',
                    dest: '<%= buildConfig.DIR_DEST %>',
                    src: ['**/*.html', '!assets/vendors/**']
                }]
            },

            media: {
                files: [{
                    expand: true,
                    cwd: '<%= buildConfig.DIR_SRC %>',
                    dest: '<%= buildConfig.DIR_DEST %>',
                    src: ['assets/media/**']
                }]
            },

            scripts: {
                files: [{
                    expand: true,
                    cwd: '<%= buildConfig.DIR_SRC %>',
                    dest: '<%= buildConfig.DIR_DEST %>',
                    src: [
                        'assets/scripts/**/*.js',
                        'assets/vendors/**/*.js'
                    ]
                }]
            }
        },

        ///////////////////////////////////////////////////////////////////////
        // OPTIMIZE TASKS
        ///////////////////////////////////////////////////////////////////////

        /**
         * Handles configuring the RequireJS build to optimize and minify
         * the application javascript files.
         */
        requirejs: {
            options: {
                baseUrl: '<%= buildConfig.DIR_SRC %>/assets/scripts',
                useStrict: true,
                optimize: grunt.option('dev') ? 'none' : 'uglify2',
                uglify2: {
                    output: {
                        beautify: false,
                        comments: false
                    },
                    compress: {
                        sequences: false
                    },
                    warnings: false,
                    mangle: true
                }
            },
            main: {
                options: {
                    mainConfigFile: '<%= buildConfig.DIR_SRC %>/assets/scripts/config.js',
                    name: 'main',
                    out: '<%= buildConfig.DIR_DEST %>/assets/scripts/main.min.js'
                }
            }
        },

        ///////////////////////////////////////////////////////////////////////
        // STYLE TASKS
        ///////////////////////////////////////////////////////////////////////

        sass: {
            compile: {
                options: {
                    style: 'expanded'
                },
                files: [{
                    expand: true,
                    cwd: '<%= buildConfig.DIR_SRC %>/assets/scss',
                    src: ['*.scss'],
                    dest: '<%= buildConfig.DIR_TMP %>/assets/css',
                    ext: '.css'
                }]
            }
        },

        cssmin: {
            all: {
                files: [{
                    expand: true,
                    cwd: '<%= buildConfig.DIR_TMP %>/assets/css',
                    src: ['*.css'],
                    dest: '<%= buildConfig.DIR_DEST %>/assets/css',
                    ext: '.min.css'
                }]
            }
        },

        ///////////////////////////////////////////////////////////////////////
        // LINTING TASKS
        ///////////////////////////////////////////////////////////////////////

        csslint: {
            options: {
                csslintrc: '.csslintrc'
            },
            all: {
                src: [
                    '<%= buildConfig.DIR_TMP %>/css/**/*.css'
                ]
            }
        },

        jshint: {
            options: {
                jshintrc: '.jshintrc',
                force: true
            },
            all: {
                src: [
                    'Gruntfile.js',
                    '<%= env.DIR_SRC %>/scripts/**/*.js'
                ]
            }
        },

        ///////////////////////////////////////////////////////////////////////
        // HELPER TASKS
        ///////////////////////////////////////////////////////////////////////

        /**
         * The grunt-banner allows us to place a banner on generated files
         */
        usebanner: {
            options: {
                position: 'top',
                linebreak: true
            },

            css: {
                options: {
                    banner: '/*\n<%= buildConfig.FILE_BANNER %> */\n'
                },
                files: {
                    src: ['<%= buildConfig.DIR_DEST %>/assets/css/**/*.css']
                }
            },

            markup: {
                options: {
                    banner: '<!--\n <%= buildConfig.FILE_BANNER %>\n -->\n'
                },
                files: {
                    src: ['<%= buildConfig.DIR_DEST %>/**/*.html']
                }
            },

            scripts: {
                options: {
                    banner: '/*\n<%= buildConfig.FILE_BANNER %> */\n'
                },
                files: {
                    src: ['<%= buildConfig.DIR_DEST %>/assets/scripts/**/*.js']
                }
            }
        },

        /**
         * This task allows us to run grunt watch and have our files
         * compiled upon changes.
         */
        watch: {
            options: {
                event: 'all'
            },
            grunt: {
                files: ['Gruntfile.js'],
                tasks: ['build', 'notify:build']
            },
            media: {
                files: ['<%= buildConfig.DIR_SRC %>/assets/media/**'],
                tasks: ['media', 'clean:tmp', 'notify:media']
            },
            css: {
                files: ['<%= buildConfig.DIR_SRC %>/assets/{scss,vendors}/**/*.scss'],
                tasks: ['css', 'clean:tmp', 'notify:css']
            },
            scripts: {
                files: ['<%= buildConfig.DIR_SRC %>/assets/{scripts,vendors}/**/*.js'],
                tasks: ['scripts', 'clean:tmp', 'notify:scripts']
            },
            markup: {
                files: ['<%= buildConfig.DIR_SRC %>/**/*.html'],
                tasks: ['markup', 'clean:tmp', 'notify:markup']
            }
        },

        /**
         * Notify messages when in the grunt watch mode so that we can
         * know when the build process has been executed.
         */
        notify: {
            build: {
                options: {
                    title: 'Grunt Build Complete',
                    message: 'Build Tasks Finished'
                }
            },
            media: {
                options: {
                    title: 'Grunt Build Complete',
                    message: 'Media Tasks Finished'
                }
            },
            css: {
                options: {
                    title: 'Grunt Build Complete',
                    message: 'CSS Tasks Finished'
                }
            },
            scripts: {
                options: {
                    title: 'Grunt Build Complete',
                    message: 'Scripts Tasks Finished'
                }
            },
            markup: {
                options: {
                    title: 'Grunt Build Complete',
                    message: 'Markup Tasks Finished'
                }
            }
        }
    });

    ///////////////////////////////////////////////////////////////////////////
    // REGISTER TASKS
    ///////////////////////////////////////////////////////////////////////////

    /**
     * Define our default task based upon our environment.
     */
    if (grunt.option('prod')) {
        grunt.registerTask('default', ['build', 'lint']);
    } else {
        grunt.registerTask('default', ['build']);
    }

    /**
     * Custom tasks.
     */
    grunt.registerTask('build', ['clean:dest', 'media', 'markup', 'css', 'scripts', 'clean:tmp']);
    grunt.registerTask('lint', ['csslint', 'jshint']);
    grunt.registerTask('media', ['copy:media']);
    grunt.registerTask('markup', ['copy:markup']);

    if (grunt.option('prod')) {
        grunt.registerTask('css', ['sass', 'cssmin', 'usebanner:css']);
        grunt.registerTask('scripts', ['copy:scripts', 'requirejs:main', 'usebanner:scripts']);
    } else {
        grunt.registerTask('css', ['sass', 'cssmin', 'usebanner:css']);
        grunt.registerTask('scripts', ['copy:scripts', 'usebanner:scripts']);
    }
};
<|endoftext|>


<commit_before>// ==UserScript==
// @name         Asana Links in Bitbucket
// @namespace    https://github.com/GetintheLoop/asana-highlighter/
// @version      0.3
// @description  Use Asana Task Id and render as links in Bitbucket
// @author       Lukas Siemon
// @match        https://bitbucket.org/*
// @grant        none
// @updateURL    https://raw.githubusercontent.com/GetintheLoop/asana-highlighter/master/scripts/asana-in-bitbucket.js
// ==/UserScript==

(function() {
    'use strict';
    setInterval(function() {
        if (!document.hidden) {
            let desc = $(".pull-request-title h1");
            if (desc.length === 1) {
                if (desc[0].innerText.indexOf('#') !== -1) {
                    desc[0].innerHTML = desc[0].innerText.replace(
                        /#(\d{10,})/g,
                        '' +
                        '' +
                        ''
                    );
                }
            }
        }
    }, 1000);
})();
<commit_msg>Update asana-in-bitbucket.js<commit_after>// ==UserScript==
// @name         Asana Links in Bitbucket
// @namespace    https://github.com/GetintheLoop/asana-highlighter/
// @version      0.4
// @description  Use Asana Task Id and render as links in Bitbucket
// @author       Lukas Siemon
// @match        https://bitbucket.org/*
// @grant        none
// @updateURL    https://raw.githubusercontent.com/GetintheLoop/asana-highlighter/master/scripts/asana-in-bitbucket.js
// ==/UserScript==

(function() {
    'use strict';
    setInterval(function() {
        if (!document.hidden) {
            let desc = $(".pull-request-title h1");
            if (desc.length === 1) {
                if (desc[0].innerText.indexOf('#') !== -1) {
                    desc[0].innerHTML = desc[0].innerText.replace(
                        /#(\d{10,})/g,
                        '' +
                        '' +
                        ''
                    );
                }
            }
        }
    }, 1000);
})();
<|endoftext|>


<commit_before>'use strict';

var assert = require('chai').assert;
var hock = require('hock');
var uuid = require('node-uuid').v4;
var Trader = require('../../lib/trader.js');
var PostgresqlInterface = require('../../lib/postgresql_interface.js');

var db = 'psql://lamassu:lamassu@localhost/lamassu-test';
var psqlInterface = new PostgresqlInterface(db);

var TRANSACTION_FEE = 1;
var FINGERPRINT = 'CB:3D:78:49:03:39:BA:47:0A:33:29:3E:31:25:F7:C6:4F:74:71:D7';
var TXID = '216dabdb692670bae940deb71e59486038a575f637903d3c9af601ddd48057fc';
var ADDRESS = '1LhkU2R8nJaU8Zj6jB8VjWrMpvVKGqCZ64';
var SATOSHIS = 1337;
var CURRENCY = 'USD';

var OUR_TXID = uuid();

describe('trader/send', function () {
  var trader = new Trader(psqlInterface);
  trader.config = {
    exchanges: {
      settings: {
        transactionFee: TRANSACTION_FEE
      }
    }
  };

  trader.pollRate = function () {};

  it('should call `sendBitcoins` on the transfer exchange', function (done) {
    trader.transferExchange = {
      sendBitcoins: function (address, satoshis, transactionFee, callback) {
        assert.equal(ADDRESS, address);
        assert.equal(SATOSHIS, satoshis);
        assert.equal(transactionFee, TRANSACTION_FEE);
        callback(null, TXID);
      }
    };

    trader.sendBitcoins(FINGERPRINT, {
      fiat: 100,
      txId: OUR_TXID,
      currencyCode: CURRENCY,
      toAddress: ADDRESS,
      satoshis: SATOSHIS
    }, function (err, txId) {
      assert.notOk(err);
      assert.equal(txId, TXID);
      done();
    });
  });

  it('should not call `sendBitcoins` on the transfer exchange with same send', function (done) {
    trader.transferExchange = {
      sendBitcoins: function () {
        throw new Error('This should not have been called');
      }
    };

    trader.sendBitcoins(FINGERPRINT, {
      fiat: 100,
      txId: OUR_TXID,
      currencyCode: CURRENCY,
      toAddress: ADDRESS,
      satoshis: SATOSHIS
    }, function (err, txId) {
      assert.notOk(err);
      assert.equal(txId, TXID);
      done();
    });
  });
});
<commit_msg>fixed a test<commit_after>'use strict';

var assert = require('chai').assert;
var hock = require('hock');
var uuid = require('node-uuid').v4;
var Trader = require('../../lib/trader.js');
var PostgresqlInterface = require('../../lib/postgresql_interface.js');

var db = 'psql://lamassu:lamassu@localhost/lamassu-test';
var psqlInterface = new PostgresqlInterface(db);

var TRANSACTION_FEE = 1;
var FINGERPRINT = 'CB:3D:78:49:03:39:BA:47:0A:33:29:3E:31:25:F7:C6:4F:74:71:D7';
var TXID = '216dabdb692670bae940deb71e59486038a575f637903d3c9af601ddd48057fc';
var ADDRESS = '1LhkU2R8nJaU8Zj6jB8VjWrMpvVKGqCZ64';
var SATOSHIS = 1337;
var CURRENCY = 'USD';

var OUR_TXID = uuid();

describe('trader/send', function () {
  var trader = new Trader(psqlInterface);
  trader.config = {
    exchanges: {
      settings: {
        transactionFee: TRANSACTION_FEE
      }
    }
  };

  trader.pollRate = function () {};

  it('should call `sendBitcoins` on the transfer exchange', function (done) {
    trader.transferExchange = {
      sendBitcoins: function (address, satoshis, transactionFee, callback) {
        assert.equal(ADDRESS, address);
        assert.equal(SATOSHIS, satoshis);
        assert.equal(transactionFee, TRANSACTION_FEE);
        callback(null, TXID);
      },
      balance: function () {}
    };

    trader.sendBitcoins(FINGERPRINT, {
      fiat: 100,
      txId: OUR_TXID,
      currencyCode: CURRENCY,
      toAddress: ADDRESS,
      satoshis: SATOSHIS
    }, function (err, txId) {
      assert.notOk(err);
      assert.equal(txId, TXID);
      done();
    });
  });

  it('should not call `sendBitcoins` on the transfer exchange with same send', function (done) {
    trader.transferExchange = {
      sendBitcoins: function () {
        throw new Error('This should not have been called');
      },
      balance: function () {}
    };

    trader.sendBitcoins(FINGERPRINT, {
      fiat: 100,
      txId: OUR_TXID,
      currencyCode: CURRENCY,
      toAddress: ADDRESS,
      satoshis: SATOSHIS
    }, function (err, txId) {
      assert.notOk(err);
      assert.equal(txId, TXID);
      done();
    });
  });
});
<|endoftext|>