mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-15 19:26:42 +08:00
364 lines
12 KiB
TypeScript
364 lines
12 KiB
TypeScript
import { assert, assertEqual } from "../tk-unit";
|
|
import { DOMNode } from "tns-core-modules/debugger/dom-node";
|
|
import { attachDOMInspectorCommandCallbacks, attachCSSInspectorCommandCallbacks, attachDOMInspectorEventCallbacks } from "tns-core-modules/debugger/devtools-elements";
|
|
import { InspectorCommands, InspectorEvents } from "tns-core-modules/debugger/devtools-elements";
|
|
import { unsetValue } from "tns-core-modules/ui/core/properties";
|
|
import { Button } from "tns-core-modules/ui/button";
|
|
import { Slider } from "tns-core-modules/ui/slider";
|
|
import { Label } from "tns-core-modules/ui/label";
|
|
import { textProperty } from "tns-core-modules/ui/text-base";
|
|
import { TextView } from "tns-core-modules/ui/text-view";
|
|
import { StackLayout } from "tns-core-modules/ui/layouts/stack-layout";
|
|
import { isAndroid } from "tns-core-modules/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.");
|
|
}
|