QUnit.test('`objectAt` returns correct object', function() { let arr = ['first', 'second', 'third', 'fourth']; equal(objectAt(arr, 2), 'third'); equal(objectAt(arr, 4), undefined); }); testBoth('should be clear caches for computed properties that have dependent keys on arrays that are changed after object initialization', function(get, set) { var obj = EmberObject.extend({ init() { this._super(...arguments); set(this, 'resources', emberA()); }, common: computed('*****@*****.**', function() { return get(objectAt(get(this, 'resources'), 0), 'common'); }) }).create(); get(obj, 'resources').pushObject(EmberObject.create({ common: 'HI!' })); equal('HI!', get(obj, 'common')); set(objectAt(get(obj, 'resources'), 0), 'common', 'BYE!'); equal('BYE!', get(obj, 'common')); }); testBoth('observers that contain @each in the path should fire only once the first time they are accessed', function(get, set) { var count = 0; var obj = EmberObject.extend({ init() { this._super(...arguments);
didCount++; }); } testBoth('unwatching a computed property - regular get/set', function(get, set) { var obj = {}; defineProperty(obj, 'foo', computed(function(keyName, value) { if (value !== undefined) { this.__foo = value; } return this.__foo; })); addListeners(obj, 'foo'); watch(obj, 'foo'); set(obj, 'foo', 'bar'); equal(willCount, 1, 'should have invoked willCount'); equal(didCount, 1, 'should have invoked didCount'); unwatch(obj, 'foo'); willCount = didCount = 0; set(obj, 'foo', 'BAZ'); equal(willCount, 0, 'should NOT have invoked willCount'); equal(didCount, 0, 'should NOT have invoked didCount'); }); testBoth('unwatching a regular property - regular get/set', function(get, set) {
import { observer } from 'ember-metal/mixin'; import run from 'ember-metal/run_loop'; import { testBoth } from 'ember-metal/tests/props_helper'; import EmberObject from 'ember-runtime/system/object'; QUnit.module('EmberObject observer'); testBoth('observer on class', function(get, set) { var MyClass = EmberObject.extend({ count: 0, foo: observer('bar', function() { set(this, 'count', get(this, 'count') + 1); }) }); var obj = new MyClass(); equal(get(obj, 'count'), 0, 'should not invoke observer immediately'); set(obj, 'bar', 'BAZ'); equal(get(obj, 'count'), 1, 'should invoke observer after change'); }); testBoth('observer on subclass', function(get, set) { var MyClass = EmberObject.extend({ count: 0, foo: observer('bar', function() {
import { defineProperty } from 'ember-metal/properties'; import EmberObject from 'ember-runtime/system/object'; import { testBoth } from 'ember-metal/tests/props_helper'; QUnit.module('CP macros'); testBoth('Ember.computed.empty', function (get, set) { var obj = EmberObject.extend({ bestLannister: null, lannisters: null, bestLannisterUnspecified: empty('bestLannister'), noLannistersKnown: empty('lannisters') }).create({ lannisters: Ember.A([]) }); equal(get(obj, 'bestLannisterUnspecified'), true, 'bestLannister initially empty'); equal(get(obj, 'noLannistersKnown'), true, 'lannisters initially empty'); get(obj, 'lannisters').pushObject('Tyrion'); set(obj, 'bestLannister', 'Tyrion'); equal(get(obj, 'bestLannisterUnspecified'), false, 'empty respects strings'); equal(get(obj, 'noLannistersKnown'), false, 'empty respects array mutations'); }); testBoth('Ember.computed.notEmpty', function(get, set) { var obj = EmberObject.extend({ bestLannister: null, lannisters: null,
objB.__foo = 'FOO'; // make a copy; }, teardown() { objA = objB = null; } }); testBoth('using get() and set()', function(get, set) { equal(get(objA, 'foo'), 'FOO', 'should get FOO from A'); equal(get(objB, 'foo'), 'FOO', 'should get FOO from B'); set(objA, 'foo', 'BIFF'); equal(get(objA, 'foo'), 'computed BIFF', 'should change A'); equal(get(objB, 'foo'), 'FOO', 'should NOT change B'); set(objB, 'foo', 'bar'); equal(get(objB, 'foo'), 'computed bar', 'should change B'); equal(get(objA, 'foo'), 'computed BIFF', 'should NOT change A'); set(objA, 'foo', 'BAZ'); equal(get(objA, 'foo'), 'computed BAZ', 'should change A'); equal(get(objB, 'foo'), 'computed bar', 'should NOT change B'); }); QUnit.module('redefining computed property to normal', { setup() { objA = { __foo: 'FOO' }; defineProperty(objA, 'foo', computed({ get: function(key) { return this['__'+key]; },
import { testBoth } from 'ember-metal/tests/props_helper'; import { A as emberA } from 'ember-runtime/system/native_array'; import isEnabled from 'ember-metal/features'; QUnit.module('CP macros'); testBoth('Ember.computed.empty', function (get, set) { let obj = EmberObject.extend({ bestLannister: null, lannisters: null, bestLannisterUnspecified: empty('bestLannister'), noLannistersKnown: empty('lannisters') }).create({ lannisters: emberA() }); equal(get(obj, 'bestLannisterUnspecified'), true, 'bestLannister initially empty'); equal(get(obj, 'noLannistersKnown'), true, 'lannisters initially empty'); get(obj, 'lannisters').pushObject('Tyrion'); set(obj, 'bestLannister', 'Tyrion'); equal(get(obj, 'bestLannisterUnspecified'), false, 'empty respects strings'); equal(get(obj, 'noLannistersKnown'), false, 'empty respects array mutations'); }); testBoth('Ember.computed.notEmpty', function(get, set) { let obj = EmberObject.extend({ bestLannister: null, lannisters: null,
mixin, Mixin } from 'ember-metal/mixin'; import { isWatching } from 'ember-metal/watching'; QUnit.module('Mixin observer'); testBoth('global observer helper', function(get, set) { var MyMixin = Mixin.create({ count: 0, foo: observer('bar', function() { set(this, 'count', get(this, 'count')+1); }) }); var obj = mixin({}, MyMixin); equal(get(obj, 'count'), 0, 'should not invoke observer immediately'); set(obj, 'bar', 'BAZ'); equal(get(obj, 'count'), 1, 'should invoke observer after change'); }); testBoth('global observer helper takes multiple params', function(get, set) { var MyMixin = Mixin.create({ count: 0,
objB.__foo = 'FOO'; // make a copy; }, teardown() { objA = objB = null; } }); testBoth('using get() and set()', function(get, set) { equal(get(objA, 'foo'), 'FOO', 'should get FOO from A'); equal(get(objB, 'foo'), 'FOO', 'should get FOO from B'); set(objA, 'foo', 'BIFF'); equal(get(objA, 'foo'), 'computed BIFF', 'should change A'); equal(get(objB, 'foo'), 'FOO', 'should NOT change B'); set(objB, 'foo', 'bar'); equal(get(objB, 'foo'), 'computed bar', 'should change B'); equal(get(objA, 'foo'), 'computed BIFF', 'should NOT change A'); set(objA, 'foo', 'BAZ'); equal(get(objA, 'foo'), 'computed BAZ', 'should change A'); equal(get(objB, 'foo'), 'computed bar', 'should NOT change B'); }); QUnit.module('redefining computed property to normal', { setup() { objA = { __foo: 'FOO' }; defineProperty(objA, 'foo', computed({ get: function(key) { return this['__' + key]; },
addListener(obj, keyPath + ':change', function() { didCount++; didKeys.push(keyPath); }); } testBoth('watching a computed property', function(get, set) { let obj = {}; defineProperty(obj, 'foo', computed({ get() { return this.__foo; }, set(keyName, value) { if (value !== undefined) { this.__foo = value; } return this.__foo; } })); addListeners(obj, 'foo'); watch(obj, 'foo'); set(obj, 'foo', 'bar'); equal(willCount, 1, 'should have invoked willCount'); equal(didCount, 1, 'should have invoked didCount'); }); testBoth('watching a regular defined property', function(get, set) { let obj = { foo: 'baz' }; addListeners(obj, 'foo'); watch(obj, 'foo');
testBoth('calling setProperties completes safely despite exceptions', function(get, set) { var exc = new Error("Something unexpected happened!"); var obj = EmberObject.createWithMixins({ firstName: "Steve", lastName: "Jobs", companyName: computed(function(key, value) { if (value !== undefined) { throw exc; } return "Apple, Inc."; }) }); var firstNameChangedCount = 0; addObserver(obj, 'firstName', function() { firstNameChangedCount++; }); try { obj.setProperties({ firstName: 'Tim', lastName: 'Cook', companyName: 'Fruit Co., Inc.' }); } catch(err) { if (err !== exc) { throw err; } } equal(firstNameChangedCount, 1, 'firstName should have fired once'); });
testBoth('bindings should not sync twice in a single run loop', function(get, set) { let a, b, setValue; let setCalled = 0; let getCalled = 0; run(() => { a = {}; defineProperty(a, 'foo', computed({ get(key) { getCalled++; return setValue; }, set(key, value) { setCalled++; propertyWillChange(this, key); setValue = value; propertyDidChange(this, key); return value; } }).volatile()); b = { a: a }; expectDeprecation(() => bind(b, 'foo', 'a.foo'), /`Ember.Binding` is deprecated/); }); // reset after initial binding synchronization getCalled = 0; run(() => { set(a, 'foo', 'trollface'); }); equal(get(b, 'foo'), 'trollface', 'the binding should sync'); equal(setCalled, 1, 'Set should only be called once'); equal(getCalled, 1, 'Get should only be called once'); });
}); QUnit.test('updates when array is modified', function() { obj.get('array').pushObject(1); equal(obj.get('total'), 7, 'recomputed when elements are added'); obj.get('array').popObject(); equal(obj.get('total'), 6, 'recomputes when elements are removed'); }); QUnit.module('collect'); testBoth('works', function(get, set) { var obj = { one: 'foo', two: 'bar', three: null }; defineProperty(obj, 'all', collect('one', 'two', 'three', 'four')); deepEqual(get(obj, 'all'), ['foo', 'bar', null, null], 'have all of them'); set(obj, 'four', true); deepEqual(get(obj, 'all'), ['foo', 'bar', null, true], 'have all of them'); var a = []; set(obj, 'one', 0); set(obj, 'three', a); deepEqual(get(obj, 'all'), [0, 'bar', a, true], 'have all of them'); });
testBoth("bindings should not sync twice in a single run loop", function(get, set) { var a, b, setValue; var setCalled=0; var getCalled=0; run(function() { a = {}; defineProperty(a, 'foo', computed({ get: function(key) { getCalled++; return setValue; }, set: function(key, value) { setCalled++; setValue = value; return value; } }).volatile()); b = { a: a }; bind(b, 'foo', 'a.foo'); }); // reset after initial binding synchronization getCalled = 0; run(function() { set(a, 'foo', 'trollface'); }); equal(get(b, 'foo'), "trollface", "the binding should sync"); equal(setCalled, 1, "Set should only be called once"); equal(getCalled, 1, "Get should only be called once"); });
beginPropertyChanges, endPropertyChanges } from 'ember-metal/property_events'; import { testBoth } from 'ember-metal/tests/props_helper'; import EmberObject from 'ember-runtime/system/object'; QUnit.module('ember-runtime/system/object/destroy_test'); testBoth('should schedule objects to be destroyed at the end of the run loop', function(get, set) { var obj = EmberObject.create(); var meta; run(function() { obj.destroy(); meta = obj['__ember_meta__']; ok(meta, 'meta is not destroyed immediately'); ok(get(obj, 'isDestroying'), 'object is marked as destroying immediately'); ok(!get(obj, 'isDestroyed'), 'object is not destroyed immediately'); }); meta = obj['__ember_meta__']; ok(!meta, 'meta is destroyed after run loop finishes'); ok(get(obj, 'isDestroyed'), 'object is destroyed after run loop finishes'); }); if (isEnabled('mandatory-setter')) { // MANDATORY_SETTER moves value to meta.values // a destroyed object removes meta but leaves the accessor // that looks it up QUnit.test('should raise an exception when modifying watched properties on a destroyed object', function() { var obj = EmberObject.extend({ fooDidChange: observer('foo', function() { })
beginPropertyChanges, endPropertyChanges } from 'ember-metal/property_events'; import { testBoth } from 'ember-metal/tests/props_helper'; import EmberObject from 'ember-runtime/system/object'; import { peekMeta } from 'ember-metal/meta'; QUnit.module('ember-runtime/system/object/destroy_test'); testBoth('should schedule objects to be destroyed at the end of the run loop', function(get, set) { let obj = EmberObject.create(); let meta; run(() => { obj.destroy(); meta = peekMeta(obj); ok(meta, 'meta is not destroyed immediately'); ok(get(obj, 'isDestroying'), 'object is marked as destroying immediately'); ok(!get(obj, 'isDestroyed'), 'object is not destroyed immediately'); }); meta = peekMeta(obj); ok(!meta, 'meta is destroyed after run loop finishes'); ok(get(obj, 'isDestroyed'), 'object is destroyed after run loop finishes'); }); if (isEnabled('mandatory-setter')) { // MANDATORY_SETTER moves value to meta.values // a destroyed object removes meta but leaves the accessor // that looks it up QUnit.test('should raise an exception when modifying watched properties on a destroyed object', function() { let obj = EmberObject.extend({ fooDidChange: observer('foo', function() { })
}; get(obj, 'id'); equal(count, 1); }); testBoth('should call unknownProperty on watched values if the value is undefined', function(get, set) { var obj = { count: 0, unknownProperty(key) { equal(key, 'foo', 'should pass key'); this.count++; return 'FOO'; } }; var count = 0; addObserver(obj, 'foo', function() { count++; }); equal(get(obj, 'foo'), 'FOO', 'should return value from unknown'); }); QUnit.test('warn on attemps to call get with no arguments', function() { expectAssertion(function() { get('aProperty'); }, /Get must be called with two arguments;/i); });
import { testBoth } from "ember-metal/tests/props_helper"; QUnit.module('Function.prototype.observes() helper'); testBoth('global observer helper takes multiple params', function(get, set) { if (Ember.EXTEND_PROTOTYPES === false) { ok("undefined" === typeof Function.prototype.observes, 'Function.prototype helper disabled'); return ; } var MyMixin = Ember.Mixin.create({ count: 0, foo: function() { set(this, 'count', get(this, 'count')+1); }.observes('bar', 'baz') }); var obj = Ember.mixin({}, MyMixin); equal(get(obj, 'count'), 0, 'should not invoke observer immediately'); set(obj, 'bar', "BAZ"); set(obj, 'baz', "BAZ"); equal(get(obj, 'count'), 2, 'should invoke observer after change'); }); QUnit.module('Function.prototype.on() helper'); testBoth('sets up an event listener, and can trigger the function on multiple events', function(get, set) {
endPropertyChanges, changeProperties } from 'ember-metal/property_events'; // .......................................................... // ADD OBSERVER // QUnit.module('addObserver'); testBoth('observer should fire when property is modified', function(get, set) { var obj = {}; var count = 0; addObserver(obj, 'foo', function() { equal(get(obj, 'foo'), 'bar', 'should invoke AFTER value changed'); count++; }); set(obj, 'foo', 'bar'); equal(count, 1, 'should have invoked observer'); }); testBoth('observer should fire when dependent property is modified', function(get, set) { var obj = { bar: 'bar' }; defineProperty(obj, 'foo', computed(function() { return get(this, 'bar').toUpperCase(); }).property('bar')); get(obj, 'foo'); var count = 0;
QUnit.module("Ember.Binding", { setup() { originalLookup = Ember.lookup; Ember.lookup = lookup = {}; }, teardown() { lookup = null; Ember.lookup = originalLookup; } }); testBoth('Connecting a binding between two properties', function(get, set) { var a = { foo: 'FOO', bar: 'BAR' }; // a.bar -> a.foo var binding = new Binding('foo', 'bar'); performTest(binding, a, a, get, set); }); testBoth('Connecting a binding between two objects', function(get, set) { var b = { bar: 'BAR' }; var a = { foo: 'FOO', b: b }; // b.bar -> a.foo var binding = new Binding('foo', 'b.bar'); performTest(binding, a, b, get, set); }); testBoth('Connecting a binding to path', function(get, set) {
import { computed } from 'ember-metal/computed'; import { isWatching } from 'ember-metal/watching'; import { testBoth } from 'ember-metal/tests/props_helper'; import ObjectProxy from 'ember-runtime/system/object_proxy'; QUnit.module('ObjectProxy'); testBoth('should not proxy properties passed to create', function (get, set) { let Proxy = ObjectProxy.extend({ cp: computed({ get(key) { return this._cp; }, set(key, value) { this._cp = value; return this._cp; } }) }); let proxy = Proxy.create({ prop: 'Foo', cp: 'Bar' }); equal(get(proxy, 'prop'), 'Foo', 'should not have tried to proxy set'); equal(proxy._cp, 'Bar', 'should use CP setter'); }); testBoth('should proxy properties to content', function(get, set) { let content = { firstName: 'Tom', lastName: 'Dale', unknownProperty(key) { return key + ' unknown';} };
} from "ember-metal/computed_macros"; import EmberObject from "ember-runtime/system/object"; import { testBoth } from "ember-metal/tests/props_helper"; QUnit.module('CP macros'); testBoth('Ember.computed.empty', function (get, set) { var obj = EmberObject.extend({ bestLannister: null, lannisters: null, bestLannisterUnspecified: empty('bestLannister'), noLannistersKnown: empty('lannisters') }).create({ lannisters: Ember.A([]) }); equal(get(obj, 'bestLannisterUnspecified'), true, "bestLannister initially empty"); equal(get(obj, 'noLannistersKnown'), true, "lannisters initially empty"); get(obj, 'lannisters').pushObject('Tyrion'); set(obj, 'bestLannister', 'Tyrion'); equal(get(obj, 'bestLannisterUnspecified'), false, "empty respects strings"); equal(get(obj, 'noLannistersKnown'), false, "empty respects array mutations"); }); testBoth('Ember.computed.notEmpty', function(get, set) { var obj = EmberObject.extend({ bestLannister: null, lannisters: null,