// ========================================================================== // Project: SproutCore - JavaScript Application Framework // Copyright: ©2006-2011 Strobe Inc. and contributors. // ©2008-2011 Apple Inc. All rights reserved. // License: Licensed under MIT license (see license.js) // ========================================================================== /*global module, test, equals */

var family, grandma, momma, child1, child2, child3, child4, child5, observerFiredCount, observer2FiredCount; module(“SC.Observable - Observing with @each”, {

setup: function () {
  momma = SC.Object.create({ children: [] });
  grandma = SC.Object.create({ momma: momma });
  family = SC.Object.create({
    grandma: grandma,
    eachCallback: function () {
      observerFiredCount++;
    },
    childrenCallback: function () {
      observer2FiredCount++;
    }
  });

  child1 = SC.Object.create({ name: "Bartholomew" });
  child2 = SC.Object.create({ name: "Agnes" });
  child3 = SC.Object.create({ name: "Dan" });
  child4 = SC.Object.create({ name: "Nancy" });
  child5 = SC.Object.create({ name: "Constance" });

  momma.set('children', [child1, child2, child3]);

  observerFiredCount = 0;
  observer2FiredCount = 0;
},

teardown: function () {
  family.destroy();
  grandma.destroy();
  momma.destroy();
  child1.destroy();
  child2.destroy();
  child3.destroy();
  child4.destroy();
  child5.destroy();

  family = grandma = momma = child1 = child2 = child3 = child4 = child5 = null;
}

});

test(“chained observers on enumerable properties are triggered when the observed property of any item changes”, function () {

family.addObserver('grandma.momma.children.@each.name', family, family.eachCallback);
family.addObserver('grandma.momma.children', family, family.childrenCallback);

observerFiredCount = 0;
SC.run(function () { momma.get('children').setEach('name', 'Juan'); });
equals(observerFiredCount, 3, "observer fired after changing child names");

observerFiredCount = 0;
SC.run(function () { momma.children.pushObject(child4); });
equals(observerFiredCount, 1, "observer fired after adding a new item");

observerFiredCount = 0;
SC.run(function () { child4.set('name', "Herbert"); });
equals(observerFiredCount, 1, "observer fired after changing property on new object");

var oldChildren = momma.get('children');
momma.set('children', []);
observerFiredCount = 0;
SC.run(function () {
  oldChildren.pushObject(child5);
  oldChildren.objectAt(0).set('name', "Hanna");
});
equals(observerFiredCount, 0, "observer did not fire after changing removed array and property on an object in removed array");
equals(observer2FiredCount, 1, "children observer did fire only once by replacing children with empty array");

observerFiredCount = 0;
observer2FiredCount = 0;
SC.run(function () { child1.set('name', "Hanna"); });
equals(observerFiredCount, 0, "observer did not fire after changing property on a removed object");

observerFiredCount = 0;
SC.run(function () { momma.set('children', [child1, child2, child3, child4]); });
equals(observerFiredCount, 0, "@each observer did not fire after replacing children with 4 objects");
equals(observer2FiredCount, 1, "children observer did fire only once after replacing children with 4 objects");

observerFiredCount = 0;
observer2FiredCount = 0;
SC.run(function () { momma.set('children', []); });
equals(observerFiredCount, 0, "@each observer did not fire after replacing children with empty array");
equals(observer2FiredCount, 1, "children observer did fire only once after replacing children with empty array");

observerFiredCount = 0;
SC.run(function () { momma.get('children').pushObjects([child1, child2, child3, child4]); });
equals(observerFiredCount, 1, "observer did fire only once after adding 4 objects");

observerFiredCount = 0;
SC.run(function () { momma.get('children').removeObjects([child1, child2]); });
equals(observerFiredCount, 1, "observer did fire once after removing 2 of 4 objects");

observerFiredCount = 0;
SC.run(function () { momma.get('children').removeObjects([child3, child4]); });
equals(observerFiredCount, 1, "observer did fire once after removing all objects");

// New grandma.
observerFiredCount = 0;
grandma.destroy();
grandma = SC.Object.create({ momma: momma });
family.set('grandma', grandma);
equals(observerFiredCount, 0, "observer did not fire after replacing dear old grandma");

oldChildren = momma.get('children');
momma.destroy();
momma = SC.Object.create({ children: oldChildren });
grandma.set('momma', momma);
equals(observerFiredCount, 0, "observer did not fire after replacing dear old momma");

// Clean up.
family.removeObserver('grandma.momma.children.@each.name', family, family.eachCallback);

});

test(“observer cleanup”, function () {

family.addObserver('grandma.momma.children.@each.name', family, family.eachCallback);
family.removeObserver('grandma.momma.children.@each.name', family, family.eachCallback);

// Clean up.
equals(family._kvo_observed_keys.length, 0, "family has no observed keys");
equals(grandma._kvo_observed_keys.length, 0, "grandma has no observed keys");
equals(momma._kvo_observed_keys.length, 0, "momma has no observed keys: %@".fmt(momma._kvo_observed_keys.toArray()));
equals(momma.children._kvo_observed_keys.length, 0, "momma.children has no observed keys: %@".fmt(momma.children._kvo_observed_keys.toArray()));
equals(child1._kvo_observed_keys.length, 0, "child1 has no observed keys");

});

test(“content observers are removed correctly”, function () {

var child1 = SC.Object.create({ name: "Bartholomew", age: 15 });
var child2 = SC.Object.create({ name: "Agnes", age: 12 });
var children = [child1, child2];

var observerFiredCount = 0;
var observerFunc = function () { observerFiredCount++; };

children.addObserver('@each.name', this, observerFunc);
children.removeObserver('@each.name', this, observerFunc);
observerFiredCount = 0;
SC.run(function () { children.setEach('name', "Hanna"); });
equals(observerFiredCount, 0, "name observer did not fire after it was removed");

children.addObserver('@each.age', this, observerFunc);
children.removeObserver('@each.age', this, observerFunc);
observerFiredCount = 0;
SC.run(function () { children.setEach('age', 14); });
equals(observerFiredCount, 0, "age observer did not fire after it was removed");

});