Repository: ambari Updated Branches: refs/heads/trunk 6c3cf4993 -> b19bf6eab
AMBARI-14093. Add ability for some Em.computed macros to work with App.* keys (onechiporenko) Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/b19bf6ea Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/b19bf6ea Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/b19bf6ea Branch: refs/heads/trunk Commit: b19bf6eab3821de71c5ffcf8c1f87ea1b338a50b Parents: 6c3cf49 Author: Oleg Nechiporenko <onechipore...@apache.org> Authored: Fri Nov 27 11:45:06 2015 +0200 Committer: Oleg Nechiporenko <onechipore...@apache.org> Committed: Fri Nov 27 11:45:06 2015 +0200 ---------------------------------------------------------------------- ambari-web/app/utils/ember_computed.js | 102 +++-- ambari-web/test/utils/ember_computed_test.js | 496 +++++++++++++++++++++- 2 files changed, 552 insertions(+), 46 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/b19bf6ea/ambari-web/app/utils/ember_computed.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/utils/ember_computed.js b/ambari-web/app/utils/ember_computed.js index c996f32..03ac4fc 100644 --- a/ambari-web/app/utils/ember_computed.js +++ b/ambari-web/app/utils/ember_computed.js @@ -24,26 +24,57 @@ var slice = [].slice; var dataUtils = require('utils/data_manipulation'); +/** + * Returns hash with values of name properties from the context + * If <code>propertyName</code> starts with 'App.', <code>App</code> is used as context, <code>self</code> used otherwise + * If some <code>propertyName</code> starts with '!' its value will be inverted + * + * @param {object} self current context + * @param {string[]} propertyNames needed properties + * @returns {object} hash with needed values + */ function getProperties(self, propertyNames) { var ret = {}; for (var i = 0; i < propertyNames.length; i++) { var propertyName = propertyNames[i]; - var value; - if (propertyName.startsWith('!')) { - propertyName = propertyName.substring(1); - value = !get(self, propertyName); - } - else { - value = get(self, propertyName); - } + var shouldBeInverted = propertyName.startsWith('!'); + propertyName = shouldBeInverted ? propertyName.substr(1) : propertyName; + var isApp = propertyName.startsWith('App.'); + var name = isApp ? propertyName.replace('App.', '') : propertyName; + var context = isApp ? App : self; + var value = get(context, name); + value = shouldBeInverted ? !value : value; ret[propertyName] = value; } return ret; } +/** + * Returns value of named property from the context + * If <code>propertyName</code> starts with 'App.', <code>App</code> is used as context, <code>self</code> used otherwise + * + * @param {object} self current context + * @param {string} propertyName needed property + * @returns {*} needed value + */ +function smartGet(self, propertyName) { + var isApp = propertyName.startsWith('App.'); + var name = isApp ? propertyName.replace('App.', '') : propertyName; + var context = isApp ? App : self; + return get(context, name) +} + +/** + * Returns list with values of name properties from the context + * If <code>propertyName</code> starts with 'App.', <code>App</code> is used as context, <code>self</code> used otherwise + * + * @param {object} self current context + * @param {string[]} propertyNames neded properties + * @returns {array} list of needed values + */ function getValues(self, propertyNames) { return propertyNames.map(function (propertyName) { - return get(self, propertyName); + return smartGet(self, propertyName); }); } @@ -87,6 +118,7 @@ function generateComputedWithValues(macro) { * * A computed property that returns true if the provided dependent property * is equal to the given value. + * App.*-keys are supported * Example* * ```javascript * var Hamster = Ember.Object.extend({ @@ -108,12 +140,13 @@ function generateComputedWithValues(macro) { */ computed.equal = function (dependentKey, value) { return computed(dependentKey, function () { - return get(this, dependentKey) === value; + return smartGet(this, dependentKey) === value; }).cacheable(); }; /** * A computed property that returns true if the provided dependent property is not equal to the given value + * App.*-keys are supported * * @method notEqual * @param {string} dependentKey @@ -122,12 +155,13 @@ computed.equal = function (dependentKey, value) { */ computed.notEqual = function (dependentKey, value) { return computed(dependentKey, function () { - return get(this, dependentKey) !== value; + return smartGet(this, dependentKey) !== value; }); }; /** * A computed property that returns true if provided dependent properties are equal to the each other + * App.*-keys are supported * * @method equalProperties * @param {string} dependentKey1 @@ -136,12 +170,13 @@ computed.notEqual = function (dependentKey, value) { */ computed.equalProperties = function (dependentKey1, dependentKey2) { return computed(dependentKey1, dependentKey2, function () { - return get(this, dependentKey1) === get(this, dependentKey2); + return smartGet(this, dependentKey1) === smartGet(this, dependentKey2); }); }; /** * A computed property that returns true if provided dependent properties are not equal to the each other + * App.*-keys are supported * * @method notEqualProperties * @param {string} dependentKey1 @@ -150,7 +185,7 @@ computed.equalProperties = function (dependentKey1, dependentKey2) { */ computed.notEqualProperties = function (dependentKey1, dependentKey2) { return computed(dependentKey1, dependentKey2, function () { - return get(this, dependentKey1) !== get(this, dependentKey2); + return smartGet(this, dependentKey1) !== smartGet(this, dependentKey2); }); }; @@ -205,6 +240,7 @@ computed.rejectMany = function (collectionKey, propertyName, valuesToReject) { /** * A computed property that returns trueValue if dependent value is true and falseValue otherwise + * App.*-keys are supported * * @method ifThenElse * @param {string} dependentKey @@ -214,7 +250,7 @@ computed.rejectMany = function (collectionKey, propertyName, valuesToReject) { */ computed.ifThenElse = function (dependentKey, trueValue, falseValue) { return computed(dependentKey, function () { - return get(this, dependentKey) ? trueValue : falseValue; + return smartGet(this, dependentKey) ? trueValue : falseValue; }); }; @@ -222,6 +258,7 @@ computed.ifThenElse = function (dependentKey, trueValue, falseValue) { * A computed property that is equal to the logical 'and' * Takes any number of arguments * Returns true if all of them are truly, false - otherwise + * App.*-keys are supported * * @method and * @param {...string} dependentKeys @@ -242,6 +279,7 @@ computed.and = generateComputedWithProperties(function (properties) { * A computed property that is equal to the logical 'or' * Takes any number of arguments * Returns true if at least one of them is truly, false - otherwise + * App.*-keys are supported * * @method or * @param {...string} dependentKeys @@ -261,6 +299,7 @@ computed.or = generateComputedWithProperties(function (properties) { /** * A computed property that returns sum on the dependent properties values * Takes any number of arguments + * App.*-keys are supported * * @method sumProperties * @param {...string} dependentKeys @@ -278,6 +317,7 @@ computed.sumProperties = generateComputedWithProperties(function (properties) { /** * A computed property that returns true if dependent value is greater or equal to the needed value + * App.*-keys are supported * * @method gte * @param {string} dependentKey @@ -286,12 +326,13 @@ computed.sumProperties = generateComputedWithProperties(function (properties) { */ computed.gte = function (dependentKey, value) { return computed(dependentKey, function () { - return get(this, dependentKey) >= value; + return smartGet(this, dependentKey) >= value; }); }; /** * A computed property that returns true if first dependent property is greater or equal to the second dependent property + * App.*-keys are supported * * @method gteProperties * @param {string} dependentKey1 @@ -300,12 +341,13 @@ computed.gte = function (dependentKey, value) { */ computed.gteProperties = function (dependentKey1, dependentKey2) { return computed(dependentKey1, dependentKey2, function () { - return get(this, dependentKey1) >= get(this, dependentKey2); + return smartGet(this, dependentKey1) >= smartGet(this, dependentKey2); }); }; /** * A computed property that returns true if dependent property is less or equal to the needed value + * App.*-keys are supported * * @method lte * @param {string} dependentKey @@ -314,12 +356,13 @@ computed.gteProperties = function (dependentKey1, dependentKey2) { */ computed.lte = function (dependentKey, value) { return computed(dependentKey, function () { - return get(this, dependentKey) <= value; + return smartGet(this, dependentKey) <= value; }); }; /** * A computed property that returns true if first dependent property is less or equal to the second dependent property + * App.*-keys are supported * * @method lteProperties * @param {string} dependentKey1 @@ -328,12 +371,13 @@ computed.lte = function (dependentKey, value) { */ computed.lteProperties = function (dependentKey1, dependentKey2) { return computed(dependentKey1, dependentKey2, function () { - return get(this, dependentKey1) <= get(this, dependentKey2); + return smartGet(this, dependentKey1) <= smartGet(this, dependentKey2); }); }; /** * A computed property that returns true if dependent value is greater than the needed value + * App.*-keys are supported * * @method gt * @param {string} dependentKey @@ -342,12 +386,13 @@ computed.lteProperties = function (dependentKey1, dependentKey2) { */ computed.gt = function (dependentKey, value) { return computed(dependentKey, function () { - return get(this, dependentKey) > value; + return smartGet(this, dependentKey) > value; }); }; /** * A computed property that returns true if first dependent property is greater than the second dependent property + * App.*-keys are supported * * @method gtProperties * @param {string} dependentKey1 @@ -356,12 +401,13 @@ computed.gt = function (dependentKey, value) { */ computed.gtProperties = function (dependentKey1, dependentKey2) { return computed(dependentKey1, dependentKey2, function () { - return get(this, dependentKey1) > get(this, dependentKey2); + return smartGet(this, dependentKey1) > smartGet(this, dependentKey2); }); }; /** * A computed property that returns true if dependent value is less than the needed value + * App.*-keys are supported * * @method lt * @param {string} dependentKey @@ -370,12 +416,13 @@ computed.gtProperties = function (dependentKey1, dependentKey2) { */ computed.lt = function (dependentKey, value) { return computed(dependentKey, function () { - return get(this, dependentKey) < value; + return smartGet(this, dependentKey) < value; }); }; /** * A computed property that returns true if first dependent property is less than the second dependent property + * App.*-keys are supported * * @method gtProperties * @param {string} dependentKey1 @@ -384,7 +431,7 @@ computed.lt = function (dependentKey, value) { */ computed.ltProperties = function (dependentKey1, dependentKey2) { return computed(dependentKey1, dependentKey2, function () { - return get(this, dependentKey1) < get(this, dependentKey2); + return smartGet(this, dependentKey1) < smartGet(this, dependentKey2); }); }; @@ -503,6 +550,7 @@ computed.findBy = function (collectionKey, propertyName, neededValue) { /** * A computed property that returns value equal to the dependent * Should be used as 'short-name' for deeply-nested values + * App.*-keys are supported * * @method alias * @param {string} dependentKey @@ -510,7 +558,7 @@ computed.findBy = function (collectionKey, propertyName, neededValue) { */ computed.alias = function (dependentKey) { return computed(dependentKey, function () { - return get(this, dependentKey); + return smartGet(this, dependentKey); }); }; @@ -548,6 +596,7 @@ computed.notExistsIn = function (dependentKey, neededValues) { * A computed property that returns result of calculation <code>(dependentProperty1/dependentProperty2 * 100)</code> * If accuracy is 0 (by default), result is rounded to integer * Otherwise - result is float with provided accuracy + * App.*-keys are supported * * @method percents * @param {string} dependentKey1 @@ -560,8 +609,8 @@ computed.percents = function (dependentKey1, dependentKey2, accuracy) { accuracy = 0; } return computed(dependentKey1, dependentKey2, function () { - var v1 = Number(get(this, dependentKey1)); - var v2 = Number(get(this, dependentKey2)); + var v1 = Number(smartGet(this, dependentKey1)); + var v2 = Number(smartGet(this, dependentKey2)); var result = v1 / v2 * 100; if (0 === accuracy) { return Math.round(result); @@ -609,6 +658,7 @@ computed.sumBy = function (collectionKey, propertyName) { /** * A computed property that returns I18n-string formatted with dependent properties * Takes at least one argument + * App.*-keys are supported * * @param {string} key key in the I18n-messages * @param {...string} dependentKeys @@ -626,6 +676,7 @@ computed.i18nFormat = generateComputedWithKey(function (key, dependentValues) { /** * A computed property that returns dependent values joined with separator * Takes at least one argument + * App.*-keys are supported * * @param {string} separator * @param {...string} dependentKeys @@ -641,6 +692,7 @@ computed.concat = generateComputedWithKey(function (separator, dependentValues) * Based on <code>Ember.isBlank</code> * Takes at least 1 argument * Dependent values order affects the result + * App.*-keys are supported * * @param {...string} dependentKeys * @method {firstNotBlank} http://git-wip-us.apache.org/repos/asf/ambari/blob/b19bf6ea/ambari-web/test/utils/ember_computed_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/utils/ember_computed_test.js b/ambari-web/test/utils/ember_computed_test.js index 380982c..4aa3158 100644 --- a/ambari-web/test/utils/ember_computed_test.js +++ b/ambari-web/test/utils/ember_computed_test.js @@ -20,12 +20,64 @@ require('utils/ember_computed'); describe('Ember.computed macros', function () { + beforeEach(function () { + App.reopen({ + someRandomTestingKey: function () { + return this.get('someAnotherKey'); + }.property('someAnotherKey'), + someAnotherKey: '' + }); + }); + + afterEach(function () { + delete App.someAnotherKey; + delete App.someRandomTestingKey; + }); + + describe('#equal', function () { + + beforeEach(function () { + App.setProperties({ + someAnotherKey: '123' + }); + this.obj = Em.Object.create({ + prop1: '123', + prop2: Em.computed.equal('prop1', '123'), + prop3: Em.computed.equal('App.someRandomTestingKey', '123') + }); + }); + + it('`true` if values are equal', function () { + expect(this.obj.get('prop2')).to.be.true; + }); + + it('`false` if values are not equal', function () { + this.obj.set('prop1', '321'); + expect(this.obj.get('prop2')).to.be.false; + }); + + it('`prop3` depends on App.* key', function () { + expect(this.obj.get('prop3')).to.be.true; + App.set('someAnotherKey', ''); + expect(this.obj.get('prop3')).to.be.false; + }); + + it('prop3 dependent keys are valid', function () { + expect(Em.meta(this.obj).descs.prop3._dependentKeys).to.eql(['App.someRandomTestingKey']); + }); + + }); + describe('#notEqual', function () { beforeEach(function () { + App.setProperties({ + someAnotherKey: '123' + }); this.obj = Em.Object.create({ prop1: '123', - prop2: Em.computed.notEqual('prop1', '123') + prop2: Em.computed.notEqual('prop1', '123'), + prop3: Em.computed.notEqual('App.someRandomTestingKey', '123') }); }); @@ -38,15 +90,28 @@ describe('Ember.computed macros', function () { expect(this.obj.get('prop2')).to.be.true; }); + it('`prop3` depends on App.* key', function () { + expect(this.obj.get('prop3')).to.be.false; + App.set('someAnotherKey', ''); + expect(this.obj.get('prop3')).to.be.true; + }); + + it('prop3 dependent keys are valid', function () { + expect(Em.meta(this.obj).descs.prop3._dependentKeys).to.eql(['App.someRandomTestingKey']); + }); + }); describe('#equalProperties', function () { beforeEach(function () { + App.set('someAnotherKey', '123'); this.obj = Em.Object.create({ prop1: '123', prop2: '123', - prop3: Em.computed.equalProperties('prop1', 'prop2') + prop3: Em.computed.equalProperties('prop1', 'prop2'), + prop4: Em.computed.equalProperties('App.someRandomTestingKey', 'prop2'), + prop5: Em.computed.equalProperties('prop1', 'App.someRandomTestingKey') }); }); @@ -59,15 +124,38 @@ describe('Ember.computed macros', function () { expect(this.obj.get('prop3')).to.be.false; }); + it('prop4 depends on App.* key', function () { + expect(this.obj.get('prop4')).to.be.true; + App.set('someAnotherKey', ''); + expect(this.obj.get('prop4')).to.be.false; + }); + + it('prop5 depends on App.* key', function () { + expect(this.obj.get('prop5')).to.be.true; + App.set('someAnotherKey', ''); + expect(this.obj.get('prop5')).to.be.false; + }); + + it('prop4 dependent keys are valid', function () { + expect(Em.meta(this.obj).descs.prop4._dependentKeys).to.eql(['App.someRandomTestingKey', 'prop2']); + }); + + it('prop5 dependent keys are valid', function () { + expect(Em.meta(this.obj).descs.prop5._dependentKeys).to.eql(['prop1', 'App.someRandomTestingKey']); + }); + }); describe('#notEqualProperties', function () { beforeEach(function () { + App.set('someAnotherKey', '123'); this.obj = Em.Object.create({ prop1: '123', prop2: '123', - prop3: Em.computed.notEqualProperties('prop1', 'prop2') + prop3: Em.computed.notEqualProperties('prop1', 'prop2'), + prop4: Em.computed.notEqualProperties('App.someRandomTestingKey', 'prop2'), + prop5: Em.computed.notEqualProperties('prop1', 'App.someRandomTestingKey') }); }); @@ -80,14 +168,36 @@ describe('Ember.computed macros', function () { expect(this.obj.get('prop3')).to.be.true; }); + it('prop4 depends on App.* key', function () { + expect(this.obj.get('prop4')).to.be.false; + App.set('someAnotherKey', ''); + expect(this.obj.get('prop4')).to.be.true; + }); + + it('prop5 depends on App.* key', function () { + expect(this.obj.get('prop5')).to.be.false; + App.set('someAnotherKey', ''); + expect(this.obj.get('prop5')).to.be.true; + }); + + it('prop4 dependent keys are valid', function () { + expect(Em.meta(this.obj).descs.prop4._dependentKeys).to.eql(['App.someRandomTestingKey', 'prop2']); + }); + + it('prop5 dependent keys are valid', function () { + expect(Em.meta(this.obj).descs.prop5._dependentKeys).to.eql(['prop1', 'App.someRandomTestingKey']); + }); + }); describe('#ifThenElse', function () { beforeEach(function () { + App.set('someAnotherKey', true); this.obj = Em.Object.create({ prop1: true, - prop2: Em.computed.ifThenElse('prop1', '1', '0') + prop2: Em.computed.ifThenElse('prop1', '1', '0'), + prop3: Em.computed.ifThenElse('App.someRandomTestingKey', '1', '0') }); }); @@ -100,17 +210,32 @@ describe('Ember.computed macros', function () { expect(this.obj.get('prop2')).to.equal('0'); }); + it('prop3 depends on App.* key', function () { + expect(this.obj.get('prop3')).to.equal('1'); + App.set('someAnotherKey', false); + expect(this.obj.get('prop3')).to.equal('0'); + }); + + it('prop3 dependent keys are valid', function () { + expect(Em.meta(this.obj).descs.prop3._dependentKeys).to.eql(['App.someRandomTestingKey']); + }); + }); describe('#and', function () { beforeEach(function () { + App.setProperties({ + someAnotherKey: true + }); this.obj = Em.Object.create({ prop1: true, prop2: true, prop3: true, prop4: Em.computed.and('prop1', 'prop2', 'prop3'), - prop5: Em.computed.and('prop1', '!prop2', '!prop3') + prop5: Em.computed.and('prop1', '!prop2', '!prop3'), + prop6: Em.computed.and('App.someRandomTestingKey', 'prop1'), + prop7: Em.computed.and('!App.someRandomTestingKey', 'prop1') }); }); @@ -142,17 +267,45 @@ describe('Ember.computed macros', function () { expect(this.obj.get('prop5')).to.be.true; }); + it('`prop6` depends on App.* key', function () { + expect(this.obj.get('prop6')).to.be.true; + App.set('someAnotherKey', false); + expect(this.obj.get('prop6')).to.be.false; + App.set('someAnotherKey', true); + expect(this.obj.get('prop6')).to.be.true; + }); + + it('prop6 dependent keys are valid', function () { + expect(Em.meta(this.obj).descs.prop6._dependentKeys).to.eql(['App.someRandomTestingKey', 'prop1']); + }); + + it('`prop7` depends on inverted App.* key', function () { + expect(this.obj.get('prop7')).to.be.false; + App.set('someAnotherKey', false); + expect(this.obj.get('prop7')).to.be.true; + App.set('someAnotherKey', true); + expect(this.obj.get('prop7')).to.be.false; + }); + + it('prop7 dependent keys are valid', function () { + expect(Em.meta(this.obj).descs.prop7._dependentKeys).to.eql(['App.someRandomTestingKey', 'prop1']); + }); + }); describe('#or', function () { - beforeEach(function () { + App.setProperties({ + someAnotherKey: true + }); this.obj = Em.Object.create({ prop1: false, prop2: false, prop3: false, prop4: Em.computed.or('prop1', 'prop2', 'prop3'), - prop5: Em.computed.or('!prop1', '!prop2', '!prop3') + prop5: Em.computed.or('!prop1', '!prop2', '!prop3'), + prop6: Em.computed.or('App.someRandomTestingKey', 'prop1'), + prop7: Em.computed.or('!App.someRandomTestingKey', 'prop1') }); }); @@ -185,16 +338,44 @@ describe('Ember.computed macros', function () { expect(this.obj.get('prop5')).to.be.false; }); + it('`prop6` depends on App.* key', function () { + expect(this.obj.get('prop6')).to.be.true; + App.set('someAnotherKey', false); + expect(this.obj.get('prop6')).to.be.false; + App.set('someAnotherKey', true); + expect(this.obj.get('prop6')).to.be.true; + }); + + it('prop6 dependent keys are valid', function () { + expect(Em.meta(this.obj).descs.prop6._dependentKeys).to.eql(['App.someRandomTestingKey', 'prop1']); + }); + + it('`prop7` depends on inverted App.* key', function () { + expect(this.obj.get('prop7')).to.be.false; + App.set('someAnotherKey', false); + expect(this.obj.get('prop7')).to.be.true; + App.set('someAnotherKey', true); + expect(this.obj.get('prop7')).to.be.false; + }); + + it('prop7 dependent keys are valid', function () { + expect(Em.meta(this.obj).descs.prop7._dependentKeys).to.eql(['App.someRandomTestingKey', 'prop1']); + }); + }); describe('#sumProperties', function () { beforeEach(function () { + App.setProperties({ + someAnotherKey: 5 + }); this.obj = Em.Object.create({ prop1: 1, prop2: 2, prop3: 3, - prop4: Em.computed.sumProperties('prop1', 'prop2', 'prop3') + prop4: Em.computed.sumProperties('prop1', 'prop2', 'prop3'), + prop5: Em.computed.sumProperties('prop1', 'prop2', 'App.someRandomTestingKey') }); }); @@ -222,14 +403,26 @@ describe('Ember.computed macros', function () { expect(this.obj.get('prop4')).to.equal(5); }); + it('`prop5` depends on App.* key', function () { + expect(this.obj.get('prop5')).to.equal(8); + App.set('someAnotherKey', 6); + expect(this.obj.get('prop5')).to.equal(9); + }); + + it('prop5 dependent keys are valid', function () { + expect(Em.meta(this.obj).descs.prop5._dependentKeys).to.eql(['prop1', 'prop2', 'App.someRandomTestingKey']); + }); + }); describe('#gte', function () { beforeEach(function () { + App.set('someAnotherKey', 4); this.obj = Em.Object.create({ prop1: 2, - prop2: Em.computed.gte('prop1', 3) + prop2: Em.computed.gte('prop1', 3), + prop3: Em.computed.gte('App.someRandomTestingKey', 3) }); }); @@ -247,15 +440,30 @@ describe('Ember.computed macros', function () { expect(this.obj.get('prop2')).to.be.true; }); + it('prop3 depends on App.* key', function () { + expect(this.obj.get('prop3')).to.be.true; + App.set('someAnotherKey', 3); + expect(this.obj.get('prop3')).to.be.true; + App.set('someAnotherKey', 2); + expect(this.obj.get('prop3')).to.be.false; + }); + + it('prop3 dependent keys are valid', function () { + expect(Em.meta(this.obj).descs.prop3._dependentKeys).to.eql(['App.someRandomTestingKey']); + }); + }); describe('#gteProperties', function () { beforeEach(function () { + App.set('someAnotherKey', 4); this.obj = Em.Object.create({ prop1: 2, prop2: 3, - prop3: Em.computed.gteProperties('prop1', 'prop2') + prop3: Em.computed.gteProperties('prop1', 'prop2'), + prop4: Em.computed.gteProperties('App.someRandomTestingKey', 'prop2'), + prop5: Em.computed.gteProperties('prop1', 'App.someRandomTestingKey') }); }); @@ -273,14 +481,40 @@ describe('Ember.computed macros', function () { expect(this.obj.get('prop3')).to.be.true; }); + it('prop4 depends on App.* key', function () { + expect(this.obj.get('prop4')).to.be.true; + App.set('someAnotherKey', 3); + expect(this.obj.get('prop4')).to.be.true; + App.set('someAnotherKey', 2); + expect(this.obj.get('prop4')).to.be.false; + }); + + it('prop5 depends on App.* key', function () { + expect(this.obj.get('prop5')).to.be.false; + App.set('someAnotherKey', 2); + expect(this.obj.get('prop5')).to.be.true; + App.set('someAnotherKey', 1); + expect(this.obj.get('prop5')).to.be.true; + }); + + it('prop4 dependent keys are valid', function () { + expect(Em.meta(this.obj).descs.prop4._dependentKeys).to.eql(['App.someRandomTestingKey', 'prop2']); + }); + + it('prop5 dependent keys are valid', function () { + expect(Em.meta(this.obj).descs.prop5._dependentKeys).to.eql(['prop1', 'App.someRandomTestingKey']); + }); + }); describe('#lte', function () { beforeEach(function () { + App.set('someAnotherKey', 0); this.obj = Em.Object.create({ prop1: 2, - prop2: Em.computed.lte('prop1', 1) + prop2: Em.computed.lte('prop1', 1), + prop3: Em.computed.lte('App.someRandomTestingKey', 1) }); }); @@ -298,15 +532,30 @@ describe('Ember.computed macros', function () { expect(this.obj.get('prop2')).to.be.true; }); + it('prop3 depends on App.* key', function () { + expect(this.obj.get('prop3')).to.be.true; + App.set('someAnotherKey', 1); + expect(this.obj.get('prop3')).to.be.true; + App.set('someAnotherKey', 2); + expect(this.obj.get('prop3')).to.be.false; + }); + + it('prop3 dependent keys are valid', function () { + expect(Em.meta(this.obj).descs.prop3._dependentKeys).to.eql(['App.someRandomTestingKey']); + }); + }); describe('#lteProperties', function () { beforeEach(function () { + App.set('someAnotherKey', 1); this.obj = Em.Object.create({ prop1: 2, prop2: 1, - prop3: Em.computed.lteProperties('prop1', 'prop2') + prop3: Em.computed.lteProperties('prop1', 'prop2'), + prop4: Em.computed.lteProperties('App.someRandomTestingKey', 'prop2'), + prop5: Em.computed.lteProperties('prop1', 'App.someRandomTestingKey') }); }); @@ -324,14 +573,40 @@ describe('Ember.computed macros', function () { expect(this.obj.get('prop3')).to.be.true; }); + it('prop4 depends on App.* key', function () { + expect(this.obj.get('prop4')).to.be.true; + App.set('someAnotherKey', 0); + expect(this.obj.get('prop4')).to.be.true; + App.set('someAnotherKey', 2); + expect(this.obj.get('prop4')).to.be.false; + }); + + it('prop5 depends on App.* key', function () { + expect(this.obj.get('prop5')).to.be.false; + App.set('someAnotherKey', 2); + expect(this.obj.get('prop5')).to.be.true; + App.set('someAnotherKey', 3); + expect(this.obj.get('prop5')).to.be.true; + }); + + it('prop4 dependent keys are valid', function () { + expect(Em.meta(this.obj).descs.prop4._dependentKeys).to.eql(['App.someRandomTestingKey', 'prop2']); + }); + + it('prop5 dependent keys are valid', function () { + expect(Em.meta(this.obj).descs.prop5._dependentKeys).to.eql(['prop1', 'App.someRandomTestingKey']); + }); + }); describe('#gt', function () { beforeEach(function () { + App.set('someAnotherKey', 4); this.obj = Em.Object.create({ prop1: 2, - prop2: Em.computed.gt('prop1', 3) + prop2: Em.computed.gt('prop1', 3), + prop3: Em.computed.gt('App.someRandomTestingKey', 3) }); }); @@ -349,15 +624,30 @@ describe('Ember.computed macros', function () { expect(this.obj.get('prop2')).to.be.true; }); + it('prop3 depends on App.* key', function () { + expect(this.obj.get('prop3')).to.be.true; + App.set('someAnotherKey', 3); + expect(this.obj.get('prop3')).to.be.false; + App.set('someAnotherKey', 2); + expect(this.obj.get('prop3')).to.be.false; + }); + + it('prop3 dependent keys are valid', function () { + expect(Em.meta(this.obj).descs.prop3._dependentKeys).to.eql(['App.someRandomTestingKey']); + }); + }); describe('#gtProperties', function () { beforeEach(function () { + App.set('someAnotherKey', 4); this.obj = Em.Object.create({ prop1: 2, prop2: 3, - prop3: Em.computed.gtProperties('prop1', 'prop2') + prop3: Em.computed.gtProperties('prop1', 'prop2'), + prop4: Em.computed.gtProperties('App.someRandomTestingKey', 'prop2'), + prop5: Em.computed.gtProperties('prop1', 'App.someRandomTestingKey') }); }); @@ -375,14 +665,40 @@ describe('Ember.computed macros', function () { expect(this.obj.get('prop3')).to.be.true; }); + it('prop4 depends on App.* key', function () { + expect(this.obj.get('prop4')).to.be.true; + App.set('someAnotherKey', 3); + expect(this.obj.get('prop4')).to.be.false; + App.set('someAnotherKey', 2); + expect(this.obj.get('prop4')).to.be.false; + }); + + it('prop5 depends on App.* key', function () { + expect(this.obj.get('prop5')).to.be.false; + App.set('someAnotherKey', 2); + expect(this.obj.get('prop5')).to.be.false; + App.set('someAnotherKey', 1); + expect(this.obj.get('prop5')).to.be.true; + }); + + it('prop4 dependent keys are valid', function () { + expect(Em.meta(this.obj).descs.prop4._dependentKeys).to.eql(['App.someRandomTestingKey', 'prop2']); + }); + + it('prop5 dependent keys are valid', function () { + expect(Em.meta(this.obj).descs.prop5._dependentKeys).to.eql(['prop1', 'App.someRandomTestingKey']); + }); + }); describe('#lt', function () { beforeEach(function () { + App.set('someAnotherKey', 0); this.obj = Em.Object.create({ prop1: 2, - prop2: Em.computed.lt('prop1', 1) + prop2: Em.computed.lt('prop1', 1), + prop3: Em.computed.lt('App.someRandomTestingKey', 1) }); }); @@ -400,15 +716,30 @@ describe('Ember.computed macros', function () { expect(this.obj.get('prop2')).to.be.true; }); + it('prop3 depends on App.* key', function () { + expect(this.obj.get('prop3')).to.be.true; + App.set('someAnotherKey', 1); + expect(this.obj.get('prop3')).to.be.false; + App.set('someAnotherKey', 2); + expect(this.obj.get('prop3')).to.be.false; + }); + + it('prop3 dependent keys are valid', function () { + expect(Em.meta(this.obj).descs.prop3._dependentKeys).to.eql(['App.someRandomTestingKey']); + }); + }); describe('#ltProperties', function () { beforeEach(function () { + App.set('someAnotherKey', 1); this.obj = Em.Object.create({ prop1: 2, prop2: 1, - prop3: Em.computed.ltProperties('prop1', 'prop2') + prop3: Em.computed.ltProperties('prop1', 'prop2'), + prop4: Em.computed.ltProperties('App.someRandomTestingKey', 'prop2'), + prop5: Em.computed.ltProperties('prop1', 'App.someRandomTestingKey') }); }); @@ -426,6 +757,30 @@ describe('Ember.computed macros', function () { expect(this.obj.get('prop3')).to.be.true; }); + it('prop4 depends on App.* key', function () { + expect(this.obj.get('prop4')).to.be.false; + App.set('someAnotherKey', 0); + expect(this.obj.get('prop4')).to.be.true; + App.set('someAnotherKey', 2); + expect(this.obj.get('prop4')).to.be.false; + }); + + it('prop5 depends on App.* key', function () { + expect(this.obj.get('prop5')).to.be.false; + App.set('someAnotherKey', 2); + expect(this.obj.get('prop5')).to.be.false; + App.set('someAnotherKey', 3); + expect(this.obj.get('prop5')).to.be.true; + }); + + it('prop4 dependent keys are valid', function () { + expect(Em.meta(this.obj).descs.prop4._dependentKeys).to.eql(['App.someRandomTestingKey', 'prop2']); + }); + + it('prop5 dependent keys are valid', function () { + expect(Em.meta(this.obj).descs.prop5._dependentKeys).to.eql(['prop1', 'App.someRandomTestingKey']); + }); + }); describe('#match', function () { @@ -581,6 +936,7 @@ describe('Ember.computed macros', function () { describe('#alias', function() { beforeEach(function () { + App.set('someAnotherKey', {a: {b: 1}}); this.obj = Em.Object.create({ prop1: { a: { @@ -589,7 +945,8 @@ describe('Ember.computed macros', function () { } } }, - prop2: Em.computed.alias('prop1.a.b.c') + prop2: Em.computed.alias('prop1.a.b.c'), + prop3: Em.computed.alias('App.someAnotherKey.a.b') }) }); @@ -602,6 +959,16 @@ describe('Ember.computed macros', function () { expect(this.obj.get('prop2')).to.equal(2); }); + it('prop3 depends on App.* key', function () { + expect(this.obj.get('prop3')).to.equal(1); + App.set('someAnotherKey.a.b', 4); + expect(this.obj.get('prop3')).to.equal(4); + }); + + it('prop3 dependent keys are valid', function () { + expect(Em.meta(this.obj).descs.prop3._dependentKeys).to.eql(['App.someAnotherKey.a.b']); + }); + }); describe('#existsIn', function () { @@ -632,14 +999,24 @@ describe('Ember.computed macros', function () { describe('#percents', function () { beforeEach(function () { + App.setProperties({ + p1: 25, + p2: 100 + }); this.obj = Em.Object.create({ prop1: 10, prop2: 25, prop3: Em.computed.percents('prop1', 'prop2'), - prop4: Em.computed.percents('prop1', 'prop2', 2) + prop4: Em.computed.percents('prop1', 'prop2', 2), + prop5: Em.computed.percents('App.p1', 'App.p2', 1) }); }); + afterEach(function () { + delete App.p1; + delete App.p2; + }); + it('should calculate percents', function () { expect(this.obj.get('prop3')).to.equal(40); expect(this.obj.get('prop4')).to.equal(40.00); @@ -671,6 +1048,18 @@ describe('Ember.computed macros', function () { expect(this.obj.get('prop4')).to.equal(10.60); }); + it('prop5 depends on App.* keys', function () { + expect(this.obj.get('prop5')).to.equal(25.0); + App.set('p2', 50); + expect(this.obj.get('prop5')).to.equal(50.0); + App.set('p1', 10); + expect(this.obj.get('prop5')).to.equal(20.0); + }); + + it('prop4 dependent keys are valid', function () { + expect(Em.meta(this.obj).descs.prop5._dependentKeys).to.eql(['App.p1', 'App.p2']); + }); + }); describe('#formatRole', function () { @@ -730,11 +1119,21 @@ describe('Ember.computed macros', function () { expect(this.obj.get('prop2')).to.equal(10); }); + it('0 for empty collection', function () { + this.obj.set('prop1', []); + expect(this.obj.get('prop2')).to.equal(0); + }); + }); describe('#i18nFormat', function () { beforeEach(function () { + + App.setProperties({ + someAnotherKey: 'some value' + }); + sinon.stub(Em.I18n, 't', function (key) { var msgs = { key1: '{0} {1} {2}' @@ -746,7 +1145,8 @@ describe('Ember.computed macros', function () { prop2: 'cba', prop3: 'aaa', prop4: Em.computed.i18nFormat('key1', 'prop1', 'prop2', 'prop3'), - prop5: Em.computed.i18nFormat('not_existing_key', 'prop1', 'prop2', 'prop3') + prop5: Em.computed.i18nFormat('not_existing_key', 'prop1', 'prop2', 'prop3'), + prop6: Em.computed.i18nFormat('key1', 'App.someRandomTestingKey', 'prop2', 'prop3') }); }); @@ -771,16 +1171,33 @@ describe('Ember.computed macros', function () { expect(this.obj.get('prop5')).to.equal(''); }); + it('`prop6` depends on App.* key', function () { + expect(this.obj.get('prop6')).to.equal('some value cba aaa'); + App.set('someAnotherKey', ''); + expect(this.obj.get('prop6')).to.equal(' cba aaa'); + }); + + it('prop6 dependent keys are valid', function () { + expect(Em.meta(this.obj).descs.prop6._dependentKeys).to.eql(['App.someRandomTestingKey', 'prop2', 'prop3']); + }); + }); describe('#concat', function () { beforeEach(function () { + + App.setProperties({ + someAnotherKey: 'some value' + }); + this.obj = Em.Object.create({ prop1: 'abc', prop2: 'cba', prop3: 'aaa', - prop4: Em.computed.concat(' ', 'prop1', 'prop2', 'prop3') + prop4: Em.computed.concat(' ', 'prop1', 'prop2', 'prop3'), + prop5: Em.computed.concat(' ', 'App.someRandomTestingKey', 'prop2', 'prop3'), + prop6: Em.computed.concat(' ') }); }); @@ -793,6 +1210,20 @@ describe('Ember.computed macros', function () { expect(this.obj.get('prop4')).to.equal('aaa cba aaa'); }); + it('`prop5` depends on App.* key', function () { + expect(this.obj.get('prop5')).to.equal('some value cba aaa'); + App.set('someAnotherKey', ''); + expect(this.obj.get('prop5')).to.equal(' cba aaa'); + }); + + it('prop5 dependent keys are valid', function () { + expect(Em.meta(this.obj).descs.prop5._dependentKeys).to.eql(['App.someRandomTestingKey', 'prop2', 'prop3']); + }); + + it('prop6 without dependent keys', function () { + expect(this.obj.get('prop6')).to.equal(''); + }); + }); describe('#notExistsIn', function () { @@ -823,11 +1254,18 @@ describe('Ember.computed macros', function () { describe('#firstNotBlank', function () { beforeEach(function () { + + App.setProperties({ + someAnotherKey: 'NOT-EMPTY-STRING' + }); + this.obj = Em.Object.create({ prop1: '', prop2: null, prop3: '1234', - prop4: Em.computed.firstNotBlank('prop1', 'prop2', 'prop3') + prop4: Em.computed.firstNotBlank('prop1', 'prop2', 'prop3'), + prop5: Em.computed.firstNotBlank('prop1', 'App.someRandomTestingKey', 'prop3'), + prop6: Em.computed.firstNotBlank('prop1', 'prop2') }) }); @@ -850,6 +1288,22 @@ describe('Ember.computed macros', function () { expect(this.obj.get('prop4')).to.equal('prop1 is used'); }); + it('`prop5` depends on App.* key', function () { + expect(this.obj.get('prop5')).to.equal('NOT-EMPTY-STRING'); + App.set('someAnotherKey', '!!!!!!!'); + expect(this.obj.get('prop5')).to.equal('!!!!!!!'); + App.set('someAnotherKey', null); + expect(this.obj.get('prop5')).to.equal('1234'); + }); + + it('prop5 dependent keys are valid', function () { + expect(Em.meta(this.obj).descs.prop5._dependentKeys).to.eql(['prop1', 'App.someRandomTestingKey', 'prop3']); + }); + + it('prop6 depends on blank values', function () { + expect(this.obj.get('prop6')).to.be.null; + }); + }); }); \ No newline at end of file