forked from emberjs/ember.js
/
alias_test.js
221 lines (165 loc) · 6.02 KB
/
alias_test.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
import {
alias,
defineProperty,
get,
set,
isWatching,
addObserver,
removeObserver,
tagFor,
tagForProperty,
} from '..';
import { meta } from '@ember/-internals/meta';
import { moduleFor, AbstractTestCase } from 'internal-test-helpers';
let obj, count;
function incrementCount() {
count++;
}
moduleFor(
'@ember/-internals/metal/alias',
class extends AbstractTestCase {
beforeEach() {
obj = { foo: { faz: 'FOO' } };
count = 0;
}
afterEach() {
obj = null;
}
['@test should proxy get to alt key'](assert) {
defineProperty(obj, 'bar', alias('foo.faz'));
assert.equal(get(obj, 'bar'), 'FOO');
}
['@test should proxy set to alt key'](assert) {
defineProperty(obj, 'bar', alias('foo.faz'));
set(obj, 'bar', 'BAR');
assert.equal(get(obj, 'foo.faz'), 'BAR');
}
['@test old dependent keys should not trigger property changes'](assert) {
let obj1 = Object.create(null);
defineProperty(obj1, 'foo', null, null);
defineProperty(obj1, 'bar', alias('foo'));
defineProperty(obj1, 'baz', alias('foo'));
defineProperty(obj1, 'baz', alias('bar')); // redefine baz
addObserver(obj1, 'baz', incrementCount);
set(obj1, 'foo', 'FOO');
assert.equal(count, 1);
removeObserver(obj1, 'baz', incrementCount);
set(obj1, 'foo', 'OOF');
assert.equal(count, 1);
}
[`@test inheriting an observer of the alias from the prototype then
redefining the alias on the instance to another property dependent on same key
does not call the observer twice`](assert) {
let obj1 = Object.create(null);
obj1.incrementCount = incrementCount;
meta(obj1).proto = obj1;
defineProperty(obj1, 'foo', null, null);
defineProperty(obj1, 'bar', alias('foo'));
defineProperty(obj1, 'baz', alias('foo'));
addObserver(obj1, 'baz', null, 'incrementCount');
let obj2 = Object.create(obj1);
defineProperty(obj2, 'baz', alias('bar')); // override baz
set(obj2, 'foo', 'FOO');
assert.equal(count, 1);
removeObserver(obj2, 'baz', null, 'incrementCount');
set(obj2, 'foo', 'OOF');
assert.equal(count, 1);
}
['@test an observer of the alias works if added after defining the alias'](assert) {
defineProperty(obj, 'bar', alias('foo.faz'));
addObserver(obj, 'bar', incrementCount);
assert.ok(isWatching(obj, 'foo.faz'));
set(obj, 'foo.faz', 'BAR');
assert.equal(count, 1);
}
['@test an observer of the alias works if added before defining the alias'](assert) {
addObserver(obj, 'bar', incrementCount);
defineProperty(obj, 'bar', alias('foo.faz'));
assert.ok(isWatching(obj, 'foo.faz'));
set(obj, 'foo.faz', 'BAR');
assert.equal(count, 1);
}
['@test object with alias is dirtied if interior object of alias is set after consumption'](
assert
) {
defineProperty(obj, 'bar', alias('foo.faz'));
get(obj, 'bar');
let tag = tagFor(obj);
let tagValue = tag.value();
set(obj, 'foo.faz', 'BAR');
assert.ok(!tag.validate(tagValue), 'setting the aliased key should dirty the object');
}
['@test setting alias on self should fail assertion']() {
expectAssertion(
() => defineProperty(obj, 'bar', alias('bar')),
"Setting alias 'bar' on self"
);
}
['@test destroyed alias does not disturb watch count'](assert) {
defineProperty(obj, 'bar', alias('foo.faz'));
assert.equal(get(obj, 'bar'), 'FOO');
assert.ok(isWatching(obj, 'foo.faz'));
defineProperty(obj, 'bar', null);
assert.notOk(isWatching(obj, 'foo.faz'));
}
['@test setting on oneWay alias does not disturb watch count'](assert) {
defineProperty(obj, 'bar', alias('foo.faz').oneWay());
assert.equal(get(obj, 'bar'), 'FOO');
assert.ok(isWatching(obj, 'foo.faz'));
set(obj, 'bar', null);
assert.notOk(isWatching(obj, 'foo.faz'));
}
['@test redefined alias with observer does not disturb watch count'](assert) {
defineProperty(obj, 'bar', alias('foo.faz').oneWay());
assert.equal(get(obj, 'bar'), 'FOO');
assert.ok(isWatching(obj, 'foo.faz'));
addObserver(obj, 'bar', incrementCount);
assert.equal(count, 0);
set(obj, 'bar', null);
assert.equal(count, 1);
assert.notOk(isWatching(obj, 'foo.faz'));
defineProperty(obj, 'bar', alias('foo.faz'));
assert.equal(count, 1);
assert.ok(isWatching(obj, 'foo.faz'));
set(obj, 'foo.faz', 'great');
assert.equal(count, 2);
}
['@test property tags are bumped when the source changes [GH#17243]'](assert) {
function assertPropertyTagChanged(obj, keyName, callback) {
let tag = tagForProperty(obj, keyName);
let before = tag.value();
callback();
let after = tag.value();
assert.notEqual(after, before, `tagForProperty ${keyName} should change`);
}
function assertPropertyTagUnchanged(obj, keyName, callback) {
let tag = tagForProperty(obj, keyName);
let before = tag.value();
callback();
let after = tag.value();
assert.equal(after, before, `tagForProperty ${keyName} should not change`);
}
defineProperty(obj, 'bar', alias('foo.faz'));
assertPropertyTagUnchanged(obj, 'bar', () => {
assert.equal(get(obj, 'bar'), 'FOO');
});
assertPropertyTagChanged(obj, 'bar', () => {
set(obj, 'foo.faz', 'BAR');
});
assertPropertyTagUnchanged(obj, 'bar', () => {
assert.equal(get(obj, 'bar'), 'BAR');
});
assertPropertyTagUnchanged(obj, 'bar', () => {
// trigger willWatch, then didUnwatch
addObserver(obj, 'bar', incrementCount);
removeObserver(obj, 'bar', incrementCount);
});
assertPropertyTagChanged(obj, 'bar', () => {
set(obj, 'foo.faz', 'FOO');
});
assertPropertyTagUnchanged(obj, 'bar', () => {
assert.equal(get(obj, 'bar'), 'FOO');
});
}
}
);