Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
81165 views
1
/**
2
* Copyright 2013-2014, Facebook, Inc.
3
* All rights reserved.
4
*
5
* This source code is licensed under the BSD-style license found in the
6
* LICENSE file in the root directory of this source tree. An additional grant
7
* of patent rights can be found in the PATENTS file in the same directory.
8
*
9
* @emails react-core
10
*/
11
12
"use strict";
13
14
describe('DOMPropertyOperations', function() {
15
var DOMPropertyOperations;
16
var DOMProperty;
17
18
var mocks;
19
20
beforeEach(function() {
21
require('mock-modules').dumpCache();
22
var ReactDefaultInjection = require('ReactDefaultInjection');
23
ReactDefaultInjection.inject();
24
25
DOMPropertyOperations = require('DOMPropertyOperations');
26
DOMProperty = require('DOMProperty');
27
28
mocks = require('mocks');
29
});
30
31
describe('createMarkupForProperty', function() {
32
33
it('should create markup for simple properties', function() {
34
expect(DOMPropertyOperations.createMarkupForProperty(
35
'name',
36
'simple'
37
)).toBe('name="simple"');
38
39
expect(DOMPropertyOperations.createMarkupForProperty(
40
'name',
41
false
42
)).toBe('name="false"');
43
44
expect(DOMPropertyOperations.createMarkupForProperty(
45
'name',
46
null
47
)).toBe('');
48
});
49
50
it('should work with the id attribute', function() {
51
expect(DOMPropertyOperations.createMarkupForProperty(
52
'id',
53
'simple'
54
)).toBe('id="simple"');
55
});
56
57
it('should warn about incorrect casing', function() {
58
spyOn(console, 'warn');
59
expect(DOMPropertyOperations.createMarkupForProperty(
60
'tabindex',
61
'1'
62
)).toBe(null);
63
expect(console.warn.argsForCall.length).toBe(1);
64
expect(console.warn.argsForCall[0][0]).toContain('tabIndex');
65
});
66
67
it('should warn about class', function() {
68
spyOn(console, 'warn');
69
expect(DOMPropertyOperations.createMarkupForProperty(
70
'class',
71
'muffins'
72
)).toBe(null);
73
expect(console.warn.argsForCall.length).toBe(1);
74
expect(console.warn.argsForCall[0][0]).toContain('className');
75
});
76
77
it('should create markup for boolean properties', function() {
78
expect(DOMPropertyOperations.createMarkupForProperty(
79
'checked',
80
'simple'
81
)).toBe('checked');
82
83
expect(DOMPropertyOperations.createMarkupForProperty(
84
'checked',
85
true
86
)).toBe('checked');
87
88
expect(DOMPropertyOperations.createMarkupForProperty(
89
'checked',
90
false
91
)).toBe('');
92
});
93
94
it('should create markup for booleanish properties', function() {
95
expect(DOMPropertyOperations.createMarkupForProperty(
96
'download',
97
'simple'
98
)).toBe('download="simple"');
99
100
expect(DOMPropertyOperations.createMarkupForProperty(
101
'download',
102
true
103
)).toBe('download');
104
105
expect(DOMPropertyOperations.createMarkupForProperty(
106
'download',
107
'true'
108
)).toBe('download="true"');
109
110
expect(DOMPropertyOperations.createMarkupForProperty(
111
'download',
112
false
113
)).toBe('');
114
115
expect(DOMPropertyOperations.createMarkupForProperty(
116
'download',
117
'false'
118
)).toBe('download="false"');
119
120
expect(DOMPropertyOperations.createMarkupForProperty(
121
'download',
122
undefined
123
)).toBe('');
124
125
expect(DOMPropertyOperations.createMarkupForProperty(
126
'download',
127
null
128
)).toBe('');
129
130
expect(DOMPropertyOperations.createMarkupForProperty(
131
'download',
132
0
133
)).toBe('download="0"');
134
});
135
136
it('should create markup for custom attributes', function() {
137
expect(DOMPropertyOperations.createMarkupForProperty(
138
'aria-label',
139
'simple'
140
)).toBe('aria-label="simple"');
141
142
expect(DOMPropertyOperations.createMarkupForProperty(
143
'aria-label',
144
false
145
)).toBe('aria-label="false"');
146
147
expect(DOMPropertyOperations.createMarkupForProperty(
148
'aria-label',
149
null
150
)).toBe('');
151
});
152
153
it('should create markup for numeric properties', function() {
154
expect(DOMPropertyOperations.createMarkupForProperty(
155
'start',
156
5
157
)).toBe('start="5"');
158
159
expect(DOMPropertyOperations.createMarkupForProperty(
160
'start',
161
0
162
)).toBe('start="0"');
163
164
expect(DOMPropertyOperations.createMarkupForProperty(
165
'size',
166
0
167
)).toBe('');
168
169
expect(DOMPropertyOperations.createMarkupForProperty(
170
'size',
171
1
172
)).toBe('size="1"');
173
});
174
175
});
176
177
describe('setValueForProperty', function() {
178
var stubNode;
179
180
beforeEach(function() {
181
stubNode = document.createElement('div');
182
});
183
184
it('should set values as properties by default', function() {
185
DOMPropertyOperations.setValueForProperty(stubNode, 'title', 'Tip!');
186
expect(stubNode.title).toBe('Tip!');
187
});
188
189
it('should set values as attributes if necessary', function() {
190
DOMPropertyOperations.setValueForProperty(stubNode, 'role', '#');
191
expect(stubNode.getAttribute('role')).toBe('#');
192
expect(stubNode.role).toBeUndefined();
193
});
194
195
it('should convert attribute values to string first', function() {
196
// Browsers default to this behavior, but some test environments do not.
197
// This ensures that we have consistent behavior.
198
var obj = {toString: function() { return '<html>'; }};
199
DOMPropertyOperations.setValueForProperty(stubNode, 'role', obj);
200
expect(stubNode.getAttribute('role')).toBe('<html>');
201
});
202
203
it('should remove for falsey boolean properties', function() {
204
DOMPropertyOperations.setValueForProperty(
205
stubNode,
206
'allowFullScreen',
207
false
208
);
209
expect(stubNode.hasAttribute('allowFullScreen')).toBe(false);
210
});
211
212
it('should remove when setting custom attr to null', function() {
213
DOMPropertyOperations.setValueForProperty(
214
stubNode,
215
'data-foo',
216
'bar'
217
);
218
expect(stubNode.hasAttribute('data-foo')).toBe(true);
219
DOMPropertyOperations.setValueForProperty(
220
stubNode,
221
'data-foo',
222
null
223
);
224
expect(stubNode.hasAttribute('data-foo')).toBe(false);
225
});
226
227
it('should use mutation method where applicable', function() {
228
var foobarSetter = mocks.getMockFunction();
229
// inject foobar DOM property
230
DOMProperty.injection.injectDOMPropertyConfig({
231
Properties: {foobar: null},
232
DOMMutationMethods: {
233
foobar: foobarSetter
234
}
235
});
236
237
DOMPropertyOperations.setValueForProperty(
238
stubNode,
239
'foobar',
240
'cows say moo'
241
);
242
243
expect(foobarSetter.mock.calls.length).toBe(1);
244
expect(foobarSetter.mock.calls[0][0]).toBe(stubNode);
245
expect(foobarSetter.mock.calls[0][1]).toBe('cows say moo');
246
});
247
248
it('should set className to empty string instead of null', function() {
249
DOMPropertyOperations.setValueForProperty(
250
stubNode,
251
'className',
252
'selected'
253
);
254
expect(stubNode.className).toBe('selected');
255
256
DOMPropertyOperations.setValueForProperty(
257
stubNode,
258
'className',
259
null
260
);
261
// className should be '', not 'null' or null (which becomes 'null' in
262
// some browsers)
263
expect(stubNode.className).toBe('');
264
});
265
266
it('should remove property properly even with different name', function() {
267
// Suppose 'foobar' is a property that corresponds to the underlying
268
// 'className' property:
269
DOMProperty.injection.injectDOMPropertyConfig({
270
Properties: {foobar: DOMProperty.injection.MUST_USE_PROPERTY},
271
DOMPropertyNames: {
272
foobar: 'className'
273
}
274
});
275
276
DOMPropertyOperations.setValueForProperty(
277
stubNode,
278
'foobar',
279
'selected'
280
);
281
expect(stubNode.className).toBe('selected');
282
283
DOMPropertyOperations.setValueForProperty(
284
stubNode,
285
'foobar',
286
null
287
);
288
// className should be '', not 'null' or null (which becomes 'null' in
289
// some browsers)
290
expect(stubNode.className).toBe('');
291
});
292
293
});
294
295
describe('injectDOMPropertyConfig', function() {
296
it('should support custom attributes', function() {
297
// foobar does not exist yet
298
expect(DOMPropertyOperations.createMarkupForProperty(
299
'foobar',
300
'simple'
301
)).toBe(null);
302
303
// foo-* does not exist yet
304
expect(DOMPropertyOperations.createMarkupForProperty(
305
'foo-xyz',
306
'simple'
307
)).toBe(null);
308
309
// inject foobar DOM property
310
DOMProperty.injection.injectDOMPropertyConfig({
311
isCustomAttribute: function(name) {
312
return name.indexOf('foo-') === 0;
313
},
314
Properties: {foobar: null}
315
});
316
317
// Ensure old attributes still work
318
expect(DOMPropertyOperations.createMarkupForProperty(
319
'name',
320
'simple'
321
)).toBe('name="simple"');
322
expect(DOMPropertyOperations.createMarkupForProperty(
323
'data-name',
324
'simple'
325
)).toBe('data-name="simple"');
326
327
// foobar should work
328
expect(DOMPropertyOperations.createMarkupForProperty(
329
'foobar',
330
'simple'
331
)).toBe('foobar="simple"');
332
333
// foo-* should work
334
expect(DOMPropertyOperations.createMarkupForProperty(
335
'foo-xyz',
336
'simple'
337
)).toBe('foo-xyz="simple"');
338
339
// It should complain about double injections.
340
expect(function() {
341
DOMProperty.injection.injectDOMPropertyConfig(
342
{Properties: {foobar: null}}
343
);
344
}).toThrow();
345
});
346
});
347
});
348
349