dijit
Version:
Dijit provides a complete collection of user interface controls based on Dojo, giving you the power to create web applications that are highly optimized for usability, performance, internationalization, accessibility, but above all deliver an incredible u
1,305 lines (1,097 loc) • 41.6 kB
HTML
<html lang="en">
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>dijit.Tree / dijit.tree.ObjectStoreModel automated test</title>
<script type="text/javascript" src="../boilerplate.js"></script>
<script type="text/javascript">
require([
"doh/runner",
"dojo/_base/array",
"dojo/aspect",
"dojo/cookie",
"dojo/dom-class",
"dojo/_base/lang",
"dojo/on",
"dojo/_base/window",
"dojo/promise/all",
"dojo/store/Memory",
"dojo/store/Observable",
"dijit/focus",
"dijit/registry",
"dijit/Tree",
"dijit/tree/ObjectStoreModel",
"dijit/tree/dndSource",
"dijit/tests/_data/geography",
"dijit/tests/AsyncMemoryStore",
"dijit/tests/helpers", // functions to help test
"dojo/domReady!"
], function(doh, array, aspect, cookie, domClass, lang, on, win, all, Memory, Observable,
focus, registry, Tree, ObjectStoreModel, dndSource, data, AsyncMemoryStore, helpers){
var myStore, myModel, myTree, myTree2, cache;
// Create / reset the data store and model, setting global-ish variables myStore and myModel
function setupStoreAndModel(/*Function*/ Store, /*Boolean*/ isObservable, idDataType){
if(!Store){
Store = Memory;
}
// Clone to sandbox tests that change data
var datacopy = lang.clone(data);
// id datatype switch:
// assume fetched data id is of type 'string', overwrite if needed
// store original id in a cache, so it can be retrieved later
var _id, i=0, l=datacopy.length;
cache = {};
for(i=0;i<l;i++){
_id = datacopy[i].id;
cache[_id] = idDataType=="float" ? Math.random() : idDataType=="int" ? i+1 : _id;
datacopy[i].id = cache[_id];
}
// replace parent
for(i=0;i<l;i++){
if(datacopy[i].hasOwnProperty("parent")){
datacopy[i].parent = cache[datacopy[i].parent];
}
}
// Create test store.
myStore = new Store({
data: datacopy
});
// Since dojo.store.Memory doesn't have various store methods we need, we have to add them manually
myStore.getChildren = function(object){
// Add a getChildren() method to store for the data model where
// children objects point to their parent (aka relational model)
return this.query({parent: this.getIdentity(object)});
};
if(isObservable){
aspect.around(myStore, "put", function(originalPut){
// To support DnD, the store must support put(child, {parent: parent}).
// Since our store is relational, that just amounts to setting child.parent
// to the parent's id.
return function(obj, options){
if(options && options.parent){
obj.parent = options.parent.id;
}
return originalPut.call(myStore, obj, options);
}
});
// Wrap the store in Observable so that updates to the store are reflected
myStore = new Observable(myStore);
}
doh.t(myStore, "store created");
// Create the model
myModel = new ObjectStoreModel({store: myStore, query: {id: cache["earth"]}});
doh.t(myModel, "model created");
}
// Register tests for specified store / observable
function registerBasicTests(/*Boolean*/ async, /*Boolean*/ isObservable){
var category = (async ? "async " : "sync ") + (isObservable ? "observable ": "") + "store: ";
doh.register(category + "setup", function(){
setupStoreAndModel(async ? AsyncMemoryStore : Memory, isObservable);
});
doh.register(category + "basic", [
{
name: "create",
timeout: 5000,
runTest: function(){
myTree = new Tree({
id: "myTree",
model: myModel,
persist: false, // persist==true is too hard to test
dndController: dndSource
}).placeAt(win.body());
doh.t(myTree, "tree created");
myTree.startup();
// Give the tree time to load, and the do checks that it loaded correctly
return myTree.onLoadDeferred.then(function(){
var world = myTree.rootNode;
doh.t(world, "root node exists");
doh.is("The earth", world.label, "world node label");
doh.t(world.isExpanded, "root node is expanded");
doh.t(domClass.contains(world.domNode, "dijitTreeIsRoot"), "root node has dijitTreeIsRoot");
var children = world.getChildren();
doh.is(6, children.length, "six children");
doh.is("Africa", children[0].label, "first child");
doh.f(domClass.contains(children[0].domNode, "dijitTreeIsRoot"), "first child doesn't have dijitTreeIsRoot");
doh.f(children[0].isExpanded, "first child not expanded");
doh.is("South America", children[5].label, "last child");
// Last child has special CSS for drawing the grid lines
doh.f(domClass.contains(children[3].domNode, "dijitTreeIsLast"), "middle node doesn't have dijitTreeIsLast");
doh.t(domClass.contains(children[5].domNode, "dijitTreeIsLast"), "last node has dijitTreeIsLast");
});
}
},
function openEurope(){
var d = new doh.Deferred();
var world = myTree.rootNode;
var europe = world.getChildren()[3];
doh.is("Europe", europe.label, "europe node label");
doh.t(europe, "europe node exists");
// Click on Europe to open it
on.emit(europe.expandoNode, "click", {bubbles: true});
// Give the children time to load, and the do checks that they
// loaded correctly
setTimeout(d.getTestCallback(function(){
doh.t(europe.isExpanded, "europe node is expanded");
var children = europe.getChildren();
doh.is(4, children.length, "children count");
doh.is("Germany", children[0].label, "first child");
doh.f(children[0].isExpanded, "first child not expanded");
doh.is("Italy", children[3].label, "last child");
// Last child has special CSS for drawing the grid lines
doh.f(domClass.contains(children[1].domNode, "dijitTreeIsLast"), "middle node doesn't have dijitTreeIsLast");
doh.t(domClass.contains(children[3].domNode, "dijitTreeIsLast"), "last node has dijitTreeIsLast");
}), 750);
return d;
},
function openAsia(){
var d = new doh.Deferred();
var world = myTree.rootNode;
var asia = world.getChildren()[1];
doh.is("Asia", asia.label, "asia node label");
doh.t(asia, "asia node exists");
// Click on Europe to open it
on.emit(asia.expandoNode, "click", {bubbles: true});
// Give the children time to load, and the do checks that they
// loaded correctly
setTimeout(d.getTestCallback(function(){
doh.t(asia.isExpanded, "asia node is expanded");
var children = asia.getChildren();
doh.is(4, children.length, "children count");
doh.is("China", children[0].label, "first child");
doh.is("Mongolia", children[3].label, "last child");
}), 750);
return d;
}
]);
if(isObservable){
doh.register(category + "data store binding", [
function itemUpdate(){
// Test that Tree notices when data store items change, and updates accordingly
myStore.put({ id: "ES", name: "España", type: "country", parent: "EU" });
var world = myTree.rootNode;
var europe = world.getChildren()[3];
doh.is("España", helpers.innerText(europe.getChildren()[2].labelNode), "label changed");
},
function topLevelItemDelete(){
// Delete a top level item.
// Remove "South America"
myStore.remove("SA");
var world = myTree.rootNode;
var children = world.getChildren();
doh.is(5, children.length, "five children");
doh.is("North America", children[4].label, "last child");
doh.t(domClass.contains(children[4].domNode, "dijitTreeIsLast"),
"North america has become the last node so it gets the CSS class for that");
},
function nestedItemDelete(){
// Delete a nested item
// Remove "China"
myStore.remove("CN");
var world = myTree.rootNode;
var asia = world.getChildren()[1];
var children = asia.getChildren();
doh.is(3, children.length, "three children");
},
function topLevelItemInsert(){
// Create a new top level item as last child.
// ForestStoreModel needs to realize that the top level children have changed and notify Tree.
myStore.add({
id: "PA",
name: "Pacifica",
type: "continent",
parent: "earth"
});
var world = myTree.rootNode;
var children = world.getChildren();
doh.is(6, children.length, "six children");
doh.is("Pacifica", children[5].label, "last child");
doh.f(domClass.contains(children[4].domNode, "dijitTreeIsLast"),
"North America no longer last child");
doh.t(domClass.contains(children[5].domNode, "dijitTreeIsLast"),
"Pacifica is last child");
},
function topLevelItemModify(){
// Modify a top level item so it's no longer top level.
myStore.put({
id: "PA",
name: "Pacifica",
type: "continent",
parent: "AS"
});
var world = myTree.rootNode;
doh.is(5, world.getChildren().length, "world children");
var asia = world.getChildren()[1];
doh.is(4, asia.getChildren().length, "asia children");
},
function nestedItemModify(){
// Modify a nested item so it matches the query for top level items in the tree.
myStore.put({
id: "PA",
name: "Pacifica",
type: "continent",
parent: "earth"
});
var world = myTree.rootNode;
var asia = world.getChildren()[1];
doh.is(3, asia.getChildren().length, "asia children");
}
]);
doh.register(category + "DnD", [
// Drag Germany from Europe to Asia
function dragGermanyToAsia(){
return all([myStore.get("AS"), myStore.get("EU"), myStore.get("DE")]).then(function(items){
var asiaItem = items[0],
europeItem = items[1],
germanyItem = items[2];
return myModel.pasteItem(germanyItem, europeItem, asiaItem);
}).then(function(){
// Check tree state
var world = myTree.rootNode;
var asia = world.getChildren()[1];
var europe = world.getChildren()[3];
doh.is(3, europe.getChildren().length, "europe children");
doh.is(4, asia.getChildren().length, "asia children");
doh.is("Germany", asia.getChildren()[3].label, "last child of asia");
});
},
// Drag Germany from Asia to Europe
function dragGermanyToEurope(){
return all([myStore.get("AS"), myStore.get("EU"), myStore.get("DE")]).then(function(items){
var asiaItem = items[0],
europeItem = items[1],
germanyItem = items[2];
return myModel.pasteItem(germanyItem, asiaItem, europeItem);
}).then(function(){
// Check tree state
var world = myTree.rootNode;
var asia = world.getChildren()[1];
var europe = world.getChildren()[3];
doh.is(3, asia.getChildren().length, "asia children");
doh.is(4, europe.getChildren().length, "europe children");
doh.is("Germany", europe.getChildren()[3].label, "last child of europe");
});
},
function openAfrica(){
var d = new doh.Deferred();
var world = myTree.rootNode;
var africa = world.getChildren()[0];
doh.is("Africa", africa.label, "africa node label");
doh.t(africa, "africa node exists");
// Click on Africa to open it
on.emit(africa.expandoNode, "click", {bubbles: true});
// Give the children time to load, and the do checks that they
// loaded correctly
setTimeout(d.getTestCallback(function(){
doh.t(africa.isExpanded, "node is expanded");
var children = africa.getChildren();
doh.is(3, children.length, "children count");
}), 750);
return d;
},
function openKenya(){
var d = new doh.Deferred();
var world = myTree.rootNode;
var africa = world.getChildren()[0];
var kenya = africa.getChildren()[1];
doh.t(kenya, "kenya node exists");
doh.is("Kenya", kenya.label, "kenya node label");
// Click on Kenya to open it
on.emit(kenya.expandoNode, "click", {bubbles: true});
// Give the children time to load, and the do checks that they
// loaded correctly
setTimeout(d.getTestCallback(function(){
doh.t(kenya.isExpanded, "node is expanded");
var children = kenya.getChildren();
doh.is(2, children.length, "children count");
}), 750);
return d;
},
// Dragging open node to make sure it stays open.
function dragKenyaToAsia(){
// Get some pointers to TreeNodes
var world = myTree.rootNode;
var africa = world.getChildren()[0];
var asia = world.getChildren()[1];
var kenya = africa.getChildren()[1];
return all([myStore.get("AS"), myStore.get("AF"), myStore.get("KE")]).then(function(items){
var asiaItem = items[0],
africaItem = items[1],
kenyaItem = items[2];
return myModel.pasteItem(kenyaItem, africaItem, asiaItem);
}).then(function(){
// Confirm Tree state
doh.is(4, asia.getChildren().length, "asia children");
doh.is("Kenya", asia.getChildren()[3].label, "last child of asia");
doh.is(kenya, asia.getChildren()[3], "same TreeNode as before");
doh.t(kenya.isExpanded, "node is still expanded");
doh.is(2, kenya.getChildren().length, "same children count as before");
});
},
// Put Kenya back in Africa
function dragKenyaToAfrica(){
return all([myStore.get("AS"), myStore.get("AF"), myStore.get("KE")]).then(function(items){
var asiaItem = items[0],
africaItem = items[1],
kenyaItem = items[2];
return myModel.pasteItem(kenyaItem, asiaItem, africaItem);
}).then(function(){
var world = myTree.rootNode;
var africa = world.getChildren()[0];
var asia = world.getChildren()[1];
doh.is(3, asia.getChildren().length, "asia children");
doh.is(3, africa.getChildren().length, "africa children");
});
},
// Drag Europe onto root, to make sure it doesn't disappear (#16692)
function dragEuropeToRoot(){
var world = myTree.rootNode;
doh.is(6, world.getChildren().length, "world children before paste");
return all([myStore.get("earth"), myStore.get("EU")]).then(function(items){
var worldItem = items[0],
europeItem = items[1];
return myModel.pasteItem(europeItem, worldItem, worldItem);
}).then(function(){
doh.is(6, world.getChildren().length, "world children after paste");
});
}
]);
}
doh.register(category + "tearDown", function destroyTree(){
myTree.destroy();
myModel.destroy();
});
}
registerBasicTests(false, true);
registerBasicTests(true, true);
registerBasicTests(true, false);
// Other tests, currently only run on synchronous observable store
function registerPathsTests(datatype){
// use datatype to switch between int|float|string (default)
// cleanup:
datatype = datatype == "float" ? "float" : datatype == "int" ? "int" : "string";
function typePath(path){
if(datatype!="string"){
return array.map(path,function(item){
return cache[item];
});
}
return path;
}
// return original id from cache
function fromCache(val){
for(var k in cache){
if(cache[k]===val){
return k;
}
}
}
doh.register("paths_"+datatype, [
function reset(){
setupStoreAndModel(Memory, true, datatype);
},
{
name: "getPath",
timeout: 5000,
runTest: function(){
myTree = new Tree({
id: "myTree",
model: myModel,
persist: false, // persist==true is too hard to test
dndController: dndSource,
autoExpand: true
}).placeAt(win.body());
doh.t(myTree, "tree created");
myTree.startup();
return myTree.onLoadDeferred.then(function (){
// Select the node. can't emit "click" because dndSelector listens for mousedown & mouseup.
// And before the mousedown, we need a mouseover event, so _dndContainer.js sets this.current.
var europe = myTree.rootNode.getChildren()[3];
var france = europe.getChildren()[1];
on.emit(france.labelNode, navigator.pointerEnabled ? "pointerover" : navigator.msPointerEnabled ? "MSPointerOver" : "mouseover", {bubbles: true});
on.emit(france.labelNode, navigator.pointerEnabled ? "pointerdown" : navigator.msPointerEnabled ? "MSPointerDown" : "mousedown", {button: dojo.mouseButtons.LEFT, bubbles: true});
on.emit(france.labelNode, navigator.pointerEnabled ? "pointerup" : navigator.msPointerEnabled ? "MSPointerUp" : "mouseup", {button: dojo.mouseButtons.LEFT, bubbles: true});
var path = myTree.get("path");
doh.is("earth, EU, FR", array.map(myTree.get("path"), function (obj){
return fromCache(obj.id);
}).join(", "), "serialized path");
});
}
},
{
name: "createWithPath",
timeout: 5000,
runTest: function(){
myTree2 = new Tree({
id: "myTree2",
model: myModel,
persist: false, // persist==true is too hard to test
dndController: dndSource,
path: typePath(["earth", "EU", "IT"])
}).placeAt(win.body());
doh.t(myTree2, "myTree2 created");
myTree2.startup();
return myTree2.onLoadDeferred.then(function(){
doh.t(myTree2.rootNode, "root node exists");
doh.t(myTree2.rootNode.isExpanded, "root node is expanded");
doh.t(myTree2.rootNode.getChildren()[3].isExpanded, "europe node is expanded");
doh.is("Italy", myTree2.selectedNode.label, "selected correct node");
});
}
},
function copyPath(){
var world = myTree.rootNode;
return myTree.set("path", myTree2.get("path")).then(function(items){
doh.is("earth, EU, IT", array.map(items, function(item){
return fromCache(item.id);
}).join(", "));
doh.t(world.isExpanded, "root node is expanded");
doh.t(world.getChildren()[3].isExpanded, "europe node is expanded");
doh.is("Italy", myTree.get("selectedNode").label, "selected correct node");
});
},
{
name: "copyPathByIds",
timeout: 5000,
runTest: function(){
var testpath = typePath(["earth", "NA", "CA", "Ottawa"]);
return myTree.set("path", testpath).then(function(){
var path = array.map(myTree.get("path"), function(item){ return item.id; });
doh.is(testpath, path, "path got set on myTree");
return myTree2.set("path", path).then(function(){
doh.t(myTree2.rootNode.isExpanded, "root node is expanded");
doh.t(myTree2.rootNode.getChildren()[4].isExpanded, "north america node is expanded");
doh.t(myTree2.rootNode.getChildren()[4].getChildren()[1].isExpanded, "canada node is expanded");
doh.is("Ottawa", myTree2.get("selectedNode").label, "selected correct node");
});
});
}
},
function setPathToNull(){
return myTree2.set("path", []).then(function(){
doh.is(null, myTree2.get("selectedNode"), "no selected node");
});
},
function setPathToRoot(){
return myTree2.set("path", typePath(["earth"])).then(function(){
doh.is(myTree2.rootNode, myTree2.get("selectedNode"), "selected root node");
});
},
{
name: "setPaths",
timeout: 5000,
runTest: function(){
return myTree2.set("paths", [
typePath(["earth", "AF", "KE", "Nairobi"]),
typePath(["earth", "NA", "MX", "Guadalajara"])
]).then(function(paths){
doh.is("earth, AF, KE, Nairobi", array.map(paths[0], function(item){
return fromCache(item.id);
}).join(", "));
doh.is("earth, NA, MX, Guadalajara", array.map(paths[1], function(item){
return fromCache(item.id);
}).join(", "));
var ids = array.map(myTree2.selectedItems, function(x){
return myTree2.model.getIdentity(x);
}).sort();
doh.is(typePath(["Guadalajara", "Nairobi"]).sort(), ids);
});
}
},
function setEmptyPath(){
// setting an empty path is interpreted as selecting nothing
return myTree2.set("path", []).then(function(){
doh.is(0, myTree2.get("selectedNodes").length, "no nodes selected");
});
},
function setInvalidPath(){
var d = new doh.Deferred();
myTree2.set("path", typePath(["earth", "AF", "KE", "Narnia"])).then(
function(){
d.errback("Should have gotten error trying to set invalid path");
},
d.getTestCallback(function(e){
doh.t(e instanceof Tree.PathError, "got PathError");
})
);
return d;
},
function destroyTree(){
myTree.destroy();
myTree2.destroy();
}
]);
}
registerPathsTests("string");
registerPathsTests("int");
registerPathsTests("float");
doh.register("delete selected node", [
function reset(){
setupStoreAndModel(Memory, true);
},
{
name: "create",
timeout: 10000,
runTest: function(){
myTree = new Tree({
id: "myTree",
model: myModel,
persist: false, // persist==true is too hard to test
path: ["earth", "EU", "IT"]
}).placeAt(win.body());
doh.t(myTree, "tree created");
myTree.startup();
return myTree.onLoadDeferred.then(function(){
doh.is("IT", myTree.get("selectedItem").id);
});
}
},
function deleteSelectedItem(){
myStore.remove("IT");
},
function selectNewItem(){
// Since EU is already open this set("path", ...) should execute immediately
myTree.set("path", ["earth", "EU", "FR"]);
doh.is("FR", myTree.get("selectedItem").id);
},
function tearDown(){
myTree.destroy();
myModel.destroy();
}
]);
doh.register("nobidi", [
function reset(){
setupStoreAndModel(Memory, true);
},
{
name: "create",
timeout: 10000,
runTest: function(){
myTree = new Tree({
id: "myTree",
model: myModel,
persist: false, // persist==true is too hard to test
path: ["earth", "EU", "IT"]
}).placeAt(win.body());
doh.t(myTree, "tree created");
}
},
// Make sure that Tree doesn't have spurious lang="" dir="" on nodes
function noLangDir(){
doh.t(myTree.rootNode, "root node exists");
doh.t(myTree.rootNode.isExpanded, "root node is expanded");
doh.f(domClass.contains(myTree.rootNode, "lang"), "no (empty) lang attribute on root TreeNode");
doh.f(domClass.contains(myTree.rootNode, "dir"), "no (empty) dir attribute on root TreeNode");
var children = myTree.rootNode.getChildren();
doh.f(domClass.contains(children[2], "lang"), "no (empty) lang attribute on child TreeNode");
doh.f(domClass.contains(children[2], "dir"), "no (empty) dir attribute on child TreeNode");
},
function tearDown(){
myTree.destroy();
myModel.destroy();
}
]);
doh.register("expand/contract", [
function reset(){
setupStoreAndModel(Memory, true);
},
{
name: "initiallyExpanded",
timeout: 10000,
runTest: function(){
myTree = new Tree({
id: "myTreeExpand",
model: myModel,
persist: false, // persist==true is too hard to test
autoExpand: true
}).placeAt(win.body());
doh.t(myTree, "tree created");
myTree.startup();
return myTree.onLoadDeferred.then(function(){
var world = myTree.rootNode;
doh.t(world, "root node exists");
doh.t(world.isExpanded, "root node is expanded");
var children = world.getChildren();
doh.is(6, children.length, "world children");
doh.t(children[0].isExpanded, "Africa expanded");
doh.t(children[0].getChildren()[1].isExpanded, "Kenya expanded too");
doh.is(2, children[0].getChildren()[1].getChildren().length, "Kenya children");
doh.t(children[4].isExpanded, "North America expanded");
doh.is(3, children[4].getChildren().length, "North America children");
});
}
},
{
name: "collapseAll",
timeout: 10000,
runTest: function(){
return myTree.collapseAll().then(function(){
var world = myTree.rootNode;
doh.t(world, "root node exists");
doh.f(world.isExpanded, "root node collapsed");
var children = world.getChildren();
doh.is(6, children.length, "world children");
doh.f(children[0].isExpanded, "Africa collapsed");
doh.f(children[0].getChildren()[1].iscollapsed, "Kenya collapsed too");
doh.is(2, children[0].getChildren()[1].getChildren().length, "Kenya children");
doh.f(children[4].isExpanded, "North America collapsed");
doh.is(3, children[4].getChildren().length, "North America children");
});
}
},
{
name: "expandAll",
timeout: 10000,
runTest: function(){
myTree.destroy();
myTree = new Tree({
id: "myTreeExpand",
model: myModel,
persist: false, // persist==true is too hard to test
autoExpand: false
}).placeAt(win.body());
doh.t(myTree, "tree created");
myTree.startup();
return myTree.onLoadDeferred.then(function(){
var world = myTree.rootNode;
doh.t(world, "root node exists");
doh.t(world.isExpanded, "root node is expanded");
var children = world.getChildren();
doh.is(6, children.length, "world children");
doh.f(children[0].isExpanded, "Africa collapsed");
return myTree.expandAll().then(function(){
var children = world.getChildren();
doh.t(children[0].isExpanded, "Africa expanded");
doh.t(children[0].getChildren()[2].isExpanded, "Kenya expanded too");
doh.t(children[4].isExpanded, "North America expanded");
doh.is(3, children[4].getChildren().length, "North America children");
});
});
}
},
{
name: "collapseShowRootFalseTree",
timeout: 5000,
runTest: function(){
myTree.destroy();
myTree = new Tree({
id: "myTreeExpand",
model: myModel,
persist: false, // persist==true is too hard to test
showRoot: false
}).placeAt(win.body());
doh.t(myTree, "tree created");
myTree.startup();
return myTree.onLoadDeferred.then(function(){
var world = myTree.rootNode;
return myTree._expandNode(world.getChildren()[0]).then(function(){
var children = world.getChildren();
doh.t(children[0].isExpanded, "Africa expanded");
// While we are here, check that dijitTreeIsRoot class applied to first level of
// children, since the actual root node is hidden.
doh.t(domClass.contains(children[0].domNode, "dijitTreeIsRoot"),
"first level children have dijitTreeIsRoot");
return myTree.collapseAll().then(function(){
doh.t(world, "root node exists");
doh.t(world.isExpanded, "root node expanded (because it's hidden");
doh.f(children[0].isExpanded, "Africa collapsed");
doh.t(helpers.isVisible(children[0]), "Africa node visible");
});
});
});
}
},
function tearDown(){
myTree.destroy();
myModel.destroy();
}
]);
doh.register("persistence", [
// Reset the data to original values
function reset(){
setupStoreAndModel();
},
{
name: "create",
timeout: 5000,
runTest: function(){
if(registry.byId("myTree")){
registry.byId("myTree").destroy();
}
cookie("myTreeSaveStateCookie", "");
myTree = new Tree({
id: "myTree",
model: myModel,
persist: true
}).placeAt(win.body());
doh.t(myTree, "tree created");
myTree.startup();
return myTree.onLoadDeferred;
}
},
{
name: "expand and contract",
timeout: 5000,
runTest: function(){
var d = new doh.Deferred();
var world = myTree.rootNode;
na = world.getChildren()[4];
doh.is("North America", na.label, "North America node label");
// Click on North America to open it
on.emit(na.expandoNode, "click", {bubbles: true});
// Wait for animation to complete
setTimeout(d.getTestErrback(function(){
mx = na.getChildren()[0];
doh.is("Mexico", mx.label, "Mexico node label");
// Click on Mexico to open it
on.emit(mx.expandoNode, "click", {bubbles: true});
// Wait for animation to complete.
setTimeout(d.getTestErrback(function(){
// Click on North America again, to close it
on.emit(na.expandoNode, "click", {bubbles: true});
setTimeout(d.getTestCallback(function(){
// Wait for close animation to finish and then return success
}), 500);
}), 500);
}), 500);
return d;
}
},
{
name: "recreate tree",
timeout: 5000,
runTest: function(){
myTree.destroy();
myTree = new Tree({
id: "myTree",
model: myModel,
persist: true
}).placeAt(win.body());
doh.t(myTree, "tree created");
myTree.startup();
return myTree.onLoadDeferred;
}
},
{
name: "check tree state",
timeout: 5000,
runTest: function(){
var d = new doh.Deferred();
var world = myTree.rootNode;
var na = world.getChildren()[4];
doh.is("North America", na.label, "North America node label");
doh.f(na.isExpanded, "North America collapsed");
// Click on North America to open it
on.emit(na.expandoNode, "click", {bubbles: true});
setTimeout(d.getTestCallback(function(){
doh.t(na.isExpanded, "North America expanded");
mx = na.getChildren()[0];
doh.is("Mexico", mx.label, "Mexico node label");
doh.t(mx.isExpanded, "Mexico expanded");
}), 500);
return d;
}
},
function tearDown(){
myTree.destroy();
myModel.destroy();
}
]);
// Tests that TreeNodes that are destroyed don't linger in selection, etc.
doh.register("destroyed nodes", [
// Reset the data to original values
function reset(){
setupStoreAndModel(Memory, true);
},
{
name: "create",
timeout: 5000,
runTest: function(){
cookie("myDeleteTreeSaveStateCookie", "");
myTree = new Tree({
id: "myDeleteTree",
model: myModel,
persist: true
}).placeAt(win.body());
doh.t(myTree, "tree created");
myTree.startup();
doh.is("earth", cookie("myDeleteTreeSaveStateCookie"), "initial persistence cookie just earth");
}
},
{
name: "removedFromSelection",
timeout: 10000,
runTest: function(){
var d = new doh.Deferred();
// Select Mexico city
myTree.set("path", ["earth", "NA", "MX", "Mexico City"]).then(d.getTestErrback(function(){
doh.is(1, myTree.get("paths").length, "one selected node");
var selectedNode = myTree.get("selectedNode");
// Ancestors of the selected node should be expanded, and that should be saved
// in the cookie
doh.is("earth,earth/NA,earth/NA/MX", cookie("myDeleteTreeSaveStateCookie"),
"Earth, North America, Mexico should be listed as expanded");
// Remove selection's ancestor
myStore.remove("NA");
// use setTimeout() to give Tree time to realize this isn't a drag & drop, but that
// the North America subtree was truly deleted
setTimeout(d.getTestCallback(function(){
doh.t(selectedNode._destroyed, "the selected node was destroyed (along with it's ancestor)");
doh.is(0, myTree.get("paths").length, "no selected nodes");
doh.is("earth", cookie("myDeleteTreeSaveStateCookie"),
"North America and Mexico should have been removed from list of expanded nodes")
}), 100);
}));
return d;
}
},
{
name: "reinsert deleted descendants",
timeout: 5000,
runTest: function(){
myStore.put({ id: "NA", name:"North America", type:"continent", parent: "earth" });
myStore.put({ id: "MX", name:"Mexico", type:"country", population:"108 million", area:"1,972,550 sq km",
parent: "NA" });
myStore.put({ id: "Mexico City", name:"Mexico City", type:"city", population:"19 million", timezone:"-6 UTC", parent: "MX"});
myStore.put({ id: "Guadalajara", name:"Guadalajara", type:"city", population:"4 million", timezone:"-6 UTC", parent: "MX" });
return myTree.set("path", ["earth", "NA", "MX", "Mexico City"]).then(function(){
var node = myTree.get("selectedNode");
doh.isNot(null, node, "got a selected node");
doh.f(node._destroyed, "not destroyed");
doh.f(node.getParent()._destroyed, "parent not destroyed");
doh.f(node.getParent().getParent()._destroyed, "grandparent not destroyed");
});
}
},
function tearDown(){
myTree.destroy();
myModel.destroy();
}
]);
doh.register("HTML tree", {
name: "create",
timeout: 10000,
runTest: function(){
var d = new doh.Deferred();
// Create test store.
htmlData = array.map(data, function(o){
var n = lang.clone(o);
n.name = "<i>" + o.name + "</i>";
return n;
});
htmlStore = new Memory({
data: htmlData
});
// Since dojo.store.Memory doesn't have various store methods we need, we have to add them manually
htmlStore.getChildren = function(object){
// Add a getChildren() method to store for the data model where
// children objects point to their parent (aka relational model)
return this.query({parent: this.getIdentity(object)});
};
// Create the model
htmlModel = new ObjectStoreModel({
store: htmlStore,
labelType: "html",
query: {id: "earth"}
});
doh.t(htmlModel, "model created");
htmlTree = new Tree({
id: "htmlTree",
model: htmlModel
}).placeAt(win.body());
doh.t(htmlTree, "tree created");
htmlTree.startup();
world = htmlTree.rootNode;
return htmlTree.expandAll().then(function(){
doh.t(world, "root node exists");
doh.is("<i>The earth</i>", world.label, "world node label");
doh.is("<i>the earth</i>", world.labelNode.innerHTML.toLowerCase(), "world node labelNode.innerHTML");
var children = world.getChildren();
doh.is("<i>Africa</i>", children[0].label, "first child");
doh.is("<i>africa</i>", children[0].labelNode.innerHTML.toLowerCase(), "first child labelNode.innerHTML");
});
},
tearDown: function(){
htmlTree.destroy();
htmlModel.destroy();
}
});
doh.register("plain text tree", {
name: "create",
timeout: 10000,
runTest: function(){
var d = new doh.Deferred();
// Create test store.
plainTextData = array.map(data, function(o){
var n = lang.clone(o);
n.name = "<>&" + o.name;
return n;
});
plainTextStore = new Memory({
data: plainTextData
});
// Since dojo.store.Memory doesn't have various store methods we need, we have to add them manually
plainTextStore.getChildren = function(object){
// Add a getChildren() method to store for the data model where
// children objects point to their parent (aka relational model)
return this.query({parent: this.getIdentity(object)});
};
// Create the model
plainTextModel = new ObjectStoreModel({
store: plainTextStore,
labelType: "text",
query: {id: "earth"}
});
doh.t(plainTextModel, "model created");
plainTextTree = new Tree({
id: "plainTextTree",
model: plainTextModel
}).placeAt(win.body());
doh.t(plainTextTree, "tree created");
plainTextTree.startup();
world = plainTextTree.rootNode;
return plainTextTree.expandAll().then(function(){
doh.t(world, "root node exists");
doh.is("<>&The earth", world.label, "world node label");
doh.is("<>&The earth", helpers.innerText(world.labelNode), "world node labelNode.innerText");
var children = world.getChildren();
doh.is("<>&Africa", helpers.innerText(children[0].labelNode), "first child");
});
},
tearDown: function(){
plainTextTree.destroy();
plainTextModel.destroy();
}
});
// Repeat of suite in Tree_a11y.html, but here to run against ObjectStoreModel instead of TreeStoreModel.
var myTree_before = document.createElement("input");
doh.register("destroy and focus", [
{
name: "create",
timeout: 5000,
runTest: function(){
setupStoreAndModel(Memory, true);
win.body().appendChild(myTree_before);
myTree = new Tree({
id: "myTree",
model: myModel,
persist: false, // persist==true is too hard to test
dndController: dndSource
}).placeAt(win.body());
doh.t(myTree, "tree created");
myTree.startup();
return myTree.expandAll();
}
},
{
name: "destroy previously focused node",
timeout: 20000,
runTest: function(){
var d = new doh.Deferred();
// Go to Africa node
var rootNode = registry.byId("myTree").getChildren()[0];
rootNode.getChildren()[0].focus();
setTimeout(d.getTestErrback(function(){
doh.is("Africa", myTree.focusedChild.label, "focus");
var previouslyFocusedChild = myTree.focusedChild;
// Tab out of Tree, and then destroy previously focused node.
myTree_before.focus();
setTimeout(d.getTestErrback(function(){
var store = myTree.model.store;
store.remove("AF");
// Refocus Tree. Since previously focused node was destroyed,
// focus should go to The earth.
setTimeout(d.getTestErrback(function(){
myTree.focus();
setTimeout(d.getTestCallback(function(){
doh.is("The earth", focus.curNode.innerHTML, "focus");
}), 500);
}), 500);
}), 500);
}), 500);
return d;
}
},
{
name: "destroy previously focused node's ancestor",
timeout: 20000,
runTest: function(){
var d = new doh.Deferred();
// Go to China node
var rootNode = registry.byId("myTree").getChildren()[0];
rootNode.getChildren()[0].getChildren()[0].focus();
setTimeout(d.getTestErrback(function(){
doh.is("China", myTree.focusedChild.label, "focus");
var previouslyFocusedChild = myTree.focusedChild;
// Tab out of Tree, and then destroy previously focused node's ancestor
myTree_before.focus();
setTimeout(d.getTestErrback(function(){
var store = myTree.model.store;
store.remove("AS");
// Refocus Tree. Since previously focused node was destroyed,
// focus should go to The earth.
setTimeout(d.getTestErrback(function(){
myTree.focus();
setTimeout(d.getTestCallback(function(){
doh.is("The earth", focus.curNode.innerHTML, "focus");
}), 500);
}), 500);
}), 500);
}), 500);
return d;
}
},
{
name: "destroy currently focused node",
timeout: 4000,
runTest: function(){
var d = new doh.Deferred();
// Go to Oceania node
var rootNode = registry.byId("myTree").getChildren()[0];
rootNode.getChildren()[0].focus();
setTimeout(d.getTestErrback(function(){
doh.is("Oceania", myTree.focusedChild.label, "focus");
// Destroy currently focused node
setTimeout(d.getTestErrback(function(){
var store = myTree.model.store;
store.remove("OC");
// Focus should go to The earth
setTimeout(d.getTestCallback(function(){
doh.is("The earth", focus.curNode.innerHTML, "focus");
}), 500);
}), 500);
}), 500);
return d;
}
},
{
name: "destroy currently focused node's ancestor",
timeout: 4000,
runTest: function(){
var d = new doh.Deferred();
// Go to Germany node
var rootNode = registry.byId("myTree").getChildren()[0];
rootNode.getChildren()[0].getChildren()[0].focus();
setTimeout(d.getTestErrback(function(){
doh.is("Germany", myTree.focusedChild.label, "focus");
// Destroy currently focused node's ancestor
setTimeout(d.getTestErrback(function(){
var store = myTree.model.store;
store.remove("EU");
// Focus should go to The earth
setTimeout(d.getTestCallback(function(){
doh.is("The earth", focus.curNode.innerHTML, "focus");
}), 500);
}), 500);
}), 500);
return d;
}
}
]);
doh.run();
});
</script>
</head>
<body class="claro" role="main">
<h1 class="testTitle">dijit/Tree using dijit/tree/ObjectStore (against dojo/store) Automated Test</h1>
</body>
</html>