-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
dom-node-tests.ts
363 lines (290 loc) · 11.7 KB
/
dom-node-tests.ts
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
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
import { assert, assertEqual } from "../tk-unit";
import { DOMNode } from "@nativescript/core/debugger/dom-node";
import { attachDOMInspectorCommandCallbacks, attachCSSInspectorCommandCallbacks, attachDOMInspectorEventCallbacks } from "@nativescript/core/debugger/devtools-elements";
import { InspectorCommands, InspectorEvents } from "@nativescript/core/debugger/devtools-elements";
import { unsetValue } from "@nativescript/core/ui/core/properties";
import { Button } from "@nativescript/core/ui/button";
import { Slider } from "@nativescript/core/ui/slider";
import { Label } from "@nativescript/core/ui/label";
import { textProperty } from "@nativescript/core/ui/text-base";
import { TextView } from "@nativescript/core/ui/text-view";
import { StackLayout } from "@nativescript/core/ui/layouts/stack-layout";
import { isAndroid } from "@nativescript/core/platform/platform";
let originalInspectorGlobal: InspectorCommands & InspectorEvents;
let currentInspector: InspectorCommands & InspectorEvents;
function getTestInspector(): InspectorCommands & InspectorEvents {
let inspector = {
getDocument(): any { return {}; },
removeNode(nodeId: number): void { /* */ },
getComputedStylesForNode(nodeId: number): any { return []; },
setAttributeAsText(nodeId: number, text: string, name: string): void { /* */ },
childNodeInserted(parentId: number, lastId: number, node: string | DOMNode): void { /* to be replaced */ },
childNodeRemoved(parentId: number, nodeId: number): void { /* to be replaced */ },
attributeModified(nodeId: number, attrName: string, attrValue: string) { /* to be replaced */ },
attributeRemoved(nodeId: number, attrName: string) { /* to be replaced */ }
};
attachDOMInspectorCommandCallbacks(inspector);
attachDOMInspectorEventCallbacks(inspector);
attachCSSInspectorCommandCallbacks(inspector);
return inspector;
}
function getIOSDOMInspector() {
return {
events: {
childNodeInserted(parentId: number, lastId: number, node: DOMNode): void { return; },
childNodeRemoved(parentId: number, nodeId: number): void { return; },
attributeModified(nodeId: number, attrName: string, attrValue: string): void { return; },
attributeRemoved(nodeId: number, attrName: string): void { return; }
},
commands: {
getDocument(): any { return {}; },
removeNode(nodeId: number): void { /* */ },
getComputedStylesForNode(nodeId: number): any { return []; },
setAttributeAsText(nodeId: number, text: string, name: string): void { /* */ }
}
};
}
export function setUp(): void {
if (isAndroid) {
originalInspectorGlobal = global.__inspector;
currentInspector = getTestInspector();
global.__inspector = currentInspector;
} else {
let domInspector = getIOSDOMInspector();
currentInspector = getTestInspector();
domInspector.events = currentInspector;
}
}
export function tearDown(): void {
if (isAndroid) {
global.__inspector = originalInspectorGlobal;
}
}
function assertAttribute(domNode: DOMNode, name: string, value: any) {
const propIdx = domNode.attributes.indexOf(name);
assert(propIdx >= 0, `Attribute ${name} not found`);
assertEqual(domNode.attributes[propIdx + 1], value);
}
export function test_custom_attribute_is_reported_in_dom_node() {
const btn = new Button();
btn["test_prop"] = "test_value";
btn.ensureDomNode();
const domNode = btn.domNode;
assertAttribute(domNode, "test_prop", "test_value");
}
export function test_custom__falsy_attribute_is_reported_in_dom_node() {
const btn = new Button();
btn["test_prop_null"] = null;
btn["test_prop_0"] = 0;
btn["test_prop_undefined"] = undefined;
btn["test_prop_empty_string"] = "";
btn.ensureDomNode();
const domNode = btn.domNode;
assertAttribute(domNode, "test_prop_null", null + "");
assertAttribute(domNode, "test_prop_0", 0 + "");
assertAttribute(domNode, "test_prop_undefined", undefined + "");
assertAttribute(domNode, "test_prop_empty_string", "");
}
export function test_property_is_reported_in_dom_node() {
const btn = new Button();
btn.text = "test_value";
btn.ensureDomNode();
const domNode = btn.domNode;
assertAttribute(domNode, "text", "test_value");
}
export function test_childNodeInserted_in_dom_node() {
let childNodeInsertedCalled = false;
let actualParentId = 0;
let expectedParentId = 0;
currentInspector.childNodeInserted = (parentId, lastNodeId, node) => {
childNodeInsertedCalled = true;
actualParentId = parentId;
};
const stack = new StackLayout();
stack.ensureDomNode();
expectedParentId = stack._domId;
const btn1 = new Button();
btn1.text = "button1";
stack.addChild(btn1);
assert(childNodeInsertedCalled, "global inspector childNodeInserted not called.");
assertEqual(actualParentId, expectedParentId);
}
export function test_childNodeInserted_at_index_in_dom_node() {
const stack = new StackLayout();
stack.ensureDomNode();
// child index 0
const btn1 = new Button();
btn1.text = "button1";
stack.addChild(btn1);
// child index 1
const btn2 = new Button();
btn2.text = "button2";
stack.addChild(btn2);
// child index 2
const btn3 = new Button();
btn3.text = "button3";
stack.addChild(btn3);
const lbl = new Label();
lbl.text = "label me this";
let called = false;
currentInspector.childNodeInserted = (parentId, lastNodeId, node: any) => {
assertEqual(lastNodeId, btn1._domId, "Child inserted at index 1's previous sibling does not match.");
assertEqual(node.toObject().nodeId, lbl._domId, "Child id doesn't match");
called = true;
};
stack.insertChild(lbl, 1);
assert(called, "childNodeInserted not called");
}
export function test_childNodeRemoved_in_dom_node() {
let childNodeRemovedCalled = false;
let actualRemovedNodeId = 0;
let expectedRemovedNodeId = 0;
currentInspector.childNodeRemoved = (parentId, nodeId) => {
childNodeRemovedCalled = true;
actualRemovedNodeId = nodeId;
};
const stack = new StackLayout();
stack.ensureDomNode();
const btn1 = new Button();
btn1.text = "button1";
expectedRemovedNodeId = btn1._domId;
stack.addChild(btn1);
const btn2 = new Button();
btn2.text = "button2";
stack.addChild(btn2);
stack.removeChild(btn1);
console.log("btn2: " + btn2);
assert(childNodeRemovedCalled, "global inspector childNodeRemoved not called.");
assertEqual(actualRemovedNodeId, expectedRemovedNodeId);
}
export function test_falsy_property_is_reported_in_dom_node() {
const btn = new Button();
btn.text = null;
btn.ensureDomNode();
const domNode = btn.domNode;
assertAttribute(domNode, "text", "null");
btn.text = undefined;
domNode.loadAttributes();
assertAttribute(domNode, "text", "undefined");
}
export function test_property_change_calls_attributeModified() {
const btn = new Button();
btn.ensureDomNode();
const domNode = btn.domNode;
let callbackCalled = false;
currentInspector.attributeModified = (nodeId: number, attrName: string, attrValue: string) => {
assertEqual(nodeId, domNode.nodeId, "nodeId");
assertEqual(attrName, "text", "attrName");
assertEqual(attrValue, "new value", "attrValue");
callbackCalled = true;
};
btn.text = "new value";
assert(callbackCalled, "attributeModified not called");
}
export function test_property_change_from_native_calls_attributeModified() {
const tv = new TextView();
tv.ensureDomNode();
const domNode = tv.domNode;
let callbackCalled = false;
currentInspector.attributeModified = (nodeId: number, attrName: string, attrValue: string) => {
assertEqual(nodeId, domNode.nodeId, "nodeId");
assertEqual(attrName, "text", "attrName");
assertEqual(attrValue, "new value", "attrValue");
callbackCalled = true;
};
textProperty.nativeValueChange(tv, "new value");
assert(callbackCalled, "attributeModified not called");
}
export function test_property_reset_calls_attributeRemoved() {
const btn = new Button();
btn.text = "some value";
btn.ensureDomNode();
const domNode = btn.domNode;
let callbackCalled = false;
currentInspector.attributeRemoved = (nodeId: number, attrName: string) => {
assertEqual(nodeId, domNode.nodeId, "nodeId");
assertEqual(attrName, "text", "attrName");
callbackCalled = true;
};
btn.text = unsetValue;
assert(callbackCalled, "attributeRemoved not called");
}
export function test_coercible_property_change_calls_attributeModified() {
const slider = new Slider();
slider.ensureDomNode();
const domNode = slider.domNode;
let callbackCalled = false;
currentInspector.attributeModified = (nodeId: number, attrName: string, attrValue: string) => {
assertEqual(nodeId, domNode.nodeId, "nodeId");
assertEqual(attrName, "value", "attrName");
assertEqual(attrValue, "10", "attrValue");
callbackCalled = true;
};
slider.value = 10;
assert(callbackCalled, "attributeModified not called");
}
export function test_coercible_property_reset_calls_attributeRemoved() {
const slider = new Slider();
slider.value = 10;
slider.ensureDomNode();
const domNode = slider.domNode;
let callbackCalled = false;
currentInspector.attributeRemoved = (nodeId: number, attrName: string) => {
assertEqual(nodeId, domNode.nodeId, "nodeId");
assertEqual(attrName, "value", "attrName");
callbackCalled = true;
};
slider.value = unsetValue;
assert(callbackCalled, "attributeRemoved not called");
}
export function test_inspector_ui_setAttributeAsText_set_existing_property() {
// Arrange
const label = new Label();
label.text = "original label";
const expectedValue = "updated label";
label.ensureDomNode();
// Act
// simulate call from the inspector UI
currentInspector.setAttributeAsText(label.domNode.nodeId, "text='" + expectedValue + "'", "text");
// Assert
assertEqual(label.text, expectedValue);
}
export function test_inspector_ui_setAttributeAsText_remove_existing_property() {
// Arrange
const label = new Label();
label.text = "original label";
label.ensureDomNode();
// Act
// simulate call from the inspector UI
currentInspector.setAttributeAsText(label.domNode.nodeId, "" /* empty value - removes the attribute */, "text");
// Assert
assertEqual(label.text, "");
}
export function test_inspector_ui_setAttributeAsText_set_new_property() {
// Arrange
const label = new Label();
const expectedValue = "custom";
label.ensureDomNode();
// Act
// simulate call from the inspector UI
currentInspector.setAttributeAsText(label.domNode.nodeId, "data-attr='" + expectedValue + "'" /* data-attr="custom" */, " " /* empty attr name initially */);
// Assert
assertEqual(label["data-attr"], expectedValue);
}
export function test_inspector_ui_removeNode() {
let childNodeRemovedCalled = false;
let stack = new StackLayout();
let label = new Label();
stack.addChild(label);
stack.ensureDomNode();
label.ensureDomNode();
let expectedParentId = stack.domNode.nodeId;
let expectedNodeId = label.domNode.nodeId;
currentInspector.childNodeRemoved = (parentId, nodeId) => {
childNodeRemovedCalled = true;
assertEqual(parentId, expectedParentId);
assertEqual(nodeId, expectedNodeId);
};
currentInspector.removeNode(label.domNode.nodeId);
assert(childNodeRemovedCalled, "childNodeRemoved callback not called.");
}