<!DOCTYPE html>
<html>
<head>
<title></title>
<style>

</style>
<script src="http://closure-library.googlecode.com/svn/trunk/closure/goog/base.js"></script>
<script src="cr.js"></script>
<script src="cr/event_target.js"></script>
<script>

goog.require('goog.testing.jsunit');

</script>

</head>
<body>

<script>

const EventTarget = cr.EventTarget;

function testDefineProperty() {
  var obj = new EventTarget;
  cr.defineProperty(obj, 'test');

  obj.test = 1;
  assertEquals(1, obj.test);
  assertEquals(1, obj.test_);
}

function testDefinePropertyOnClass() {
  function C() {}
  C.prototype = {
    __proto__: EventTarget.prototype
  };

  cr.defineProperty(C, 'test');

  var obj = new C;
  assertUndefined(obj.test);

  obj.test = 1;
  assertEquals(1, obj.test);
  assertEquals(1, obj.test_);
}

function testDefinePropertyWithSetter() {
  var obj = new EventTarget;

  var hit = false;
  function onTestSet(value, oldValue) {
    assertEquals(obj, this);
    assertEquals(2, this.test);
    assertUndefined(oldValue);
    assertEquals(2, value);
    hit = true;
  }
  cr.defineProperty(obj, 'test', cr.PropertyKind.JS, onTestSet); 
  obj.test = 2;
  assertTrue(hit);
}

function testDefinePropertyEvent() {
  var obj = new EventTarget;
  cr.defineProperty(obj, 'test');
  obj.test = 1;

  var count = 0;
  function f(e) {
    assertEquals('testChange', e.type);
    assertEquals('test', e.propertyName);
    assertEquals(1, e.oldValue);
    assertEquals(2, e.newValue);
    count++;
  }

  obj.addEventListener('testChange', f);
  obj.test = 2;
  assertEquals(2, obj.test);
  assertEquals('Should have called the property change listener', 1, count);

  obj.test = 2;
  assertEquals(1, count);
}

function testDefinePropertyEventWithDefault() {
  var obj = new EventTarget;
  cr.defineProperty(obj, 'test', cr.PropertyKind.JS);

  var count = 0;
  function f(e) {
    assertEquals('testChange', e.type);
    assertEquals('test', e.propertyName);
    assertUndefined(e.oldValue);
    assertEquals(2, e.newValue);
    count++;
  }

  obj.addEventListener('testChange', f);

  obj.test = undefined;
  assertEquals('Should not have called the property change listener', 0, count);

  obj.test = 2;
  assertEquals(2, obj.test);
  assertEquals('Should have called the property change listener', 1, count);

  obj.test = 2;
  assertEquals(1, count);
}

function testDefinePropertyAttr() {
  var obj = document.createElement('div');
  cr.defineProperty(obj, 'test', cr.PropertyKind.ATTR);

  obj.test = 'a';
  assertEquals('a', obj.test);
  assertEquals('a', obj.getAttribute('test'));
}

function testDefinePropertyAttrOnClass() {
  var obj = document.createElement('button');
  cr.defineProperty(HTMLButtonElement, 'test', cr.PropertyKind.ATTR);

  assertEquals(null, obj.test);

  obj.test = 'a';
  assertEquals('a', obj.test);
  assertEquals('a', obj.getAttribute('test'));
}

function testDefinePropertyAttrWithSetter() {
  var obj = document.createElement('div');

  var hit = false;
  function onTestSet(value, oldValue) {
    assertEquals(obj, this);
    assertEquals(null, oldValue);
    assertEquals('b', value);
    assertEquals('b', this.test);
    hit = true;
  }
  cr.defineProperty(obj, 'test', cr.PropertyKind.ATTR, onTestSet);
  obj.test = 'b';
  assertTrue(hit);
}

function testDefinePropertyAttrEvent() {
  var obj = document.createElement('div');
  cr.defineProperty(obj, 'test', cr.PropertyKind.ATTR);

  var count = 0;
  function f(e) {
    assertEquals('testChange', e.type);
    assertEquals('test', e.propertyName);
    assertEquals(null, e.oldValue);
    assertEquals('b', e.newValue);
    count++;
  }

  obj.addEventListener('testChange', f);

  obj.test = null;
  assertEquals('Should not have called the property change listener', 0, count);

  obj.test = 'b';
  assertEquals('b', obj.test);
  assertEquals('Should have called the property change listener', 1, count);

  obj.test = 'b';
  assertEquals(1, count);
}

function testDefinePropertyBoolAttr() {
  var obj = document.createElement('div');
  cr.defineProperty(obj, 'test', cr.PropertyKind.BOOL_ATTR);

  assertFalse(obj.test);
  assertFalse(obj.hasAttribute('test'));

  obj.test = true;
  assertTrue(obj.test);
  assertTrue(obj.hasAttribute('test'));

  obj.test = false;
  assertFalse(obj.test);
  assertFalse(obj.hasAttribute('test'));
}

function testDefinePropertyBoolAttrEvent() {
  var obj = document.createElement('div');
  cr.defineProperty(obj, 'test', cr.PropertyKind.BOOL_ATTR);

  var count = 0;
  function f(e) {
    assertEquals('testChange', e.type);
    assertEquals('test', e.propertyName);
    assertEquals(false, e.oldValue);
    assertEquals(true, e.newValue);
    count++;
  }

  obj.addEventListener('testChange', f);
  obj.test = true;
  assertTrue(obj.test);
  assertEquals('Should have called the property change listener', 1, count);

  obj.test = true;
  assertEquals(1, count);
}

function testDefinePropertyBoolAttrEvent() {
  var obj = document.createElement('div');
  var hit = false;
  function onTestSet(value, oldValue) {
    assertEquals(obj, this);
    assertTrue(this.test);
    assertFalse(oldValue);
    assertTrue(value);
    hit = true;
  }
  cr.defineProperty(obj, 'test', cr.PropertyKind.BOOL_ATTR, onTestSet);
  obj.test = true;
  assertTrue(hit);
}

function testAddSingletonGetter() {
  function Foo() {};
  cr.addSingletonGetter(Foo);

  assertNotNull('Should add get instance function', Foo.getInstance);

  var x = Foo.getInstance();
  assertNotNull('Should successfully create an object', x);

  var y = Foo.getInstance();
  assertEquals('Should return the same object', x, y);

  delete Foo.instance_;

  var z = Foo.getInstance();
  assertNotNull('Should work after clearing for testing', z);

  assertNotEquals('Should return a different object after clearing for testing',
      x, z);
}

function testWithDoc() {
  var d = {};

  assertEquals(document, cr.doc);

  cr.withDoc(d, function() {
    assertEquals(d, cr.doc);
  });

  assertEquals(document, cr.doc);
}

function testDefineWithGetter() {
  var v = 0;
  cr.define('foo', function() {
    return {
      get v() {
        return v;
      }
    }
  });

  assertEquals(0, foo.v);

  v = 1;
  assertEquals(1, foo.v);
}

</script>

</body>
</html>