<commit_before>describe("About Objects", function() {

  describe("Properties", function() {
    var meglomaniac;

    beforeEach(function() {
       meglomaniac = {  mastermind: "Joker", henchwoman: "Harley" };
    });

    it("should confirm objects are collections of properties", function() {
      expect(meglomaniac.mastermind).toBe(FILL_ME_IN);
    });

    it("should confirm that properties are case sensitive", function() {
      expect(meglomaniac.henchwoman).toBe(FILL_ME_IN);
      expect(meglomaniac.henchWoman).toBe(FILL_ME_IN);
    });
  });

  it("should know properties that are functions act like methods", function() {
    var meglomaniac = {
      mastermind : "Brain",
      henchman: "Pinky",
      battleCry: function(noOfBrains) {
        return "They are " + this.henchman + " and the" +
          Array(noOfBrains + 1).join(" " + this.mastermind);
      }
    };

    var battleCry = meglomaniac.battleCry(4);
    expect(FILL_ME_IN).toMatch(battleCry);
  });

  it("should confirm that when a function is attached to an object, 'this' refers to the object", function () {
    var currentDate = new Date();
    var currentYear = (currentDate.getFullYear());
    var meglomaniac = {
      mastermind: "James Wood",
      henchman: "Adam West",
      birthYear: 1970,
      calculateAge: function() {
        return currentYear - this.birthYear;
      }
    };

    expect(currentYear).toBe(FILL_ME_IN);
    expect(meglomaniac.calculateAge()).toBe(FILL_ME_IN);
  });

  describe("'in' keyword", function() {
    var meglomaniac;
    beforeEach(function() {
      meglomaniac = {
        mastermind: "The Monarch",
        henchwoman: "Dr Girlfriend",
        theBomb: true
      };
    });

    it("should have the bomb", function() {
      var hasBomb = "theBomb" in meglomaniac;

      expect(hasBomb).toBe(FILL_ME_IN);
    });

    it("should not have the detonator however", function() {
      var hasDetonator = "theDetonator" in meglomaniac;

      expect(hasDetonator).toBe(FILL_ME_IN);
    });
  });

  it("should know that properties can be added and deleted", function() {
    var meglomaniac = { mastermind : "Agent Smith", henchman: "Agent Smith" };

    expect("secretary" in meglomaniac).toBe(FILL_ME_IN);

    meglomaniac.secretary = "Agent Smith";
    expect("secretary" in meglomaniac).toBe(FILL_ME_IN);

    delete meglomaniac.henchman;
    expect("henchman" in meglomaniac).toBe(FILL_ME_IN);
  });

  it("should use prototype to add to all objects", function() {
    function Circle(radius)
    {
      this.radius = radius;
    }

    var simpleCircle = new Circle(10);
    var colouredCircle = new Circle(5);
    colouredCircle.colour = "red";

    expect(simpleCircle.colour).toBe(FILL_ME_IN);
    expect(colouredCircle.colour).toBe(FILL_ME_IN);

    Circle.prototype.describe = function() {
      return "This circle has a radius of: " + this.radius;
    };

    expect(simpleCircle.describe()).toBe(FILL_ME_IN);
    expect(colouredCircle.describe()).toBe(FILL_ME_IN);
  });
});
<commit_msg>Completed AboutObjects<commit_after>describe("About Objects", function() {

  describe("Properties", function() {
    var meglomaniac;

    beforeEach(function() {
       meglomaniac = {  mastermind: "Joker", henchwoman: "Harley" };
    });

    it("should confirm objects are collections of properties", function() {
      expect(meglomaniac.mastermind).toBe("Joker");
    });

    it("should confirm that properties are case sensitive", function() {
      expect(meglomaniac.henchwoman).toBe("Harley");
      expect(meglomaniac.henchWoman).toBe(undefined);
    });
  });

  it("should know properties that are functions act like methods", function() {
    var meglomaniac = {
      mastermind : "Brain",
      henchman: "Pinky",
      battleCry: function(noOfBrains) {
        return "They are " + this.henchman + " and the" +
          Array(noOfBrains + 1).join(" " + this.mastermind);
      }
    };

    var battleCry = meglomaniac.battleCry(4);
    expect("They are Pinky and the Brain Brain Brain Brain").toMatch(battleCry);
  });

  it("should confirm that when a function is attached to an object, 'this' refers to the object", function () {
    var currentDate = new Date();
    var currentYear = (currentDate.getFullYear());
    var meglomaniac = {
      mastermind: "James Wood",
      henchman: "Adam West",
      birthYear: 1970,
      calculateAge: function() {
        return currentYear - this.birthYear;
      }
    };

    expect(currentYear).toBe(2015);
    expect(meglomaniac.calculateAge()).toBe(45);
  });

  describe("'in' keyword", function() {
    var meglomaniac;
    beforeEach(function() {
      meglomaniac = {
        mastermind: "The Monarch",
        henchwoman: "Dr Girlfriend",
        theBomb: true
      };
    });

    it("should have the bomb", function() {
      var hasBomb = "theBomb" in meglomaniac;

      expect(hasBomb).toBe(true);
    });

    it("should not have the detonator however", function() {
      var hasDetonator = "theDetonator" in meglomaniac;

      expect(hasDetonator).toBe(false);
    });
  });

  it("should know that properties can be added and deleted", function() {
    var meglomaniac = { mastermind : "Agent Smith", henchman: "Agent Smith" };

    expect("secretary" in meglomaniac).toBe(false);

    meglomaniac.secretary = "Agent Smith";
    expect("secretary" in meglomaniac).toBe(true);

    delete meglomaniac.henchman;
    expect("henchman" in meglomaniac).toBe(false);
  });

  it("should use prototype to add to all objects", function() {
    function Circle(radius)
    {
      this.radius = radius;
    }

    var simpleCircle = new Circle(10);
    var colouredCircle = new Circle(5);
    colouredCircle.colour = "red";

    expect(simpleCircle.colour).toBe(undefined);
    expect(colouredCircle.colour).toBe("red");

    Circle.prototype.describe = function() {
      return "This circle has a radius of: " + this.radius;
    };

    expect(simpleCircle.describe()).toBe("This circle has a radius of: 10");
    expect(colouredCircle.describe()).toBe("This circle has a radius of: 5");
  });
});
<|endoftext|>


<commit_before>var expect = chai.expect

describe('bacon.jquery', function() {
  describe('textFieldValue', function() {
    var field
    beforeEach(function() {
      $('#bacon-dom').html('<input type="text" id="text" value="defaultVal">')
      field = $('#bacon-dom #text')
    })

    describe('with initVal', function() {
      it('sets value to DOM', function() {
          var model = Bacon.$.textFieldValue(field, 'initVal')
          expect(field.val()).to.equal('initVal')
      })
      it('sets the initVal as the initial value of the model', function() {
        var model = Bacon.$.textFieldValue(field, 'initVal')
        specifyValue(model, 'initVal')
      })
    })

    describe('without initVal', function() {
      it('leaves DOM unaffected', function() {
          var model = Bacon.$.textFieldValue(field)
          expect(field.val()).to.equal('defaultVal')
      })
      it('uses value from DOM as initial value of the model', function() {
        var model = Bacon.$.textFieldValue(field)
        specifyValue(model, 'defaultVal')
      })
      describe('with empty default value', function() {
        it('waits for browser to autofill textfield', function(done) {
          field.val('')
          var model = Bacon.$.textFieldValue(field)
          model.filter(function (v) {
              return v
          }).onValue(function() {
            specifyValue(model, 'newVal')
            done()
          })
          field.val("newVal")
        })
      })
    })

    describe('when setting value of model', function() {
      it('sets value to DOM', function() {
          Bacon.$.textFieldValue(field).set('newVal')
          expect(field.val()).to.equal('newVal')
      })
    })

    describe('when DOM value changes', function() {
      it('updates value of model', function() {
        var model = Bacon.$.textFieldValue(field)
        field.val("newVal")
        field.trigger("keyup")
        specifyValue(model, "newVal")
      })

      it('ignores duplicates', function() {
        var model = Bacon.$.textFieldValue(field)
        field.val("newVal")
        field.trigger("keyup")
        specifyValue(model, "newVal")
        var values = collectValues(model)
        field.trigger("keyup")
        field.trigger("keyup")
        expect(values).to.deep.equal(["newVal"])
      })
    })

    describe('when element is not found', function() {
      it('returns empty string as value', function() {
        var model = Bacon.$.textFieldValue($('.asdfqwer'))
        specifyValue(model, '')
      })
    })
  })

  describe('checkBoxValue', function() {
    var field
    beforeEach(function() {
      $('#bacon-dom').html('<input type="checkbox" id="checkbox">')
      field = $('#bacon-dom #checkbox')
    })

    describe('with initVal', function() {
      it('sets value to DOM', function() {
          var model = Bacon.$.checkBoxValue(field, true)
          expect(field.prop("checked")).to.equal(true)
      })
      it('sets the initVal as the initial value of the model', function() {
        var model = Bacon.$.checkBoxValue(field, true)
        specifyValue(model, true)
      })
    })

    describe('without initVal', function() {
      it('leaves DOM unaffected', function() {
          var model = Bacon.$.checkBoxValue(field)
          expect(field.prop("checked")).to.equal(false)
      })
      it('uses value from DOM as initial value of the model', function() {
        var model = Bacon.$.checkBoxValue(field)
        specifyValue(model, false)
      })
    })

    describe('when setting value of model', function() {
      it('sets value to DOM', function() {
          Bacon.$.checkBoxValue(field).set(true)
          expect(field.prop("checked")).to.equal(true)
      })
      it('leaves defaultChecked property as is', function() {
          Bacon.$.checkBoxValue(field).set(true)
          expect(field.prop("defaultChecked")).to.equal(false)
      })
    })
    describe('when DOM value changes', function() {
      it('updates value of model', function() {
        var model = Bacon.$.checkBoxValue(field)
        field.trigger("click")
        specifyValue(model, true)
      })
    })
    describe('when element is not found', function() {
      it('returns false as value', function() {
        var model = Bacon.$.checkBoxValue($('.asdfqwer'))
        specifyValue(model, false)
      })
    })
  })

  describe('selectValue', function() {
    var field
    beforeEach(function() {
      $('#bacon-dom').html('<select id="select"><option value="a">A</option><option value="b" selected>B</option></select>')
      field = $('#bacon-dom #select')
    })

    describe('with initVal', function() {
      it('sets value to DOM', function() {
        var model = Bacon.$.selectValue(field, 'a')
        expect(field.val()).to.equal('a')
      })
      it('sets the initVal as the initial value of the model', function() {
        var model = Bacon.$.selectValue(field, 'a')
        specifyValue(model, 'a')
      })
    })

    describe('without initVal', function() {
      it('leaves DOM unaffected', function() {
        var model = Bacon.$.selectValue(field)
        expect(field.val()).to.equal('b')
      })
      it('uses value from DOM as initial value of the model', function() {
        var model = Bacon.$.selectValue(field)
        specifyValue(model, 'b')
      })
    })

    describe('when setting value of model', function() {
      it('sets value to DOM', function() {
        Bacon.$.selectValue(field).set('a')
        expect(field.val()).to.equal('a')
      })
    })
    describe('when DOM value changes', function() {
      it('updates value of model', function() {
        var model = Bacon.$.selectValue(field)
        field.val("a")
        field.trigger("change")
        specifyValue(model, "a")
      })
    })
  })

  describe('selectValue without any options', function() {
    it('sets `null` as initial value of the model', function() {
      $('#bacon-dom').html('<select id="select"></select>')
      var model = Bacon.$.selectValue($('#bacon-dom #select'))
      specifyValue(model, null)
    })
  })

  describe('selectValue when element is not found', function() {
    it('sets `undefined` as initial value of the model', function() {
      var model = Bacon.$.selectValue($('.asdfqwer'))
      specifyValue(model, undefined)
    })
  })

  describe('radioGroupValue', function() {
    var field
    beforeEach(function() {
      $('#bacon-dom').html('A<input type="radio" id="a" value="a">
B<input type="radio" id="b" value="b" checked>')
      field = $('#a,#b')
    })

    describe('with initVal', function() {
      it('sets value to DOM', function() {
        var model = Bacon.$.radioGroupValue(field, 'a')
        expect($("#a").prop("checked")).to.equal(true)
        expect($("#b").prop("checked")).to.equal(false)
      })
      it('sets the initVal as the initial value of the model', function() {
        var model = Bacon.$.radioGroupValue(field, 'a')
        specifyValue(model, 'a')
      })
    })

    describe('without initVal', function() {
      it('leaves DOM unaffected', function() {
        var model = Bacon.$.radioGroupValue(field)
        expect($("#b").prop("checked")).to.equal(true)
        expect($("#a").prop("checked")).to.equal(false)
      })
      it('uses value from DOM as initial value of the model', function() {
        var model = Bacon.$.radioGroupValue(field)
        specifyValue(model, 'b')
      })
    })

    describe('when setting value of model', function() {
      it('sets value to DOM', function() {
        Bacon.$.radioGroupValue(field).set('a')
        expect($("#a").prop("checked")).to.equal(true)
        expect($("#b").prop("checked")).to.equal(false)
      })
      it('leaves defaultChecked property as is', function() {
        Bacon.$.radioGroupValue(field).set('a')
        expect($("#a").prop("defaultChecked")).to.equal(false)
        expect($("#b").prop("defaultChecked")).to.equal(true)
      })
    })

    describe('when DOM value changes', function() {
      it('updates value of model', function() {
        var model = Bacon.$.radioGroupValue(field)
        $("#b").click()
        $("#a").click()
        specifyValue(model, "a")
      })
    })
  })

  describe('checkBoxGroupValue', function() {
    var field
    beforeEach(function() {
      $('#bacon-dom').html('A<input type="checkbox" id="a" value="a">
B<input type="checkbox" id="b" value="b" checked>')
      field = $('#a,#b')
    })

    describe('with initVal', function() {
      it('sets value to DOM', function() {
        var model = Bacon.$.checkBoxGroupValue(field, ['a'])
        expect($("#a").prop("checked")).to.equal(true)
        expect($("#b").prop("checked")).to.equal(false)
      })
      it('sets the initVal as the initial value of the model', function() {
        var model = Bacon.$.checkBoxGroupValue(field, ['a'])
        specifyValue(model, ['a'])
      })
    })

    describe('without initVal', function() {
      it('leaves DOM unaffected', function() {
        var model = Bacon.$.checkBoxGroupValue(field)
        expect($("#b").prop("checked")).to.equal(true)
        expect($("#a").prop("checked")).to.equal(false)
      })
      it('uses value from DOM as initial value of the model', function() {
        var model = Bacon.$.checkBoxGroupValue(field)
        specifyValue(model, ['b'])
      })
    })

    describe('when setting value of model', function() {
      it('sets value to DOM', function() {
        Bacon.$.checkBoxGroupValue(field).set(['a', 'b'])
        expect($("#a").prop("checked")).to.equal(true)
        expect($("#b").prop("checked")).to.equal(true)
      })
      it('leaves defaultChecked property as is', function() {
        Bacon.$.checkBoxGroupValue(field).set(['a', 'b'])
        expect($("#a").prop("defaultChecked")).to.equal(false)
        expect($("#b").prop("defaultChecked")).to.equal(true)
      })
    })

    describe('when DOM value changes', function() {
      it('updates value of model', function() {
        var model = Bacon.$.checkBoxGroupValue(field)
        $("#a").trigger("click")
        specifyValue(model, ["a", "b"])
        $("#b").trigger("click")
        specifyValue(model, ["a"])
        $("#a").trigger("click")
        specifyValue(model, [])
      })
    })
  })

  testEventHelper('click')
  testEventHelper('keyup')
  testEventHelper('keydown')
  testEventHelper('mouseup')

  describe("AJAX", function() {
    $.mockjax({
      url: "/test",
      responseTime: 0,
      responseText: "good"
    })
    describe("Converts EventStream of requests into EventStream of responses", function() {
      expectStreamValues(Bacon.once({url:"/test"}).ajax(), ["good"])
    })
    describe("Converts Property of requests into EventStream of responses", function() {
      expectStreamValues(Bacon.once({url:"/test"}).toProperty().ajax(), ["good"])
    })
  })

})

function expectStreamValues(stream, expectedValues) {
  var values = []
  before(function(done) {
    stream.onValue(function(value) { values.push(value) })
    stream.onEnd(done)
  })
  it("is an EventStream", function() {
    expect(stream instanceof Bacon.EventStream).to.be.ok()
  })
  it("contains expected values", function() {
    expect(values).to.deep.equal(expectedValues)
  })
}

function testEventHelper(eventName) {
  var methodName = eventName + "E"
  describe(methodName, function() {
    it("captures DOM events as EventStream", function() {
      $('#bacon-dom').html('<input type="text" id="text">')
      var el = $('#bacon-dom #text')
      var stream = el[methodName]()
      var values = collectValues(stream)
      el[eventName]()
      expect(values.length).to.equal(1)
    })
  })
}

function specifyValue(obs, expected) {
  var gotIt = false
  var value
  obs.onValue(function(v) {
    gotIt = true
    value = v
  })
  expect(gotIt).to.equal(true)
  expect(value).to.deep.equal(expected)
}

function collectValues(observable) {
  var values = [];
  observable.onValue(function(value) {
    return values.push(value);
  });
  return values;
}
<commit_msg>specify behavior of radioGroupValue, checkBoxGroupValue in case elements are not found<commit_after>var expect = chai.expect

describe('bacon.jquery', function() {
  describe('textFieldValue', function() {
    var field
    beforeEach(function() {
      $('#bacon-dom').html('<input type="text" id="text" value="defaultVal">')
      field = $('#bacon-dom #text')
    })

    describe('with initVal', function() {
      it('sets value to DOM', function() {
          var model = Bacon.$.textFieldValue(field, 'initVal')
          expect(field.val()).to.equal('initVal')
      })
      it('sets the initVal as the initial value of the model', function() {
        var model = Bacon.$.textFieldValue(field, 'initVal')
        specifyValue(model, 'initVal')
      })
    })

    describe('without initVal', function() {
      it('leaves DOM unaffected', function() {
          var model = Bacon.$.textFieldValue(field)
          expect(field.val()).to.equal('defaultVal')
      })
      it('uses value from DOM as initial value of the model', function() {
        var model = Bacon.$.textFieldValue(field)
        specifyValue(model, 'defaultVal')
      })
      describe('with empty default value', function() {
        it('waits for browser to autofill textfield', function(done) {
          field.val('')
          var model = Bacon.$.textFieldValue(field)
          model.filter(function (v) {
              return v
          }).onValue(function() {
            specifyValue(model, 'newVal')
            done()
          })
          field.val("newVal")
        })
      })
    })

    describe('when setting value of model', function() {
      it('sets value to DOM', function() {
          Bacon.$.textFieldValue(field).set('newVal')
          expect(field.val()).to.equal('newVal')
      })
    })

    describe('when DOM value changes', function() {
      it('updates value of model', function() {
        var model = Bacon.$.textFieldValue(field)
        field.val("newVal")
        field.trigger("keyup")
        specifyValue(model, "newVal")
      })

      it('ignores duplicates', function() {
        var model = Bacon.$.textFieldValue(field)
        field.val("newVal")
        field.trigger("keyup")
        specifyValue(model, "newVal")
        var values = collectValues(model)
        field.trigger("keyup")
        field.trigger("keyup")
        expect(values).to.deep.equal(["newVal"])
      })
    })

    describe('when element is not found', function() {
      it('returns empty string as value', function() {
        var model = Bacon.$.textFieldValue($('.asdfqwer'))
        specifyValue(model, '')
      })
    })
  })

  describe('checkBoxValue', function() {
    var field
    beforeEach(function() {
      $('#bacon-dom').html('<input type="checkbox" id="checkbox">')
      field = $('#bacon-dom #checkbox')
    })

    describe('with initVal', function() {
      it('sets value to DOM', function() {
          var model = Bacon.$.checkBoxValue(field, true)
          expect(field.prop("checked")).to.equal(true)
      })
      it('sets the initVal as the initial value of the model', function() {
        var model = Bacon.$.checkBoxValue(field, true)
        specifyValue(model, true)
      })
    })

    describe('without initVal', function() {
      it('leaves DOM unaffected', function() {
          var model = Bacon.$.checkBoxValue(field)
          expect(field.prop("checked")).to.equal(false)
      })
      it('uses value from DOM as initial value of the model', function() {
        var model = Bacon.$.checkBoxValue(field)
        specifyValue(model, false)
      })
    })

    describe('when setting value of model', function() {
      it('sets value to DOM', function() {
          Bacon.$.checkBoxValue(field).set(true)
          expect(field.prop("checked")).to.equal(true)
      })
      it('leaves defaultChecked property as is', function() {
          Bacon.$.checkBoxValue(field).set(true)
          expect(field.prop("defaultChecked")).to.equal(false)
      })
    })
    describe('when DOM value changes', function() {
      it('updates value of model', function() {
        var model = Bacon.$.checkBoxValue(field)
        field.trigger("click")
        specifyValue(model, true)
      })
    })
    describe('when element is not found', function() {
      it('returns false as value', function() {
        var model = Bacon.$.checkBoxValue($('.asdfqwer'))
        specifyValue(model, false)
      })
    })
  })

  describe('selectValue', function() {
    var field
    beforeEach(function() {
      $('#bacon-dom').html('<select id="select"><option value="a">A</option><option value="b" selected>B</option></select>')
      field = $('#bacon-dom #select')
    })

    describe('with initVal', function() {
      it('sets value to DOM', function() {
        var model = Bacon.$.selectValue(field, 'a')
        expect(field.val()).to.equal('a')
      })
      it('sets the initVal as the initial value of the model', function() {
        var model = Bacon.$.selectValue(field, 'a')
        specifyValue(model, 'a')
      })
    })

    describe('without initVal', function() {
      it('leaves DOM unaffected', function() {
        var model = Bacon.$.selectValue(field)
        expect(field.val()).to.equal('b')
      })
      it('uses value from DOM as initial value of the model', function() {
        var model = Bacon.$.selectValue(field)
        specifyValue(model, 'b')
      })
    })

    describe('when setting value of model', function() {
      it('sets value to DOM', function() {
        Bacon.$.selectValue(field).set('a')
        expect(field.val()).to.equal('a')
      })
    })
    describe('when DOM value changes', function() {
      it('updates value of model', function() {
        var model = Bacon.$.selectValue(field)
        field.val("a")
        field.trigger("change")
        specifyValue(model, "a")
      })
    })
  })

  describe('selectValue without any options', function() {
    it('sets `null` as initial value of the model', function() {
      $('#bacon-dom').html('<select id="select"></select>')
      var model = Bacon.$.selectValue($('#bacon-dom #select'))
      specifyValue(model, null)
    })
  })

  describe('selectValue when element is not found', function() {
    it('sets `undefined` as initial value of the model', function() {
      var model = Bacon.$.selectValue($('.asdfqwer'))
      specifyValue(model, undefined)
    })
  })

  describe('radioGroupValue', function() {
    var field
    beforeEach(function() {
      $('#bacon-dom').html('A<input type="radio" id="a" value="a">
B<input type="radio" id="b" value="b" checked>')
      field = $('#a,#b')
    })

    describe('with initVal', function() {
      it('sets value to DOM', function() {
        var model = Bacon.$.radioGroupValue(field, 'a')
        expect($("#a").prop("checked")).to.equal(true)
        expect($("#b").prop("checked")).to.equal(false)
      })
      it('sets the initVal as the initial value of the model', function() {
        var model = Bacon.$.radioGroupValue(field, 'a')
        specifyValue(model, 'a')
      })
    })

    describe('without initVal', function() {
      it('leaves DOM unaffected', function() {
        var model = Bacon.$.radioGroupValue(field)
        expect($("#b").prop("checked")).to.equal(true)
        expect($("#a").prop("checked")).to.equal(false)
      })
      it('uses value from DOM as initial value of the model', function() {
        var model = Bacon.$.radioGroupValue(field)
        specifyValue(model, 'b')
      })
    })

    describe('when setting value of model', function() {
      it('sets value to DOM', function() {
        Bacon.$.radioGroupValue(field).set('a')
        expect($("#a").prop("checked")).to.equal(true)
        expect($("#b").prop("checked")).to.equal(false)
      })
      it('leaves defaultChecked property as is', function() {
        Bacon.$.radioGroupValue(field).set('a')
        expect($("#a").prop("defaultChecked")).to.equal(false)
        expect($("#b").prop("defaultChecked")).to.equal(true)
      })
    })

    describe('when DOM value changes', function() {
      it('updates value of model', function() {
        var model = Bacon.$.radioGroupValue(field)
        $("#b").click()
        $("#a").click()
        specifyValue(model, "a")
      })
    })

    describe('when elements are not found', function() {
      it('returns undefined as value', function() {
        var model = Bacon.$.radioGroupValue($(".asdfqwer"))
        specifyValue(model, undefined)
      })
    })
  })

  describe('checkBoxGroupValue', function() {
    var field
    beforeEach(function() {
      $('#bacon-dom').html('A<input type="checkbox" id="a" value="a">
B<input type="checkbox" id="b" value="b" checked>')
      field = $('#a,#b')
    })

    describe('with initVal', function() {
      it('sets value to DOM', function() {
        var model = Bacon.$.checkBoxGroupValue(field, ['a'])
        expect($("#a").prop("checked")).to.equal(true)
        expect($("#b").prop("checked")).to.equal(false)
      })
      it('sets the initVal as the initial value of the model', function() {
        var model = Bacon.$.checkBoxGroupValue(field, ['a'])
        specifyValue(model, ['a'])
      })
    })

    describe('without initVal', function() {
      it('leaves DOM unaffected', function() {
        var model = Bacon.$.checkBoxGroupValue(field)
        expect($("#b").prop("checked")).to.equal(true)
        expect($("#a").prop("checked")).to.equal(false)
      })
      it('uses value from DOM as initial value of the model', function() {
        var model = Bacon.$.checkBoxGroupValue(field)
        specifyValue(model, ['b'])
      })
    })

    describe('when setting value of model', function() {
      it('sets value to DOM', function() {
        Bacon.$.checkBoxGroupValue(field).set(['a', 'b'])
        expect($("#a").prop("checked")).to.equal(true)
        expect($("#b").prop("checked")).to.equal(true)
      })
      it('leaves defaultChecked property as is', function() {
        Bacon.$.checkBoxGroupValue(field).set(['a', 'b'])
        expect($("#a").prop("defaultChecked")).to.equal(false)
        expect($("#b").prop("defaultChecked")).to.equal(true)
      })
    })

    describe('when DOM value changes', function() {
      it('updates value of model', function() {
        var model = Bacon.$.checkBoxGroupValue(field)
        $("#a").trigger("click")
        specifyValue(model, ["a", "b"])
        $("#b").trigger("click")
        specifyValue(model, ["a"])
        $("#a").trigger("click")
        specifyValue(model, [])
      })
    })
    describe('when elements are not found', function() {
      it('returns [] as value', function() {
        var model = Bacon.$.checkBoxGroupValue($(".asdfqwer"))
        specifyValue(model, [])
      })
    })
  })

  testEventHelper('click')
  testEventHelper('keyup')
  testEventHelper('keydown')
  testEventHelper('mouseup')

  describe("AJAX", function() {
    $.mockjax({
      url: "/test",
      responseTime: 0,
      responseText: "good"
    })
    describe("Converts EventStream of requests into EventStream of responses", function() {
      expectStreamValues(Bacon.once({url:"/test"}).ajax(), ["good"])
    })
    describe("Converts Property of requests into EventStream of responses", function() {
      expectStreamValues(Bacon.once({url:"/test"}).toProperty().ajax(), ["good"])
    })
  })

})

function expectStreamValues(stream, expectedValues) {
  var values = []
  before(function(done) {
    stream.onValue(function(value) { values.push(value) })
    stream.onEnd(done)
  })
  it("is an EventStream", function() {
    expect(stream instanceof Bacon.EventStream).to.be.ok()
  })
  it("contains expected values", function() {
    expect(values).to.deep.equal(expectedValues)
  })
}

function testEventHelper(eventName) {
  var methodName = eventName + "E"
  describe(methodName, function() {
    it("captures DOM events as EventStream", function() {
      $('#bacon-dom').html('<input type="text" id="text">')
      var el = $('#bacon-dom #text')
      var stream = el[methodName]()
      var values = collectValues(stream)
      el[eventName]()
      expect(values.length).to.equal(1)
    })
  })
}

function specifyValue(obs, expected) {
  var gotIt = false
  var value
  obs.onValue(function(v) {
    gotIt = true
    value = v
  })
  expect(gotIt).to.equal(true)
  expect(value).to.deep.equal(expected)
}

function collectValues(observable) {
  var values = [];
  observable.onValue(function(value) {
    return values.push(value);
  });
  return values;
}
<|endoftext|>


<commit_before>{% load i18n %}

/* globals
    getAvailableTableFilters,
    inventreeLoad,
    inventreeSave,
    reloadTableFilters,
*/

/* exported
   setupFilterList,
*/

/**
 * Code for managing query filters / table options.
 *
 * Optional query filters are available to the user for various
 * tables display in the web interface.
 * These filters are saved to the web session, and should be
 * persistent for a given table type.
 *
 * This makes use of the 'inventreeSave' and 'inventreeLoad' functions
 * for writing to and reading from session storage.
 *
 */

function defaultFilters() {
    return {
        stock: 'cascade=1&in_stock=1',
        build: '',
        parts: 'cascade=1',
        company: '',
        salesorder: '',
        purchaseorder: '',
    };
}

/**
 * Load table filters for the given table from session storage
 *
 * @param tableKey - String key for the particular table
 * @param defaults - Default filters for this table e.g. 'cascade=1&location=5'
 */
function loadTableFilters(tableKey) {

    var lookup = 'table-filters-' + tableKey.toLowerCase();

    var defaults = defaultFilters()[tableKey] || '';

    var filterstring = inventreeLoad(lookup, defaults);

    var filters = {};

    filterstring.split('&').forEach(function(item) {
        item = item.trim();

        if (item.length > 0) {
            var f = item.split('=');

            if (f.length == 2) {
                filters[f[0]] = f[1];
            } else {
                console.log(`Improperly formatted filter: ${item}`);
            }
        }
    });

    return filters;
}

/**
 * Save table filters to session storage
 *
 * @param {*} tableKey - string key for the given table
 * @param {*} filters - object of string:string pairs
 */
function saveTableFilters(tableKey, filters) {
    var lookup = 'table-filters-' + tableKey.toLowerCase();

    var strings = [];

    for (var key in filters) {
        strings.push(`${key.trim()}=${String(filters[key]).trim()}`);
    }

    var filterstring = strings.join('&');

    inventreeSave(lookup, filterstring);
}

/*
 * Remove a named filter parameter
 */
function removeTableFilter(tableKey, filterKey) {

    var filters = loadTableFilters(tableKey);

    delete filters[filterKey];

    saveTableFilters(tableKey, filters);

    // Return a copy of the updated filters
    return filters;
}

function addTableFilter(tableKey, filterKey, filterValue) {

    var filters = loadTableFilters(tableKey);

    filters[filterKey] = filterValue;

    saveTableFilters(tableKey, filters);

    // Return a copy of the updated filters
    return filters;
}

/*
 * Clear all the custom filters for a given table
 */
function clearTableFilters(tableKey) {
    saveTableFilters(tableKey, {});

    return {};
}

/*
 * Return a list of the "available" filters for a given table key.
 * A filter is "available" if it is not already being used to filter the table.
 * Once a filter is selected, it will not be returned here.
 */
function getRemainingTableFilters(tableKey) {

    var filters = loadTableFilters(tableKey);

    var remaining = getAvailableTableFilters(tableKey);

    for (var key in filters) {
        // Delete the filter if it is already in use
        delete remaining[key];
    }

    return remaining;
}

/*
 * Return the filter settings for a given table and key combination.
 * Return empty object if the combination does not exist.
 */
function getFilterSettings(tableKey, filterKey) {

    return getAvailableTableFilters(tableKey)[filterKey] || {};
}

/*
 * Return a set of key:value options for the given filter.
 * If no options are specified (e.g. for a number field),
 * then a null object is returned.
 */
function getFilterOptionList(tableKey, filterKey) {

    var settings = getFilterSettings(tableKey, filterKey);

    if (settings.type == 'bool') {
        return {
            '1': {
                key: '1',
                value: '{% trans "true" %}',
            },
            '0': {
                key: '0',
                value: '{% trans "false" %}',
            },
        };
    } else if ('options' in settings) {
        return settings.options;
    }

    return null;
}

/*
 * Generate a list of <option> tags for the given table.
 */
function generateAvailableFilterList(tableKey) {

    var remaining = getRemainingTableFilters(tableKey);

    var id = 'filter-tag-' + tableKey.toLowerCase();

    var html = `<select class='form-control filter-input' id='${id}' name='tag'>`;

    html += `<option value=''>{% trans 'Select filter' %}</option>`;

    for (var opt in remaining) {
        var title = getFilterTitle(tableKey, opt);
        html += `<option value='${opt}'>${title}</option>`;
    }

    html += `</select>`;

    return html;
}

/*
 * Generate an input for setting the value of a given filter.
 */
function generateFilterInput(tableKey, filterKey) {

    var id = 'filter-value-' + tableKey.toLowerCase();

    if (filterKey == null || filterKey.length == 0) {
        // Return an 'empty' element
        return `<div class='filter-input' id='${id}'></div>`;
    }

    var options = getFilterOptionList(tableKey, filterKey);

    var html = '';

    // A 'null' options list means that a simple text-input dialog should be used
    if (options == null) {
        html = `<input class='form-control filter-input' id='${id}' name='value'></input>`;
    } else {
        // Return a 'select' input with the available values
        html = `<select class='form-control filter-input' id='${id}' name='value'>`;

        for (var key in options) {
            var option = options[key];
            html += `<option value='${key}'>${option.value}</option>`;
        }

        html += `</select>`;
    }

    return html;
}

/**
 * Configure a filter list for a given table
 *
 * @param {*} tableKey - string lookup key for filter settings
 * @param {*} table - bootstrapTable element to update
 * @param {*} target - name of target element on page
 */
function setupFilterList(tableKey, table, target) {

    var addClicked = false;

    if (target == null || target.length == 0) {
        target = `#filter-list-${tableKey}`;
    }

    var tag = `filter-tag-${tableKey}`;
    var add = `filter-add-${tableKey}`;
    var clear = `filter-clear-${tableKey}`;
    var make = `filter-make-${tableKey}`;

    var filters = loadTableFilters(tableKey);

    var element = $(target);

    if (!element) {
        console.log(`WARNING: setupFilterList could not find target '${target}'`);
        return;
    }

    // One blank slate, please
    element.empty();

    element.append(`<button id='reload-${tableKey}' title='{% trans "Reload data" %}' class='btn btn-default filter-tag'><span class='fas fa-redo-alt'></span></button>`);

    // If there are no filters defined for this table, exit now
    if (jQuery.isEmptyObject(getAvailableTableFilters(tableKey))) {
        return;
    }

    // If there are filters currently "in use", add them in!
    element.append(`<button id='${add}' title='{% trans "Add new filter" %}' class='btn btn-default filter-tag'><span class='fas fa-filter'></span></button>`);

    if (Object.keys(filters).length > 0) {
        element.append(`<button id='${clear}' title='{% trans "Clear all filters" %}' class='btn btn-default filter-tag'><span class='fas fa-backspace icon-red'></span></button>`);
    }

    for (var key in filters) {
        var value = getFilterOptionValue(tableKey, key, filters[key]);
        var title = getFilterTitle(tableKey, key);
        var description = getFilterDescription(tableKey, key);

        element.append(`<div title='${description}' class='filter-tag'>${title} = ${value}<span ${tag}='${key}' class='close'>x</span></div>`);
    }

    // Callback for reloading the table
    element.find(`#reload-${tableKey}`).click(function() {
        $(table).bootstrapTable('refresh');
    });

    // Add a callback for adding a new filter
    element.find(`#${add}`).click(function clicked() {

        if (!addClicked) {

            addClicked = true;

            var html = '';

            html += generateAvailableFilterList(tableKey);
            html += generateFilterInput(tableKey);

            html += `<button title='{% trans "Create filter" %}' class='btn btn-default filter-tag' id='${make}'><span class='fas fa-plus'></span></button>`;

            element.append(html);

            // Add a callback for when the filter tag selection is changed
            element.find(`#filter-tag-${tableKey}`).on('change', function() {
                var list = element.find(`#filter-value-${tableKey}`);

                list.replaceWith(generateFilterInput(tableKey, this.value));
            });

            // Add a callback for when the new filter is created
            element.find(`#filter-make-${tableKey}`).click(function() {
                var tag = element.find(`#filter-tag-${tableKey}`).val();
                var val = element.find(`#filter-value-${tableKey}`).val();

                // Only add the new filter if it is not empty!
                if (tag && tag.length > 0) {
                    var filters = addTableFilter(tableKey, tag, val);
                    reloadTableFilters(table, filters);

                    // Run this function again
                    setupFilterList(tableKey, table, target);
                }

            });
        } else {
            addClicked = false;

            setupFilterList(tableKey, table, target);
        }

    });

    // Add a callback for clearing all the filters
    element.find(`#${clear}`).click(function() {
        var filters = clearTableFilters(tableKey);

        reloadTableFilters(table, filters);

        setupFilterList(tableKey, table, target);
    });

    // Add callback for deleting each filter
    element.find('.close').click(function() {
        var me = $(this);

        var filter = me.attr(`filter-tag-${tableKey}`);

        var filters = removeTableFilter(tableKey, filter);

        reloadTableFilters(table, filters);

        // Run this function again!
        setupFilterList(tableKey, table, target);
    });
}

/**
 * Return the pretty title for the given table and filter selection.
 * If no title is provided, default to the key value.
 *
 */
function getFilterTitle(tableKey, filterKey) {
    var settings = getFilterSettings(tableKey, filterKey);
    return settings.title || filterKey;
}

/*
 * Return a description for the given table and filter selection.
 */
function getFilterDescription(tableKey, filterKey) {
    var settings = getFilterSettings(tableKey, filterKey);
    return settings.description || filterKey;
}

/*
 * Return the display value for a particular option
 */
function getFilterOptionValue(tableKey, filterKey, valueKey) {

    var filter = getFilterSettings(tableKey, filterKey);

    var value = String(valueKey);

    // Lookup for boolean options
    if (filter.type == 'bool') {
        if (value == '1') return '{% trans "true" %}';
        if (value == '0') return '{% trans "false" %}';

        return value;
    }

    // Iterate through a list of options
    if ('options' in filter) {
        for (var key in filter.options) {

            if (key == valueKey) {
                return filter.options[key].value;
            }
        }

        // Could not find a match
        return value;
    }

    // Cannot map to a display string - return the original text
    return value;
}

<commit_msg>bug fix: enable "table reload" for tables without any filters<commit_after>{% load i18n %}

/* globals
    getAvailableTableFilters,
    inventreeLoad,
    inventreeSave,
    reloadTableFilters,
*/

/* exported
   setupFilterList,
*/

/**
 * Code for managing query filters / table options.
 *
 * Optional query filters are available to the user for various
 * tables display in the web interface.
 * These filters are saved to the web session, and should be
 * persistent for a given table type.
 *
 * This makes use of the 'inventreeSave' and 'inventreeLoad' functions
 * for writing to and reading from session storage.
 *
 */

function defaultFilters() {
    return {
        stock: 'cascade=1&in_stock=1',
        build: '',
        parts: 'cascade=1',
        company: '',
        salesorder: '',
        purchaseorder: '',
    };
}

/**
 * Load table filters for the given table from session storage
 *
 * @param tableKey - String key for the particular table
 * @param defaults - Default filters for this table e.g. 'cascade=1&location=5'
 */
function loadTableFilters(tableKey) {

    var lookup = 'table-filters-' + tableKey.toLowerCase();

    var defaults = defaultFilters()[tableKey] || '';

    var filterstring = inventreeLoad(lookup, defaults);

    var filters = {};

    filterstring.split('&').forEach(function(item) {
        item = item.trim();

        if (item.length > 0) {
            var f = item.split('=');

            if (f.length == 2) {
                filters[f[0]] = f[1];
            } else {
                console.log(`Improperly formatted filter: ${item}`);
            }
        }
    });

    return filters;
}

/**
 * Save table filters to session storage
 *
 * @param {*} tableKey - string key for the given table
 * @param {*} filters - object of string:string pairs
 */
function saveTableFilters(tableKey, filters) {
    var lookup = 'table-filters-' + tableKey.toLowerCase();

    var strings = [];

    for (var key in filters) {
        strings.push(`${key.trim()}=${String(filters[key]).trim()}`);
    }

    var filterstring = strings.join('&');

    inventreeSave(lookup, filterstring);
}

/*
 * Remove a named filter parameter
 */
function removeTableFilter(tableKey, filterKey) {

    var filters = loadTableFilters(tableKey);

    delete filters[filterKey];

    saveTableFilters(tableKey, filters);

    // Return a copy of the updated filters
    return filters;
}

function addTableFilter(tableKey, filterKey, filterValue) {

    var filters = loadTableFilters(tableKey);

    filters[filterKey] = filterValue;

    saveTableFilters(tableKey, filters);

    // Return a copy of the updated filters
    return filters;
}

/*
 * Clear all the custom filters for a given table
 */
function clearTableFilters(tableKey) {
    saveTableFilters(tableKey, {});

    return {};
}

/*
 * Return a list of the "available" filters for a given table key.
 * A filter is "available" if it is not already being used to filter the table.
 * Once a filter is selected, it will not be returned here.
 */
function getRemainingTableFilters(tableKey) {

    var filters = loadTableFilters(tableKey);

    var remaining = getAvailableTableFilters(tableKey);

    for (var key in filters) {
        // Delete the filter if it is already in use
        delete remaining[key];
    }

    return remaining;
}

/*
 * Return the filter settings for a given table and key combination.
 * Return empty object if the combination does not exist.
 */
function getFilterSettings(tableKey, filterKey) {

    return getAvailableTableFilters(tableKey)[filterKey] || {};
}

/*
 * Return a set of key:value options for the given filter.
 * If no options are specified (e.g. for a number field),
 * then a null object is returned.
 */
function getFilterOptionList(tableKey, filterKey) {

    var settings = getFilterSettings(tableKey, filterKey);

    if (settings.type == 'bool') {
        return {
            '1': {
                key: '1',
                value: '{% trans "true" %}',
            },
            '0': {
                key: '0',
                value: '{% trans "false" %}',
            },
        };
    } else if ('options' in settings) {
        return settings.options;
    }

    return null;
}

/*
 * Generate a list of <option> tags for the given table.
 */
function generateAvailableFilterList(tableKey) {

    var remaining = getRemainingTableFilters(tableKey);

    var id = 'filter-tag-' + tableKey.toLowerCase();

    var html = `<select class='form-control filter-input' id='${id}' name='tag'>`;

    html += `<option value=''>{% trans 'Select filter' %}</option>`;

    for (var opt in remaining) {
        var title = getFilterTitle(tableKey, opt);
        html += `<option value='${opt}'>${title}</option>`;
    }

    html += `</select>`;

    return html;
}

/*
 * Generate an input for setting the value of a given filter.
 */
function generateFilterInput(tableKey, filterKey) {

    var id = 'filter-value-' + tableKey.toLowerCase();

    if (filterKey == null || filterKey.length == 0) {
        // Return an 'empty' element
        return `<div class='filter-input' id='${id}'></div>`;
    }

    var options = getFilterOptionList(tableKey, filterKey);

    var html = '';

    // A 'null' options list means that a simple text-input dialog should be used
    if (options == null) {
        html = `<input class='form-control filter-input' id='${id}' name='value'></input>`;
    } else {
        // Return a 'select' input with the available values
        html = `<select class='form-control filter-input' id='${id}' name='value'>`;

        for (var key in options) {
            var option = options[key];
            html += `<option value='${key}'>${option.value}</option>`;
        }

        html += `</select>`;
    }

    return html;
}

/**
 * Configure a filter list for a given table
 *
 * @param {*} tableKey - string lookup key for filter settings
 * @param {*} table - bootstrapTable element to update
 * @param {*} target - name of target element on page
 */
function setupFilterList(tableKey, table, target) {

    var addClicked = false;

    if (target == null || target.length == 0) {
        target = `#filter-list-${tableKey}`;
    }

    var tag = `filter-tag-${tableKey}`;
    var add = `filter-add-${tableKey}`;
    var clear = `filter-clear-${tableKey}`;
    var make = `filter-make-${tableKey}`;

    var filters = loadTableFilters(tableKey);

    var element = $(target);

    if (!element) {
        console.log(`WARNING: setupFilterList could not find target '${target}'`);
        return;
    }

    // One blank slate, please
    element.empty();

    element.append(`<button id='reload-${tableKey}' title='{% trans "Reload data" %}' class='btn btn-default filter-tag'><span class='fas fa-redo-alt'></span></button>`);

    // Callback for reloading the table
    element.find(`#reload-${tableKey}`).click(function() {
        $(table).bootstrapTable('refresh');
    });

    // If there are no filters defined for this table, exit now
    if (jQuery.isEmptyObject(getAvailableTableFilters(tableKey))) {
        return;
    }

    // If there are filters currently "in use", add them in!
    element.append(`<button id='${add}' title='{% trans "Add new filter" %}' class='btn btn-default filter-tag'><span class='fas fa-filter'></span></button>`);

    if (Object.keys(filters).length > 0) {
        element.append(`<button id='${clear}' title='{% trans "Clear all filters" %}' class='btn btn-default filter-tag'><span class='fas fa-backspace icon-red'></span></button>`);
    }

    for (var key in filters) {
        var value = getFilterOptionValue(tableKey, key, filters[key]);
        var title = getFilterTitle(tableKey, key);
        var description = getFilterDescription(tableKey, key);

        element.append(`<div title='${description}' class='filter-tag'>${title} = ${value}<span ${tag}='${key}' class='close'>x</span></div>`);
    }

    // Add a callback for adding a new filter
    element.find(`#${add}`).click(function clicked() {

        if (!addClicked) {

            addClicked = true;

            var html = '';

            html += generateAvailableFilterList(tableKey);
            html += generateFilterInput(tableKey);

            html += `<button title='{% trans "Create filter" %}' class='btn btn-default filter-tag' id='${make}'><span class='fas fa-plus'></span></button>`;

            element.append(html);

            // Add a callback for when the filter tag selection is changed
            element.find(`#filter-tag-${tableKey}`).on('change', function() {
                var list = element.find(`#filter-value-${tableKey}`);

                list.replaceWith(generateFilterInput(tableKey, this.value));
            });

            // Add a callback for when the new filter is created
            element.find(`#filter-make-${tableKey}`).click(function() {
                var tag = element.find(`#filter-tag-${tableKey}`).val();
                var val = element.find(`#filter-value-${tableKey}`).val();

                // Only add the new filter if it is not empty!
                if (tag && tag.length > 0) {
                    var filters = addTableFilter(tableKey, tag, val);
                    reloadTableFilters(table, filters);

                    // Run this function again
                    setupFilterList(tableKey, table, target);
                }

            });
        } else {
            addClicked = false;

            setupFilterList(tableKey, table, target);
        }

    });

    // Add a callback for clearing all the filters
    element.find(`#${clear}`).click(function() {
        var filters = clearTableFilters(tableKey);

        reloadTableFilters(table, filters);

        setupFilterList(tableKey, table, target);
    });

    // Add callback for deleting each filter
    element.find('.close').click(function() {
        var me = $(this);

        var filter = me.attr(`filter-tag-${tableKey}`);

        var filters = removeTableFilter(tableKey, filter);

        reloadTableFilters(table, filters);

        // Run this function again!
        setupFilterList(tableKey, table, target);
    });
}

/**
 * Return the pretty title for the given table and filter selection.
 * If no title is provided, default to the key value.
 *
 */
function getFilterTitle(tableKey, filterKey) {
    var settings = getFilterSettings(tableKey, filterKey);
    return settings.title || filterKey;
}

/*
 * Return a description for the given table and filter selection.
 */
function getFilterDescription(tableKey, filterKey) {
    var settings = getFilterSettings(tableKey, filterKey);
    return settings.description || filterKey;
}

/*
 * Return the display value for a particular option
 */
function getFilterOptionValue(tableKey, filterKey, valueKey) {

    var filter = getFilterSettings(tableKey, filterKey);

    var value = String(valueKey);

    // Lookup for boolean options
    if (filter.type == 'bool') {
        if (value == '1') return '{% trans "true" %}';
        if (value == '0') return '{% trans "false" %}';

        return value;
    }

    // Iterate through a list of options
    if ('options' in filter) {
        for (var key in filter.options) {

            if (key == valueKey) {
                return filter.options[key].value;
            }
        }

        // Could not find a match
        return value;
    }

    // Cannot map to a display string - return the original text
    return value;
}

<|endoftext|>


<commit_before>describe("About Objects", function () {

  describe("Properties", function () {
    var meglomaniac;

    beforeEach(function () {
       meglomaniac = {  mastermind: "Joker", henchwoman: "Harley" };
    });

    it("should confirm objects are collections of properties", function () {
      expect(meglomaniac.mastermind).toBe(FILL_ME_IN);
    });

    it("should confirm that properties are case sensitive", function () {
      expect(meglomaniac.henchwoman).toBe(FILL_ME_IN);
      expect(meglomaniac.henchWoman).toBe(FILL_ME_IN);
    });
  });

  it("should know properties that are functions act like methods", function () {
    var meglomaniac = {
      mastermind : "Brain",
      henchman: "Pinky",
      battleCry: function (noOfBrains) {
        return "They are " + this.henchman + " and the" +
          Array(noOfBrains + 1).join(" " + this.mastermind);
      }
    };

    var battleCry = meglomaniac.battleCry(4);
    expect(FILL_ME_IN).toMatch(battleCry);
  });

  it("should confirm that when a function is attached to an object, 'this' refers to the object", function () {
    var currentDate = new Date()
    var currentYear = (currentDate.getFullYear());
    var meglomaniac = {
      mastermind: "James Wood",
      henchman: "Adam West",
      birthYear: 1970,
      calculateAge: function () {
        return currentYear - this.birthYear;
      }
    };

    expect(currentYear).toBe(FILL_ME_IN);
    expect(meglomaniac.calculateAge()).toBe(FILL_ME_IN);
  });

  describe("'in' keyword", function () {
    var meglomaniac;
    beforeEach(function () {
      meglomaniac = {
        mastermind: "The Monarch",
        henchwoman: "Dr Girlfriend",
        theBomb: true
      };
    });

    it("should have the bomb", function () {

      var hasBomb = "theBomb" in meglomaniac;

      expect(hasBomb).toBe(FILL_ME_IN);
    });

    it("should not have the detonator however", function () {

      var hasDetonator = "theDetonator" in meglomaniac;

      expect(hasDetonator).toBe(FILL_ME_IN);
    });
  });

  it("should know that properties can be added and deleted", function () {
    var meglomaniac = { mastermind : "Agent Smith", henchman: "Agent Smith" };

    expect("secretary" in meglomaniac).toBe(FILL_ME_IN);

    meglomaniac.secretary = "Agent Smith";
    expect("secretary" in meglomaniac).toBe(FILL_ME_IN);

    delete meglomaniac.henchman;
    expect("henchman" in meglomaniac).toBe(FILL_ME_IN);
  });

  it("should use prototype to add to all objects", function () {
    function Circle(radius)
    {
      this.radius = radius;
    }

    var simpleCircle = new Circle(10);
    var colouredCircle = new Circle(5);
    colouredCircle.colour = "red";

    expect(simpleCircle.colour).toBe(FILL_ME_IN);
    expect(colouredCircle.colour).toBe(FILL_ME_IN);

    Circle.prototype.describe = function () {
      return "This circle has a radius of: " + this.radius;
    };

    expect(simpleCircle.describe()).toBe(FILL_ME_IN);
    expect(colouredCircle.describe()).toBe(FILL_ME_IN);
  });
});
<commit_msg>Completed AboutObjects. Noticed on windows machine that completed function as a string would not pass no matter which option of characters was thrown at it. Also, noticed this function was pulled from the javascript koans repo.<commit_after>describe("About Objects", function () {

  describe("Properties", function () {
    var meglomaniac;

    beforeEach(function () {
       meglomaniac = {  mastermind: "Joker", henchwoman: "Harley" };
    });

    it("should confirm objects are collections of properties", function () {
      expect(meglomaniac.mastermind).toBe("Joker");
    });

    it("should confirm that properties are case sensitive", function () {
      expect(meglomaniac.henchwoman).toBe("Harley");
      expect(meglomaniac.henchWoman).toBe(undefined);
    });
  });

  it("should know properties that are functions act like methods", function () {
    var meglomaniac = {
      mastermind : "Brain",
      henchman: "Pinky",
      battleCry: function (noOfBrains) {
        return "They are " + this.henchman + " and the" +
          Array(noOfBrains + 1).join(" " + this.mastermind);
      }
    };

    var battleCry = meglomaniac.battleCry(4);
    expect("They are Pinky and the Brain Brain Brain Brain Brain").toMatch(battleCry);
  });

  it("should confirm that when a function is attached to an object, 'this' refers to the object", function () {
    var currentDate = new Date()
    var currentYear = (currentDate.getFullYear());
    var meglomaniac = {
      mastermind: "James Wood",
      henchman: "Adam West",
      birthYear: 1970,
      calculateAge: function () {
        return currentYear - this.birthYear;
      }
    };

    expect(currentYear).toBe(2015);
    expect(meglomaniac.calculateAge()).toBe(45);
  });

  describe("'in' keyword", function () {
    var meglomaniac;
    beforeEach(function () {
      meglomaniac = {
        mastermind: "The Monarch",
        henchwoman: "Dr Girlfriend",
        theBomb: true
      };
    });

    it("should have the bomb", function () {

      var hasBomb = "theBomb" in meglomaniac;

      expect(hasBomb).toBe(true);
    });

    it("should not have the detonator however", function () {

      var hasDetonator = "theDetonator" in meglomaniac;

      expect(hasDetonator).toBe(false);
    });
  });

  it("should know that properties can be added and deleted", function () {
    var meglomaniac = { mastermind : "Agent Smith", henchman: "Agent Smith" };

    expect("secretary" in meglomaniac).toBe(false);

    meglomaniac.secretary = "Agent Smith";
    expect("secretary" in meglomaniac).toBe(true);

    delete meglomaniac.henchman;
    expect("henchman" in meglomaniac).toBe(false);
  });

  it("should use prototype to add to all objects", function () {
    function Circle(radius)
    {
      this.radius = radius;
    }

    var simpleCircle = new Circle(10);
    var colouredCircle = new Circle(5);
    colouredCircle.colour = "red";

    expect(simpleCircle.colour).toBe(undefined);
    expect(colouredCircle.colour).toBe("red");

    Circle.prototype.describe = function () {
      return "This circle has a radius of: " + this.radius;
    };

    expect(simpleCircle.describe()).toBe("This circle has a radius of: 10");
    expect(colouredCircle.describe()).toBe("This circle has a radius of: 5");
  });
});
<|endoftext|>


<commit_before>/**
 * Created by lucavgobbi on 2015-10-12.
 */
"use strict";

/**
 * PersonAsClass
 * Defines a class (ES6)
 */
class PersonAsClass {
    constructor(options) {
        "use strict";
        this.name = options.name;
        this.weight = options.weight;
        this.height = options.height;
    }

    walk (steps) {
        // Supose that each step can walk 1/3 of the height
        return steps * this.height / 3;
    }

    sleep () {
        return this.name + " slept for 1h";
    }

    toString () {
        "use strict";
        return this.name + " is " + this.weight + "m tall";
    }

    whoIAm () {
        return "I'm a class";
    }

    static someStatic (name) {
        return "I would be " + name;
    }
}

/**
 * personAsPrototype
 * Defines a prototype (ES5)
 */
var personAsPrototype = function (options) {
    this.name = options.name;
    this.weight = options.weight;
    this.height = options.height;
};

personAsPrototype.prototype.walk = function (steps) {
    // Supose that each step can walk 1/3 of the height
    return steps * this.height / 3;
};

personAsPrototype.prototype.sleep = function () {
    return this.name + " slept for 1h";
};

personAsPrototype.prototype.toString = function () {
    return this.name + " is " + this.weight + "m tall";
};

personAsPrototype.prototype.whoIAm = function () {
    return "I'm a prototype";
};

personAsPrototype.someStatic = function (name) {
    return "I would be " + name;
};

// Instantiate PersonAsClass
var meAsClass = new PersonAsClass({ name: "Luca", height: 1.7, weight: 60 });
var youAsClass = new PersonAsClass({ name: "Luca", height: 1.78, weight: 71 });

// Instantiate PersonAsPrototype
var meAsPrototype = new personAsPrototype({ name: "Luca", height: 1.7, weight: 60 });
var youAsPrototype = new personAsPrototype({ name: "You", height: 1.78, weight: 71 });

console.log(meAsClass.whoIAm());
console.log(meAsClass.walk(5));
console.log(meAsClass.toString());
console.log(PersonAsClass.someStatic("John"));

console.log(youAsClass.whoIAm());
console.log(youAsClass.walk(5));
console.log(youAsClass.toString());
console.log(PersonAsClass.someStatic("John"));

console.log(meAsPrototype.whoIAm());
console.log(meAsPrototype.walk());
console.log(meAsPrototype.toString());
console.log(personAsPrototype.someStatic("John"));

console.log(youAsPrototype.whoIAm());
console.log(youAsPrototype.walk());
console.log(youAsPrototype.toString());
console.log(personAsPrototype.someStatic("John"));<commit_msg>-Fixed English<commit_after>/**
 * Created by lucavgobbi on 2015-10-12.
 */
"use strict";

/**
 * PersonAsClass
 * Defines a class (ES6)
 */
class PersonAsClass {
    constructor(options) {
        "use strict";
        this.name = options.name;
        this.weight = options.weight;
        this.height = options.height;
    }

    walk (steps) {
        // Suppose that each step can walk 1/3 of the height
        return steps * this.height / 3;
    }

    sleep () {
        return this.name + " slept for 1h";
    }

    toString () {
        "use strict";
        return this.name + " is " + this.weight + "m tall";
    }

    whoIAm () {
        return "I'm a class";
    }

    static someStatic (name) {
        return "I would be " + name;
    }
}

/**
 * personAsPrototype
 * Defines a prototype (ES5)
 */
var personAsPrototype = function (options) {
    this.name = options.name;
    this.weight = options.weight;
    this.height = options.height;
};

personAsPrototype.prototype.walk = function (steps) {
    // Suppose that each step can walk 1/3 of the height
    return steps * this.height / 3;
};

personAsPrototype.prototype.sleep = function () {
    return this.name + " slept for 1h";
};

personAsPrototype.prototype.toString = function () {
    return this.name + " is " + this.weight + "m tall";
};

personAsPrototype.prototype.whoIAm = function () {
    return "I'm a prototype";
};

personAsPrototype.someStatic = function (name) {
    return "I would be " + name;
};

// Instantiate PersonAsClass
var meAsClass = new PersonAsClass({ name: "Luca", height: 1.7, weight: 60 });
var youAsClass = new PersonAsClass({ name: "Luca", height: 1.78, weight: 71 });

// Instantiate PersonAsPrototype
var meAsPrototype = new personAsPrototype({ name: "Luca", height: 1.7, weight: 60 });
var youAsPrototype = new personAsPrototype({ name: "You", height: 1.78, weight: 71 });

console.log(meAsClass.whoIAm());
console.log(meAsClass.walk(5));
console.log(meAsClass.toString());
console.log(PersonAsClass.someStatic("John"));

console.log(youAsClass.whoIAm());
console.log(youAsClass.walk(5));
console.log(youAsClass.toString());
console.log(PersonAsClass.someStatic("John"));

console.log(meAsPrototype.whoIAm());
console.log(meAsPrototype.walk());
console.log(meAsPrototype.toString());
console.log(personAsPrototype.someStatic("John"));

console.log(youAsPrototype.whoIAm());
console.log(youAsPrototype.walk());
console.log(youAsPrototype.toString());
console.log(personAsPrototype.someStatic("John"));<|endoftext|>


<commit_before>describe("About Objects", function () {

  describe("Properties", function () {
    var meglomaniac;

    beforeEach(function () {
       meglomaniac = {  mastermind: "Joker", henchwoman: "Harley" };
    });

    it("should confirm objects are collections of properties", function () {
      expect(meglomaniac.mastermind).toBe(FILL_ME_IN);
    });

    it("should confirm that properties are case sensitive", function () {
      expect(meglomaniac.henchwoman).toBe(FILL_ME_IN);
      expect(meglomaniac.henchWoman).toBe(FILL_ME_IN);
    });
  });

  it("should know properties that are functions act like methods", function () {
    var meglomaniac = {
      mastermind : "Brain",
      henchman: "Pinky",
      battleCry: function (noOfBrains) {
        return "They are " + this.henchman + " and the" +
          Array(noOfBrains + 1).join(" " + this.mastermind);
      }
    };

    var battleCry = meglomaniac.battleCry(4);
    expect(FILL_ME_IN).toMatch(battleCry);
  });

  it("should confirm that when a function is attached to an object, 'this' refers to the object", function () {
    var currentDate = new Date()
    var currentYear = (currentDate.getFullYear());
    var meglomaniac = {
      mastermind: "James Wood",
      henchman: "Adam West",
      birthYear: 1970,
      calculateAge: function () {
        return currentYear - this.birthYear;
      }
    };

    expect(currentYear).toBe(FILL_ME_IN);
    expect(meglomaniac.calculateAge()).toBe(FILL_ME_IN);
  });

  describe("'in' keyword", function () {
    var meglomaniac;
    beforeEach(function () {
      meglomaniac = {
        mastermind: "The Monarch",
        henchwoman: "Dr Girlfriend",
        theBomb: true
      };
    });

    it("should have the bomb", function () {

      var hasBomb = "theBomb" in meglomaniac;

      expect(hasBomb).toBe(FILL_ME_IN);
    });

    it("should not have the detonator however", function () {

      var hasDetonator = "theDetonator" in meglomaniac;

      expect(hasDetonator).toBe(FILL_ME_IN);
    });
  });

  it("should know that properties can be added and deleted", function () {
    var meglomaniac = { mastermind : "Agent Smith", henchman: "Agent Smith" };

    expect("secretary" in meglomaniac).toBe(FILL_ME_IN);

    meglomaniac.secretary = "Agent Smith";
    expect("secretary" in meglomaniac).toBe(FILL_ME_IN);

    delete meglomaniac.henchman;
    expect("henchman" in meglomaniac).toBe(FILL_ME_IN);
  });

  it("should use prototype to add to all objects", function () {
    function Circle(radius)
    {
      this.radius = radius;
    }

    var simpleCircle = new Circle(10);
    var colouredCircle = new Circle(5);
    colouredCircle.colour = "red";

    expect(simpleCircle.colour).toBe(FILL_ME_IN);
    expect(colouredCircle.colour).toBe(FILL_ME_IN);

    Circle.prototype.describe = function () {
      return "This circle has a radius of: " + this.radius;
    };

    expect(simpleCircle.describe()).toBe(FILL_ME_IN);
    expect(colouredCircle.describe()).toBe(FILL_ME_IN);
  });
});
<commit_msg>Passed all tests in Thinking About Objects<commit_after>describe("About Objects", function () {

  describe("Properties", function () {
    var meglomaniac;

    beforeEach(function () {
       meglomaniac = {  mastermind: "Joker", henchwoman: "Harley" };
    });

    it("should confirm objects are collections of properties", function () {
      expect(meglomaniac.mastermind).toBe("Joker");
    });

    it("should confirm that properties are case sensitive", function () {
      expect(meglomaniac.henchwoman).toBe("Harley");
      expect(meglomaniac.henchWoman).toBe(undefined);
    });
  });

  it("should know properties that are functions act like methods", function () {
    var meglomaniac = {
      mastermind : "Brain",
      henchman: "Pinky",
      battleCry: function (noOfBrains) {
        return "They are " + this.henchman + " and the" +
          Array(noOfBrains + 1).join(" " + this.mastermind);
      }
    };

    var battleCry = meglomaniac.battleCry(4);
    expect("They are Pinky and the Brain Brain Brain Brain Brain").toMatch(battleCry);
  });

  it("should confirm that when a function is attached to an object, 'this' refers to the object", function () {
    var currentDate = new Date()
    var currentYear = (currentDate.getFullYear());
    var meglomaniac = {
      mastermind: "James Wood",
      henchman: "Adam West",
      birthYear: 1970,
      calculateAge: function () {
        return currentYear - this.birthYear;
      }
    };

    expect(currentYear).toBe(2015);
    expect(meglomaniac.calculateAge()).toBe(45);
  });

  describe("'in' keyword", function () {
    var meglomaniac;
    beforeEach(function () {
      meglomaniac = {
        mastermind: "The Monarch",
        henchwoman: "Dr Girlfriend",
        theBomb: true
      };
    });

    it("should have the bomb", function () {

      var hasBomb = "theBomb" in meglomaniac;

      expect(hasBomb).toBe(true);
    });

    it("should not have the detonator however", function () {

      var hasDetonator = "theDetonator" in meglomaniac;

      expect(hasDetonator).toBe(false);
    });
  });

  it("should know that properties can be added and deleted", function () {
    var meglomaniac = { mastermind : "Agent Smith", henchman: "Agent Smith" };

    expect("secretary" in meglomaniac).toBe(false);

    meglomaniac.secretary = "Agent Smith";
    expect("secretary" in meglomaniac).toBe(true);

    delete meglomaniac.henchman;
    expect("henchman" in meglomaniac).toBe(false);
  });

  it("should use prototype to add to all objects", function () {
    function Circle(radius)
    {
      this.radius = radius;
    }

    var simpleCircle = new Circle(10);
    var colouredCircle = new Circle(5);
    colouredCircle.colour = "red";

    expect(simpleCircle.colour).toBe(undefined);
    expect(colouredCircle.colour).toBe("red");

    Circle.prototype.describe = function () {
      return "This circle has a radius of: " + this.radius;
    };

    expect(simpleCircle.describe()).toBe("This circle has a radius of: 10");
    expect(colouredCircle.describe()).toBe("This circle has a radius of: 5");
  });
});
<|endoftext|>


<commit_before>document.observe('trisano:dom:loaded', function() {
  Trisano.Ajax.hookLiveSearchFields();
  Trisano.Ajax.hookUpdateLinks();
});

Element.addMethods({
  associatedSpinner: function(element) {
    var spinnerId = element.identify() + "_spinner";
    return $(spinnerId) || spinnerId;
  },

  associatedSearchResults: function(element) {
    var searchResultsId = element.identify() + "_search_results";
    return $(searchResultsId) || searchResultsId;
  }

});

Trisano.Ajax = {

  liveSearch: function(field) {
    if (!Object.isElement(field.associatedSearchResults())) {
      Element.extend(document.body).insert( { bottom: new Element('div', { id: field.associatedSearchResults(), 'class': 'autocomplete' }) } );
    }
    if (!Object.isElement(field.associatedSpinner())) {
      field.insert({ after: Trisano.Ajax.spinnerImg(field) });
    }
    new Ajax.Autocompleter(field, field.associatedSearchResults(), field.getAttribute('data-url'), {
                             indicator: field.associatedSpinner(),
                             method: 'get',
                             afterUpdateElement: Trisano.Ajax.callbackUpdateRequest
                           });
  },

  callbackUpdateRequest: function(field, selection) {
    new Ajax.Request(field.getAttribute('data-update-url'), {
                       method: 'post',
                       parameters: { place_entity_id: selection.id },
                       onCreate: function() { field.associatedSpinner().show(); },
                       onFailure: function() {
                         field.associatedSpinner().hide();
                         Trisano.flashError(i18n.t('operation_failed')).fade({delay: 3.0});
                       }
                     });
  },

  hookLiveSearchFields: function(selector) {
    var css = selector || "input[data-live-search='true']";
    $$(css).each(function(searchable) {
      Trisano.Ajax.liveSearch(searchable);
    });
  },

  hookUpdateLinks: function(selector) {
    var css = selector || 'a[data-update-link=true]';
    $$(css).each(function(link) {
      if (!Object.isElement(link.associatedSpinner())) {
        link.insert({ after: Trisano.Ajax.spinnerImg(link) });
      }
      link.observe('click', function(event) {
        new Ajax.Request(link.href, { method: 'post',
                                      onCreate: function() { link.associatedSpinner().show(); },
                                      onFailure: function() {
                                        link.associatedSpinner().hide();
                                        Trisano.flashError(i18n.t('operation_failed')).fade({delay: 4.0});
                                      } });
        event.stop();
      });
    });
  },

  spinnerImg: function(node) {
    return new Element('img', {
                         src: Trisano.url('images/redbox_spinner.gif'),
                         style: 'display:none',
                         id: node.associatedSpinner()
                       });
  }
};
<commit_msg>[Fixed #4910501] IE does not properly style elements added via JS when they are created with a certain class and then added to the DOM.  Modified code to 1) make the element, 2) add it to the page, and 3) give it the correct class.<commit_after>document.observe('trisano:dom:loaded', function() {
  Trisano.Ajax.hookLiveSearchFields();
  Trisano.Ajax.hookUpdateLinks();
});

Element.addMethods({
  associatedSpinner: function(element) {
    var spinnerId = element.identify() + "_spinner";
    return $(spinnerId) || spinnerId;
  },

  associatedSearchResults: function(element) {
    var searchResultsId = element.identify() + "_search_results";
    return $(searchResultsId) || searchResultsId;
  }

});

Trisano.Ajax = {

  liveSearch: function(field) {
    if (!Object.isElement(field.associatedSearchResults())) {
      var searchResults = new Element('div', { id: field.associatedSearchResults() });
      Element.extend(document.body).insert( { bottom: searchResults } );
      searchResults.addClassName('autocomplete');
    }
    if (!Object.isElement(field.associatedSpinner())) {
      field.insert({ after: Trisano.Ajax.spinnerImg(field) });
    }
    new Ajax.Autocompleter(field, field.associatedSearchResults(), field.getAttribute('data-url'), {
                             indicator: field.associatedSpinner(),
                             method: 'get',
                             afterUpdateElement: Trisano.Ajax.callbackUpdateRequest
                           });
  },

  callbackUpdateRequest: function(field, selection) {
    new Ajax.Request(field.getAttribute('data-update-url'), {
                       method: 'post',
                       parameters: { place_entity_id: selection.id },
                       onCreate: function() { field.associatedSpinner().show(); },
                       onFailure: function() {
                         field.associatedSpinner().hide();
                         Trisano.flashError(i18n.t('operation_failed')).fade({delay: 3.0});
                       }
                     });
  },

  hookLiveSearchFields: function(selector) {
    var css = selector || "input[data-live-search='true']";
    $$(css).each(function(searchable) {
      Trisano.Ajax.liveSearch(searchable);
    });
  },

  hookUpdateLinks: function(selector) {
    var css = selector || 'a[data-update-link=true]';
    $$(css).each(function(link) {
      if (!Object.isElement(link.associatedSpinner())) {
        link.insert({ after: Trisano.Ajax.spinnerImg(link) });
      }
      link.observe('click', function(event) {
        new Ajax.Request(link.href, { method: 'post',
                                      onCreate: function() { link.associatedSpinner().show(); },
                                      onFailure: function() {
                                        link.associatedSpinner().hide();
                                        Trisano.flashError(i18n.t('operation_failed')).fade({delay: 4.0});
                                      } });
        event.stop();
      });
    });
  },

  spinnerImg: function(node) {
    return new Element('img', {
                         src: Trisano.url('images/redbox_spinner.gif'),
                         style: 'display:none',
                         id: node.associatedSpinner()
                       });
  }
};
<|endoftext|>


<commit_before>'use strict';

var chai     = require('chai');
var promised = require('chai-as-promised');

chai.use(promised);
global.expect   = chai.expect;

exports.config = {

  // The timeout for each script run on the browser. This should be longer
  // than the maximum time your application needs to stabilize between tasks.
  allScriptsTimeout: 15000,

  // Capabilities to be passed to the webdriver instance.
  capabilities: {
    'browserName': 'chrome',
    'loggingPrefs': {
      'browser': 'ALL'
    }
  },

  // ----- What tests to run -----
  //
  // Spec patterns are relative to the location of the spec file. They may
  // include glob patterns.
  specs: [
    'admin/specs/admin-user-spec.js',
    'admin/specs/users-spec.js',
    'admin/specs/groups-spec.js',
    'admin/specs/system-spec.js',
    'admin/specs/authorizations-spec.js',
    'cockpit/specs/dashboard-spec.js',
    'tasklist/specs/tasklist-search-spec.js',
    'tasklist/specs/tasklist-sorting-spec.js'
  ],

  // A base URL for your application under test. Calls to protractor.get()
  // with relative paths will be prepended with this.
  baseUrl: 'http://localhost:8080',

  // ----- The test framework -----
  //
  // Jasmine is fully supported as a test and assertion framework.
  // Mocha has limited beta support. You will need to include your own
  // assertion framework if working with mocha.
  framework: 'mocha',

  // ----- Options to be passed to minijasminenode -----
  //
  // Options to be passed to Mocha-node.
  // See the full list at https://github.com/juliemr/minijasminenode

  mochaOpts: {
    timeout: 15000,
    colors: false,
    reporter: 'xunit-file',
    slow: 3000
  }
};
<commit_msg>chore(ci.config e2e): add filter spec to ci config<commit_after>'use strict';

var chai     = require('chai');
var promised = require('chai-as-promised');

chai.use(promised);
global.expect   = chai.expect;

exports.config = {

  // The timeout for each script run on the browser. This should be longer
  // than the maximum time your application needs to stabilize between tasks.
  allScriptsTimeout: 15000,

  // Capabilities to be passed to the webdriver instance.
  capabilities: {
    'browserName': 'chrome',
    'loggingPrefs': {
      'browser': 'ALL'
    }
  },

  // ----- What tests to run -----
  //
  // Spec patterns are relative to the location of the spec file. They may
  // include glob patterns.
  specs: [
    'admin/specs/admin-user-spec.js',
    'admin/specs/users-spec.js',
    'admin/specs/groups-spec.js',
    'admin/specs/system-spec.js',
    'admin/specs/authorizations-spec.js',
    'cockpit/specs/dashboard-spec.js',
    'tasklist/specs/filter-spec.js',
    'tasklist/specs/tasklist-search-spec.js',
    'tasklist/specs/tasklist-sorting-spec.js'
  ],

  // A base URL for your application under test. Calls to protractor.get()
  // with relative paths will be prepended with this.
  baseUrl: 'http://localhost:8080',

  // ----- The test framework -----
  //
  // Jasmine is fully supported as a test and assertion framework.
  // Mocha has limited beta support. You will need to include your own
  // assertion framework if working with mocha.
  framework: 'mocha',

  // ----- Options to be passed to minijasminenode -----
  //
  // Options to be passed to Mocha-node.
  // See the full list at https://github.com/juliemr/minijasminenode

  mochaOpts: {
    timeout: 15000,
    colors: false,
    reporter: 'xunit-file',
    slow: 3000
  }
};
<|endoftext|>


<commit_before>"use strict";

angular.module("subutai.settings-advanced.controller", [])
	.controller("SettingsAdvancedCtrl", SettingsAdvancedCtrl)
	.config(['terminalConfigurationProvider', function (terminalConfigurationProvider) {
		terminalConfigurationProvider.config('modern').allowTypingWriteDisplaying = false;
		terminalConfigurationProvider.config('modern').outputDelay = 80;
	}]);

SettingsAdvancedCtrl.$inject = ["$scope", "SettingsAdvancedSrv", "SweetAlert", "$sce", "cfpLoadingBar"];

function SettingsAdvancedCtrl($scope, SettingsAdvancedSrv, SweetAlert, $sce, cfpLoadingBar) {

	cfpLoadingBar.start();
	angular.element(document).ready(function () {
		cfpLoadingBar.complete();
	});

	var vm = this;
	vm.config = {};
	vm.activeTab = "karafconsole";
	vm.getConfig = getConfig;
	vm.updateConfig = updateConfig;
	vm.saveLogs = saveLogs;
	vm.renderHtml = renderHtml;

	//Console UI
	$scope.theme = 'modern';
	console.log($scope);
	setTimeout(function () {
		$scope.$broadcast('terminal-output', {
			output: true,
			text: [
				'Karaf Subutai',
			],
			breakLine: true
		});
		$scope.prompt.path('/');
		$scope.prompt.user('karaf');

		/*$scope.results.splice(0, $scope.results.length);
		$scope.$$phase || $scope.$apply();*/

		$scope.$apply();

		$('.terminal-viewport').perfectScrollbar();
	}, 100);

	$scope.session = {
		commands: [],
		output: [],
		$scope:$scope
	};

	$scope.$watchCollection(function () { return $scope.session.commands; }, function (n) {
		for (var i = 0; i < n.length; i++) {
			$scope.$broadcast('terminal-command', n[i]);
		}
		$scope.session.commands.splice(0, $scope.session.commands.length);
		$scope.$$phase || $scope.$apply();
	});

	$scope.$watchCollection(function () { return $scope.session.output; }, function (n) {
		for (var i = 0; i < n.length; i++) {
			$scope.$broadcast('terminal-output', n[i]);
		}
		$scope.session.output.splice(0, $scope.session.output.length);
		$scope.$$phase || $scope.$apply();
	});

	$scope.$on('terminal-input', function (e, consoleInput) {
		var output = [];
		$scope.outputDelay = 0;

		$scope.showPrompt = false;

		var cmd = consoleInput[0];

		try {
			if (cmd.command =='clear') {
				$scope.results.splice(0, $scope.results.length);
				$scope.$$phase || $scope.$apply();
				return;
			}

			SettingsAdvancedSrv.sendCommand(cmd.command).success(function(data){
				if(data.length > 0) {
					output = data.split('\r');
				}

				$scope.session.output.push(
					{ output: true, text: output, breakLine: true }
				);
			}).error(function (data) {
				$scope.session.output.push({ output: true, breakLine: true, text: [data] });
			});

		} catch (err) {
			$scope.session.output.push({ output: true, breakLine: true, text: [err.message] });
		}
	});
	//END Console UI

	function getConfig() {
		$('.js-karaflogs-load-screen').addClass('lololo').show();
		SettingsAdvancedSrv.getConfig().success(function (data) {
			$('.js-karaflogs-load-screen').hide();
			vm.config = data;
		}).error(function(error){
			SweetAlert.swal("ERROR!", error, "error");
			$('.js-karaflogs-load-screen').hide();
		});
	}
	//getConfig();

	function updateConfig() {
		SettingsAdvancedSrv.updateConfig(vm.config).success(function (data) {
			SweetAlert.swal("Success!", "Your settings were saved.", "success");
		}).error(function (error) {
			SweetAlert.swal("ERROR!", error, "error");
		});
	}

	function saveLogs() {
		var text = vm.config.karafLogs;
		var blob = new Blob([text], {type: "text/plain;charset=utf-8"});
		saveAs(blob, "karaflogs" + moment().format('YYYY-MM-DD HH:mm:ss') + ".txt");
	}

	vm.logLevel = 'INFO';
	function renderHtml(html_code) {
		//initHighlighting();
		if(html_code && html_code.length > 0) {
			var html_code_array = html_code.match(/[^\r\n]+/g);
			var temp = false;
			var stingColor = false;
			var spliceIdx = 0;
			for(var i = 0; i < html_code_array.length; i++) {
				if(vm.logLevel == 'all' || html_code_array[i].includes(vm.logLevel)) {
					if(html_code_array[i].includes('ERROR') || html_code_array[i].includes('WARN')) {
						if(html_code_array[i].includes('WARN')) {
							stingColor = '#f1c40f';
						} else if(html_code_array[i].includes('ERROR')) {
							stingColor = '#c1272d';
						}
						html_code_array[i] = '' + html_code_array[i] + '';
					} else {
						stingColor = false;
					}
					temp = checkNextString(i, html_code_array, stingColor);
					html_code_array = temp.array;
					i = temp.index;
				} else {
					html_code_array.splice(i - spliceIdx++, 1);
					//delete html_code_array[i];
				}
			}
			console.log(html_code_array);
			var codeBlock = document.getElementById('js-highlight-block');
			codeBlock.scrollTop = codeBlock.scrollHeight;
			return $sce.trustAsHtml(html_code_array.join('\n'));
		} else {
			return $sce.trustAsHtml(html_code);
		}
	}

	function checkNextString(index, stringArray, color) {
		if(color == undefined || color == null) color = false;
		if(!parseDate(stringArray[index+1])) {
			if(color) {
				stringArray[index] = '' + stringArray[index+1] + '';
			}
			return checkNextString(index+1, stringArray, color);
		} else {
			return {"index": index, "array": stringArray};
		}
	}

	function parseDate(str) {
		var m = str.match(/[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1]) (2[0-3]|[01][0-9]):[0-5][0-9].*/);
		return (m) ? true : false;
	}

	function initHighlighting() {
		$('pre code').each(function(i, block) {
			hljs.highlightBlock(block);
		});
		var codeBlock = document.getElementById('js-highlight-block');
		codeBlock.scrollTop = codeBlock.scrollHeight;
	}
}
<commit_msg>#252 splice idx changed to idx operation<commit_after>"use strict";

angular.module("subutai.settings-advanced.controller", [])
	.controller("SettingsAdvancedCtrl", SettingsAdvancedCtrl)
	.config(['terminalConfigurationProvider', function (terminalConfigurationProvider) {
		terminalConfigurationProvider.config('modern').allowTypingWriteDisplaying = false;
		terminalConfigurationProvider.config('modern').outputDelay = 80;
	}]);

SettingsAdvancedCtrl.$inject = ["$scope", "SettingsAdvancedSrv", "SweetAlert", "$sce", "cfpLoadingBar"];

function SettingsAdvancedCtrl($scope, SettingsAdvancedSrv, SweetAlert, $sce, cfpLoadingBar) {

	cfpLoadingBar.start();
	angular.element(document).ready(function () {
		cfpLoadingBar.complete();
	});

	var vm = this;
	vm.config = {};
	vm.activeTab = "karafconsole";
	vm.getConfig = getConfig;
	vm.updateConfig = updateConfig;
	vm.saveLogs = saveLogs;
	vm.renderHtml = renderHtml;

	//Console UI
	$scope.theme = 'modern';
	console.log($scope);
	setTimeout(function () {
		$scope.$broadcast('terminal-output', {
			output: true,
			text: [
				'Karaf Subutai',
			],
			breakLine: true
		});
		$scope.prompt.path('/');
		$scope.prompt.user('karaf');

		/*$scope.results.splice(0, $scope.results.length);
		$scope.$$phase || $scope.$apply();*/

		$scope.$apply();

		$('.terminal-viewport').perfectScrollbar();
	}, 100);

	$scope.session = {
		commands: [],
		output: [],
		$scope:$scope
	};

	$scope.$watchCollection(function () { return $scope.session.commands; }, function (n) {
		for (var i = 0; i < n.length; i++) {
			$scope.$broadcast('terminal-command', n[i]);
		}
		$scope.session.commands.splice(0, $scope.session.commands.length);
		$scope.$$phase || $scope.$apply();
	});

	$scope.$watchCollection(function () { return $scope.session.output; }, function (n) {
		for (var i = 0; i < n.length; i++) {
			$scope.$broadcast('terminal-output', n[i]);
		}
		$scope.session.output.splice(0, $scope.session.output.length);
		$scope.$$phase || $scope.$apply();
	});

	$scope.$on('terminal-input', function (e, consoleInput) {
		var output = [];
		$scope.outputDelay = 0;

		$scope.showPrompt = false;

		var cmd = consoleInput[0];

		try {
			if (cmd.command =='clear') {
				$scope.results.splice(0, $scope.results.length);
				$scope.$$phase || $scope.$apply();
				return;
			}

			SettingsAdvancedSrv.sendCommand(cmd.command).success(function(data){
				if(data.length > 0) {
					output = data.split('\r');
				}

				$scope.session.output.push(
					{ output: true, text: output, breakLine: true }
				);
			}).error(function (data) {
				$scope.session.output.push({ output: true, breakLine: true, text: [data] });
			});

		} catch (err) {
			$scope.session.output.push({ output: true, breakLine: true, text: [err.message] });
		}
	});
	//END Console UI

	function getConfig() {
		$('.js-karaflogs-load-screen').addClass('lololo').show();
		SettingsAdvancedSrv.getConfig().success(function (data) {
			$('.js-karaflogs-load-screen').hide();
			vm.config = data;
		}).error(function(error){
			SweetAlert.swal("ERROR!", error, "error");
			$('.js-karaflogs-load-screen').hide();
		});
	}
	//getConfig();

	function updateConfig() {
		SettingsAdvancedSrv.updateConfig(vm.config).success(function (data) {
			SweetAlert.swal("Success!", "Your settings were saved.", "success");
		}).error(function (error) {
			SweetAlert.swal("ERROR!", error, "error");
		});
	}

	function saveLogs() {
		var text = vm.config.karafLogs;
		var blob = new Blob([text], {type: "text/plain;charset=utf-8"});
		saveAs(blob, "karaflogs" + moment().format('YYYY-MM-DD HH:mm:ss') + ".txt");
	}

	vm.logLevel = 'INFO';
	function renderHtml(html_code) {
		//initHighlighting();
		if(html_code && html_code.length > 0) {
			var html_code_array = html_code.match(/[^\r\n]+/g);
			var temp = false;
			var stingColor = false;
			for(var i = 0; i < html_code_array.length; i++) {
				if(vm.logLevel == 'all' || html_code_array[i].includes(vm.logLevel)) {
					if(html_code_array[i].includes('ERROR') || html_code_array[i].includes('WARN')) {
						if(html_code_array[i].includes('WARN')) {
							stingColor = '#f1c40f';
						} else if(html_code_array[i].includes('ERROR')) {
							stingColor = '#c1272d';
						}
						html_code_array[i] = '' + html_code_array[i] + '';
					} else {
						stingColor = false;
					}
					temp = checkNextString(i, html_code_array, stingColor);
					html_code_array = temp.array;
					i = temp.index;
				} else {
					html_code_array.splice(i, 1);
					i--;
				}
			}
			console.log(html_code_array);
			var codeBlock = document.getElementById('js-highlight-block');
			codeBlock.scrollTop = codeBlock.scrollHeight;
			return $sce.trustAsHtml(html_code_array.join('\n'));
		} else {
			return $sce.trustAsHtml(html_code);
		}
	}

	function checkNextString(index, stringArray, color) {
		if(color == undefined || color == null) color = false;
		if(!parseDate(stringArray[index+1])) {
			if(color) {
				stringArray[index] = '' + stringArray[index+1] + '';
			}
			return checkNextString(index+1, stringArray, color);
		} else {
			return {"index": index, "array": stringArray};
		}
	}

	function parseDate(str) {
		var m = str.match(/[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1]) (2[0-3]|[01][0-9]):[0-5][0-9].*/);
		return (m) ? true : false;
	}

	function initHighlighting() {
		$('pre code').each(function(i, block) {
			hljs.highlightBlock(block);
		});
		var codeBlock = document.getElementById('js-highlight-block');
		codeBlock.scrollTop = codeBlock.scrollHeight;
	}
}
<|endoftext|>


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

var debug = require('cog/logger')('rtc/cleanup');

var CANNOT_CLOSE_STATES = [
  'closed'
];

var EVENTNAMES = [
  'addstream',
  'datachannel',
  'icecandidate',
  'iceconnectionstatechange',
  'negotiationneeded',
  'removestream',
  'signalingstatechange'
];

/**
  ### rtc-tools/cleanup

  ```
  cleanup(pc)
  ```

  The `cleanup` function is used to ensure that a peer connection is properly
  closed and ready to be cleaned up by the browser.

**/
module.exports = function(pc) {
  // see if we can close the connection
  var currentState = pc.iceConnectionState;
  var canClose = CANNOT_CLOSE_STATES.indexOf(currentState) < 0;

  if (canClose) {
    debug('attempting connection close, current state: '+ pc.iceConnectionState);
    pc.close();
  }

  // remove the event listeners
  // after a short delay giving the connection time to trigger
  // close and iceconnectionstatechange events
  setTimeout(function() {
    EVENTNAMES.forEach(function(evtName) {
      if (pc['on' + evtName]) {
        pc['on' + evtName] = null;
      }
    });
  }, 100);
};
<commit_msg>Cleanup event handlers in two phases - before close and after close<commit_after>/* jshint node: true */
'use strict';

var debug = require('cog/logger')('rtc/cleanup');

var CANNOT_CLOSE_STATES = [
  'closed'
];

var EVENTS_DECOUPLE_BC = [
  'addstream',
  'datachannel',
  'icecandidate',
  'negotiationneeded',
  'removestream',
  'signalingstatechange'
];

var EVENTS_DECOUPLE_AC = [
  'iceconnectionstatechange'
];

/**
  ### rtc-tools/cleanup

  ```
  cleanup(pc)
  ```

  The `cleanup` function is used to ensure that a peer connection is properly
  closed and ready to be cleaned up by the browser.

**/
module.exports = function(pc) {
  // see if we can close the connection
  var currentState = pc.iceConnectionState;
  var canClose = CANNOT_CLOSE_STATES.indexOf(currentState) < 0;

  function decouple(events) {
    events.forEach(function(evtName) {
      if (pc['on' + evtName]) {
        pc['on' + evtName] = null;
      }
    });
  }

  // decouple "before close" events
  decouple(EVENTS_DECOUPLE_BC);

  if (canClose) {
    debug('attempting connection close, current state: '+ pc.iceConnectionState);
    pc.close();
  }

  // remove the event listeners
  // after a short delay giving the connection time to trigger
  // close and iceconnectionstatechange events
  setTimeout(function() {
    decouple(EVENTS_DECOUPLE_AC);
  }, 100);
};
<|endoftext|>


<commit_before>/**
 * Created by kdban on 3/26/2016.
 */

var InterpolationBuffer = require('polyball/client/synchronizer/InterpolationBuffer');

/**
 * Interpolates from past snapshot state smoothly to current times.  Results in increase delay but increase smoothness.
 *
 * @param {Object} config
 * @property {Number} config.receiptInterval - The interval between which new frames ar *ideally* added.
 * @constructor
 */
var Interpolator = function (config) {

    var receiptInterval = config.receiptInterval;  // jshint ignore:line

    var buffer = new InterpolationBuffer();

    this.addPastServerState = function(receivedTime, players) {
        if (players != null) {
            buffer.addNewFrame({
                receivedTime: receivedTime,
                playerStates: players
            });
        }
    };

    /**
     * Interpolate local states based on past remote states.
     *
     * @param {Model} model - the Model whose remote paddles should be interpolated
     * TODO @param currentTime
     */
    this.interpolateState = function (model) {
        var mostRecent = buffer.getMostRecentFrame();

        if (mostRecent != null && mostRecent.playerStates != null) {
            mostRecent.playerStates.forEach(function (playerState) {
                var remotePlayer = model.playersContainer.getPlayer(playerState.id);
                var remotePaddle = remotePlayer ? remotePlayer.paddle : null;

                if (playerState.id !== model.getLocalClientID() && remotePlayer != null && remotePaddle != null) {
                    remotePaddle.body.state.pos.x = playerState.paddleConfig.body.state.pos.x;
                    remotePaddle.body.state.pos.y = playerState.paddleConfig.body.state.pos.y;

                    remotePaddle.body.state.vel.x = playerState.paddleConfig.body.state.vel.x;
                    remotePaddle.body.state.vel.y = playerState.paddleConfig.body.state.vel.y;
                }
            });
        }
    };

};

module.exports = Interpolator;<commit_msg>Fixed null body exception on client during round intermission. Closes #263<commit_after>/**
 * Created by kdban on 3/26/2016.
 */

var InterpolationBuffer = require('polyball/client/synchronizer/InterpolationBuffer');

/**
 * Interpolates from past snapshot state smoothly to current times.  Results in increase delay but increase smoothness.
 *
 * @param {Object} config
 * @property {Number} config.receiptInterval - The interval between which new frames ar *ideally* added.
 * @constructor
 */
var Interpolator = function (config) {

    var receiptInterval = config.receiptInterval;  // jshint ignore:line

    var buffer = new InterpolationBuffer();

    this.addPastServerState = function(receivedTime, players) {
        if (players != null) {
            buffer.addNewFrame({
                receivedTime: receivedTime,
                playerStates: players
            });
        }
    };

    /**
     * Interpolate local states based on past remote states.
     *
     * @param {Model} model - the Model whose remote paddles should be interpolated
     * TODO @param currentTime
     */
    this.interpolateState = function (model) {
        var mostRecent = buffer.getMostRecentFrame();

        if (mostRecent != null && mostRecent.playerStates != null) {
            mostRecent.playerStates.forEach(function (playerState) {
                var remotePlayer = model.playersContainer.getPlayer(playerState.id);
                var remotePaddle = remotePlayer ? remotePlayer.paddle : null;

                if (playerState.id !== model.getLocalClientID() && remotePlayer != null &&
                    remotePaddle != null && playerState.paddleConfig) {
                    remotePaddle.body.state.pos.x = playerState.paddleConfig.body.state.pos.x;
                    remotePaddle.body.state.pos.y = playerState.paddleConfig.body.state.pos.y;

                    remotePaddle.body.state.vel.x = playerState.paddleConfig.body.state.vel.x;
                    remotePaddle.body.state.vel.y = playerState.paddleConfig.body.state.vel.y;
                }
            });
        }
    };

};

module.exports = Interpolator;<|endoftext|>