forked from emberjs/ember.js
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a failing test for emberjs#12475
- Loading branch information
Showing
2 changed files
with
160 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
155 changes: 155 additions & 0 deletions
155
packages/ember-runtime/tests/system/array_proxy/watching_and_listening_test.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
import { get } from 'ember-metal/property_get'; | ||
import { listenersFor } from 'ember-metal/events'; | ||
import { addObserver } from 'ember-metal/observer'; | ||
import { defineProperty } from 'ember-metal/properties'; | ||
import { watcherCount } from 'ember-metal/watching'; | ||
import computed from 'ember-metal/computed'; | ||
import ArrayProxy from 'ember-runtime/system/array_proxy'; | ||
import { A } from 'ember-runtime/system/native_array'; | ||
|
||
function sortedListenersFor(obj, eventName) { | ||
return listenersFor(obj, eventName).sort((listener1, listener2) => { | ||
return (listener1[1] > listener2[1]) ? -1 : 1; | ||
}); | ||
} | ||
|
||
QUnit.module('ArrayProxy - watching and listening'); | ||
|
||
QUnit.test(`setting 'content' adds listeners correctly`, function() { | ||
let content = A(); | ||
let proxy = ArrayProxy.create(); | ||
|
||
deepEqual(sortedListenersFor(content, '@array:before'), []); | ||
deepEqual(sortedListenersFor(content, '@array:change'), []); | ||
|
||
proxy.set('content', content); | ||
|
||
deepEqual( | ||
sortedListenersFor(content, '@array:before'), | ||
[[proxy, 'contentArrayWillChange'], [proxy, 'arrangedContentArrayWillChange']] | ||
); | ||
deepEqual( | ||
sortedListenersFor(content, '@array:change'), | ||
[[proxy, 'contentArrayDidChange'], [proxy, 'arrangedContentArrayDidChange']] | ||
); | ||
}); | ||
|
||
QUnit.test(`changing 'content' adds and removes listeners correctly`, function() { | ||
let content1 = A(); | ||
let content2 = A(); | ||
let proxy = ArrayProxy.create({ content: content1 }); | ||
|
||
deepEqual( | ||
sortedListenersFor(content1, '@array:before'), | ||
[[proxy, 'contentArrayWillChange'], [proxy, 'arrangedContentArrayWillChange']] | ||
); | ||
deepEqual( | ||
sortedListenersFor(content1, '@array:change'), | ||
[[proxy, 'contentArrayDidChange'], [proxy, 'arrangedContentArrayDidChange']] | ||
); | ||
|
||
proxy.set('content', content2); | ||
|
||
deepEqual(sortedListenersFor(content1, '@array:before'), []); | ||
deepEqual(sortedListenersFor(content1, '@array:change'), []); | ||
deepEqual( | ||
sortedListenersFor(content2, '@array:before'), | ||
[[proxy, 'contentArrayWillChange'], [proxy, 'arrangedContentArrayWillChange']] | ||
); | ||
deepEqual( | ||
sortedListenersFor(content2, '@array:change'), | ||
[[proxy, 'contentArrayDidChange'], [proxy, 'arrangedContentArrayDidChange']] | ||
); | ||
}); | ||
|
||
QUnit.test(`regression test for https://github.com/emberjs/ember.js/issues/12475`, function() { | ||
let item1a = { id: 1 }; | ||
let item1b = { id: 2 }; | ||
let item1c = { id: 3 }; | ||
let content1 = A([item1a, item1b, item1c]); | ||
|
||
let proxy = ArrayProxy.create({ content: content1 }); | ||
let obj = { proxy }; | ||
|
||
defineProperty(obj, 'ids', computed('[email protected]', function() { | ||
return get(this, 'proxy').mapBy('id'); | ||
})); | ||
|
||
// These manually added observers are to simulate the observers added by the | ||
// rendering process in a template like: | ||
// | ||
// {{#each items as |item|}} | ||
// {{item.id}} | ||
// {{/each}} | ||
addObserver(item1a, 'id', function() { }); | ||
addObserver(item1b, 'id', function() { }); | ||
addObserver(item1c, 'id', function() { }); | ||
|
||
// The EachProxy has not yet been consumed. Only the manually added | ||
// observers are watching. | ||
equal(watcherCount(item1a, 'id'), 1); | ||
equal(watcherCount(item1b, 'id'), 1); | ||
equal(watcherCount(item1c, 'id'), 1); | ||
|
||
// Consume the each proxy. This causes the EachProxy to add two observers | ||
// per item: one for "before" events and one for "after" events. | ||
deepEqual(get(obj, 'ids'), [1, 2, 3]); | ||
|
||
// For each item, the two each proxy observers and one manual added observer | ||
// are watching. | ||
equal(watcherCount(item1a, 'id'), 3); | ||
equal(watcherCount(item1b, 'id'), 3); | ||
equal(watcherCount(item1c, 'id'), 3); | ||
|
||
// This should be a no-op because observers do not fire if the value | ||
// 1. is an object and 2. is the same as the old value. | ||
proxy.set('content', content1); | ||
|
||
equal(watcherCount(item1a, 'id'), 3); | ||
equal(watcherCount(item1b, 'id'), 3); | ||
equal(watcherCount(item1c, 'id'), 3); | ||
|
||
// This is repeated to catch the regression. It should still be a no-op. | ||
proxy.set('content', content1); | ||
|
||
equal(watcherCount(item1a, 'id'), 3); | ||
equal(watcherCount(item1b, 'id'), 3); | ||
equal(watcherCount(item1c, 'id'), 3); | ||
|
||
// Set the content to a new array with completely different items and | ||
// repeat the process. | ||
let item2a = { id: 4 }; | ||
let item2b = { id: 5 }; | ||
let item2c = { id: 6 }; | ||
let content2 = A([item2a, item2b, item2c]); | ||
|
||
addObserver(item2a, 'id', function() { }); | ||
addObserver(item2b, 'id', function() { }); | ||
addObserver(item2c, 'id', function() { }); | ||
|
||
proxy.set('content', content2); | ||
|
||
deepEqual(get(obj, 'ids'), [4, 5, 6]); | ||
|
||
equal(watcherCount(item2a, 'id'), 3); | ||
equal(watcherCount(item2b, 'id'), 3); | ||
equal(watcherCount(item2c, 'id'), 3); | ||
|
||
// Ensure that the observers added by the EachProxy on all items in the | ||
// first content array have been torn down. | ||
equal(watcherCount(item1a, 'id'), 1); | ||
equal(watcherCount(item1b, 'id'), 1); | ||
equal(watcherCount(item1c, 'id'), 1); | ||
|
||
proxy.set('content', content2); | ||
|
||
equal(watcherCount(item2a, 'id'), 3); | ||
equal(watcherCount(item2b, 'id'), 3); | ||
equal(watcherCount(item2c, 'id'), 3); | ||
|
||
proxy.set('content', content2); | ||
|
||
equal(watcherCount(item2a, 'id'), 3); | ||
equal(watcherCount(item2b, 'id'), 3); | ||
equal(watcherCount(item2c, 'id'), 3); | ||
}); |