diff --git a/addon/index.js b/addon/index.js index f1c7505..76f7818 100644 --- a/addon/index.js +++ b/addon/index.js @@ -34,6 +34,8 @@ export default Ember.Mixin.create({ this._super(...arguments); let config = this.get('didChangeAttrsConfig'); + let equalityFn = config.isEqual || isEqual; + let trackedAttrs = config.attrs; let oldValues = this.get('_didChangeAttrsWeakMap').get(this); let changes = {}; @@ -43,7 +45,7 @@ export default Ember.Mixin.create({ let current = this.get(key); let previous = oldValues[key]; - if (!isEqual(key, previous, current)) { //TODO: configurable equality fn + if (!equalityFn(key, previous, current)) { changes[key] = { previous, current }; oldValues[key] = current; } diff --git a/tests/integration/did-change-attrs-test.js b/tests/integration/did-change-attrs-test.js index 3a0ac18..5636f31 100644 --- a/tests/integration/did-change-attrs-test.js +++ b/tests/integration/did-change-attrs-test.js @@ -32,6 +32,7 @@ test('Basic usage', function(assert) { this.set('isAdmin', false); this.render(hbs`{{x-changer email=email isAdmin=isAdmin name=name}}`); + assert.equal(didChangeAttrsCallCount, 0, '`didChangeAttrs` is not called on initial render'); this.set('email', 'emberjs@hamster.org'); @@ -47,3 +48,63 @@ test('Basic usage', function(assert) { this.set('name', 'TheTomster'); assert.equal(didChangeAttrsCallCount, 1, '`didChangeAttrs` is not called when an untracked attribute is changed'); }); + +test('Custom isEqual', function(assert) { + let changedAttrs, didChangeAttrsCallCount = 0; + + registerComponent(this, { + didChangeAttrsConfig: { + attrs: ['user', 'isAdmin'], + isEqual(key, a, b) { + if (key === 'user') { + return (a && b) ? a.id === b.id : a === b; + } + return a === b; + } + }, + + didChangeAttrs(changes) { + this._super(...arguments); + + didChangeAttrsCallCount++; + changedAttrs = changes; + } + }); + + this.set('user', { name: 'Tomster', id: '123' }); + this.set('isAdmin', false); + + this.render(hbs`{{x-changer user=user isAdmin=isAdmin}}`); + + assert.equal(didChangeAttrsCallCount, 0, '`didChangeAttrs` is not called on initial render'); + + this.set('user', { name: 'TheTomster', id: '123' }); + + assert.equal(didChangeAttrsCallCount, 0, '`didChangeAttrs` is not called because user entities are equal'); + + this.set('user', { name: 'Zoey', id: '456' }); + + assert.equal(didChangeAttrsCallCount, 1, '`didChangeAttrs` is called because user entities are not equal'); + assert.deepEqual(changedAttrs, { + user: { + previous: { + id: '123', + name: 'Tomster' + }, + current: { + id: '456', + name: 'Zoey' + } + } + }, '`user` included in `changedAttrs` because `user.id` is different'); + + this.set('isAdmin', true); + + assert.equal(didChangeAttrsCallCount, 2, '`didChangeAttrs` is called because isAdmin changed'); + assert.deepEqual(changedAttrs, { + isAdmin: { + previous: false, + current: true + } + }, '`isAdmin` included in `changedAttrs` because it changed'); +});