UNPKG

fuelux

Version:

Base Fuel UX styles and controls

453 lines (368 loc) 15.5 kB
/*global QUnit:false, module:false, test:false, asyncTest:false, expect:false*/ /*global start:false, stop:false ok:false, equal:false, notEqual:false, deepEqual:false*/ /*global notDeepEqual:false, strictEqual:false, notStrictEqual:false, raises:false*/ define( function ( require ) { var QUnit = require('qunit'); var $ = require( "jquery" ); var html = require( "text!test/markup/tree-markup.html!strip" ); $( "body" ).append( html ); require( "bootstrap" ); require( "fuelux/tree" ); QUnit.module( "Fuel UX Tree", { beforeEach: function( assert ) { var callLimit = 50; var callCount = 0; function guid () { function s4 () { return Math.floor( ( 1 + Math.random() ) * 0x10000 ) .toString( 16 ) .substring( 1 ); } return s4() + s4() + "-" + s4() + "-" + s4() + "-" + s4() + "-" + s4() + s4() + s4(); } this.dataSource = function( options, callback ) { if ( callCount >= callLimit ) { callback( { data: [ { "name": "Convex and Concave", "type": "item", "attr": { "id": "item4" } } ] }, 400 ); return; } callCount++; callback( { data: [ { name: "Ascending and Descending", type: "folder", attr: { id: "folder" + guid() } }, { name: "Sky and Water I (with custom icon)", type: "item", attr: { id: "folder" + guid(), "data-icon": "glyphicon glyphicon-file" } }, { name: "Drawing Hands", type: "folder", attr: { id: "folder" + guid(), "data-children": false } }, { name: "Waterfall", type: "item", attr: { id: "item2" } }, { name: "Belvedere", type: "folder", attr: { id: "folder" + guid() } }, { name: "Relativity (with custom icon)", type: "item", attr: { id: "item3", "data-icon": "glyphicon glyphicon-picture" } }, { name: "House of Stairs", type: "folder", attr: { id: "folder" + guid() } }, { name: "Convex and Concave", type: "item", attr: { id: "item4" } }, { name: "Load More", type: "overflow", attr: { id: "overflow1" } } ] } ); }; this.textDataSource = function( options, callback ) { callback( { data: [ { text: "node text", type: "folder", attr: { id: "folder1" } } ] } ); }; } } ); var NUM_CHILDREN = 9; var NUM_FOLDERS = 4; var NUM_ITEMS = 4; var NUM_OVERFLOWS = 1; QUnit.test( "should be defined on jquery object", function( assert ) { assert.ok( $().tree, "tree method is defined" ); } ); QUnit.test( "should return element", function( assert ) { var $tree = $( html ); assert.ok( $tree.tree() === $tree, "tree should be initialized" ); } ); QUnit.test( "should have correct defaults", function correctDefaults( assert ) { var $tree = $( html ); var defaults = $tree.tree.defaults; assert.equal( defaults.multiSelect, false, "multiSelect defaults to false" ); assert.equal( defaults.cacheItems, true, "cacheItems defaults to true" ); assert.equal( defaults.folderSelect, true, "folderSelect defaults to true" ); assert.equal( defaults.itemSelect, true, "itemSelect defaults to true" ); assert.equal( defaults.disclosuresUpperLimit, 0, "disclosuresUpperLimit defaults to 0" ); assert.ok( defaults.dataSource, "dataSource exists by default" ); } ); QUnit.test( "should call dataSource correctly", function( assert ) { var $tree = $( html ); $tree.tree( { dataSource: function( options, callback ) { assert.ok( 1 === 1, "dataSource function called prior to rendering" ); assert.equal( typeof options, "object", "dataSource provided options object" ); assert.equal( typeof callback, "function", "dataSource provided callback function" ); callback( { data: [] } ); } } ); } ); QUnit.test( "Tree should be populated by items on initialization", function( assert ) { var $tree = $( html ).find( "#MyTree" ); $tree.tree( { dataSource: this.dataSource } ); assert.equal( $tree.find( ".tree-branch:not([data-template])" ).length, NUM_FOLDERS, "Initial set of folders have been added" ); assert.equal( $tree.find( ".tree-item:not([data-template])" ).length, NUM_ITEMS, "Initial set of items have been added" ); assert.equal( $tree.find( ".tree-overflow:not([data-template])" ).length, NUM_OVERFLOWS, "Initial overflow has been added" ); } ); QUnit.test( "Folder should populate when opened", function( assert ) { var $tree = $( html ).find( "#MyTree" ); var $selNode; $tree.tree( { dataSource: this.dataSource } ); $selNode = $tree.find( ".tree-branch:eq(1)" ); $tree.tree( "discloseFolder", $selNode.find( ".tree-branch-name" ) ); assert.equal( $selNode.find( ".tree-branch-children > li" ).length, NUM_CHILDREN, "Folder has been populated with items/sub-folders" ); $tree = $( html ).find( "#MyTreeSelectableFolder" ); $tree.tree( { dataSource: this.dataSource, folderSelect: true } ); $selNode = $tree.find( ".tree-branch:eq(1)" ); $tree.tree( "discloseFolder", $selNode.find( ".tree-branch-header" ) ); assert.equal( $selNode.find( ".tree-branch-children > li" ).length, NUM_CHILDREN, "Folder has been populated with sub-folders and items" ); } ); QUnit.test( "getValue alias should function", function( assert ) { var $tree = $( html ).find( "#MyTree" ); // MultiSelect: false is the default $tree.tree( { dataSource: this.dataSource } ); $tree.tree( "selectItem", $tree.find( ".tree-item:eq(1)" ) ); assert.deepEqual( $tree.tree( "selectedItems" ), $tree.tree( "getValue" ), "getValue aliases selectedItems" ); } ); QUnit.test( "Single item/folder selection works as designed", function( assert ) { var $tree = $( html ).find( "#MyTree" ); // MultiSelect: false is the default $tree.tree( { dataSource: this.dataSource } ); $tree.tree( "selectItem", $tree.find( ".tree-item:eq(1)" ) ); assert.equal( $tree.tree( "selectedItems" ).length, 1, "Return single selected value" ); $tree.tree( "selectItem", $tree.find( ".tree-item:eq(2)" ) ); assert.equal( $tree.tree( "selectedItems" ).length, 1, "Return new single selected value" ); $tree = $( html ).find( "#MyTreeSelectableFolder" ); $tree.tree( { dataSource: this.dataSource, folderSelect: true } ); $tree.tree( "selectItem", $tree.find( ".tree-item:eq(1)" ) ); assert.equal( $tree.tree( "selectedItems" ).length, 1, "Return single selected item (none previously selected, 1st programatic selection)" ); $tree.tree( "selectFolder", $tree.find( ".tree-branch-name:eq(1)" ) ); assert.equal( $tree.tree( "selectedItems" ).length, 1, "Return single selected folder (item previously selected, 2nd programatic selection)" ); $tree.tree( "selectItem", $tree.find( ".tree-item:eq(2)" ) ); assert.equal( $tree.tree( "selectedItems" ).length, 1, "Return single selected item (folder previously selected, 3rd programatic selection)" ); $tree.find( ".tree-item:eq(1)" ).click(); assert.equal( $tree.tree( "selectedItems" ).length, 1, "Return single selected item (item previously selected, 1st click selection)" ); $tree.find( ".tree-branch-name:eq(1)" ).click(); assert.equal( $tree.tree( "selectedItems" ).length, 1, "Return single selected folder (item previously selected, 2nd click selection)" ); $tree.find( ".tree-item:eq(2)" ).click(); assert.equal( $tree.tree( "selectedItems" ).length, 1, "Return single selected item (folder previously selected, 3rd click selection)" ); } ); // Test("Overflow click works as designed", function () { // var $tree = $(html).find('#MyTree'); // $tree.tree({ // dataSource: this.dataSource // }); // Equal($tree.find('> li:not([data-template])').length, NUM_CHILDREN, 'Initial set of folders (' + NUM_CHILDREN + ' children) have been added'); // $tree.find('.tree-overflow:eq(0)').click(); // //Once overflow is clicked, all original contents is loaded again, and original overflow is actually REMOVED from tree contents. // var NUM_AFTER_OVERFLOW_CLICK = (NUM_CHILDREN * 2) - 1; // equal($tree.find('> li:not([data-template])').length, NUM_AFTER_OVERFLOW_CLICK, 'Overflow contents (now ' + NUM_AFTER_OVERFLOW_CLICK + ' children) have loaded'); // }); QUnit.test( "Multiple item/folder selection works as designed", function( assert ) { var $tree = $( html ).find( "#MyTree" ); $tree.tree( { dataSource: this.dataSource, multiSelect: true } ); $tree.tree( "selectItem", $tree.find( ".tree-item:eq(1)" ) ); assert.equal( $tree.tree( "selectedItems" ).length, 1, "Return single selected value" ); $tree.tree( "selectItem", $tree.find( ".tree-item:eq(2)" ) ); assert.equal( $tree.tree( "selectedItems" ).length, 2, "Return multiple selected values" ); $tree.tree( "selectItem", $tree.find( ".tree-item:eq(1)" ) ); assert.equal( $tree.tree( "selectedItems" ).length, 1, "Return single selected value" ); $tree = $( html ).find( "#MyTreeSelectableFolder" ); $tree.tree( { dataSource: this.dataSource, multiSelect: true, folderSelect: true } ); $tree.tree( "selectFolder", $tree.find( ".tree-branch-name:eq(1)" ) ); assert.equal( $tree.tree( "selectedItems" ).length, 1, "Return single selected value" ); $tree.tree( "selectFolder", $tree.find( ".tree-branch-name:eq(2)" ) ); assert.equal( $tree.tree( "selectedItems" ).length, 2, "Return multiple selected values" ); $tree.tree( "selectFolder", $tree.find( ".tree-branch-name:eq(1)" ) ); assert.equal( $tree.tree( "selectedItems" ).length, 1, "Return single selected value" ); } ); QUnit.test( "should not allow selecting items if disabled", function( assert ) { var $tree = $( html ).find( "#MyTree" ); $tree.tree( { dataSource: this.dataSource, itemSelect: false } ); $tree.tree( "selectItem", $tree.find( ".tree-item:eq(1)" ) ); assert.equal( $tree.tree( "selectedItems" ).length, 0, "Return no value" ); } ); QUnit.test( "should not allow selecting folders if disabled", function( assert ) { var $tree = $( html ).find( "#MyTree" ); $tree.tree( { dataSource: this.dataSource, folderSelect: false } ); $tree.tree( "selectFolder", $tree.find( ".tree-branch-name:eq(1)" ) ); assert.equal( $tree.tree( "selectedItems" ).length, 0, "Return no value" ); } ); QUnit.test( "folders should open and close correctly", function( assert ) { var $tree = $( html ).find( "#MyTree" ); $tree.tree( { dataSource: this.dataSource } ); var $targetBranch = $( $tree.find( ".tree-branch" )[ 0 ] ); assert.equal( $targetBranch.hasClass( "tree-open" ), false, "Branch starts closed" ); $tree.tree( "discloseFolder", $targetBranch ); assert.equal( $targetBranch.hasClass( "tree-open" ), true, "discloseFolder opens folder" ); $tree.tree( "discloseFolder", $targetBranch ); assert.equal( $targetBranch.hasClass( "tree-open" ), true, "redundant discloseFolder calls leaves folder open" ); $tree.tree( "closeFolder", $targetBranch ); assert.equal( $targetBranch.hasClass( "tree-open" ), false, "closeFolder closes folder" ); $tree.tree( "closeFolder", $targetBranch ); assert.equal( $targetBranch.hasClass( "tree-open" ), false, "redundant closeFolder calls leaves folder closed" ); $tree.tree( "toggleFolder", $targetBranch ); assert.equal( $targetBranch.hasClass( "tree-open" ), true, "toggleFolder on closed folder opens folder" ); $tree.tree( "toggleFolder", $targetBranch ); assert.equal( $targetBranch.hasClass( "tree-open" ), false, "toggleFolder on open folder closes folder" ); } ); QUnit.test( "should disclose visible folders", function( assert ) { var ready = assert.async(); var $tree = $( "body" ).find( "#MyTree" ); $tree.tree( { dataSource: this.dataSource } ); var toBeOpened = $tree.find( ".tree-branch:not('.tree-open, .hidden')" ).length; assert.equal( $tree.find( ".tree-branch.tree-open:not('.hidden')" ).length, 0, "0 folders open" ); $tree.one( "disclosedVisible.fu.tree", function() { assert.equal( $tree.find( ".tree-branch.tree-open:not('.hidden')" ).length, toBeOpened, toBeOpened + " folders open" ); ready(); } ); $tree.tree( "discloseVisible" ); } ); QUnit.test( "should disclose all folders up to limit, and then close them, then open them all", function( assert ) { var ready = assert.async(); var $tree = $( "body" ).find( "#MyTree2" ); $tree.tree( { dataSource: this.dataSource, disclosuresUpperLimit: 2 } ); assert.equal( $tree.find( ".tree-branch.tree-open:not('.hidden')" ).length, 0, "0 folders open" ); $tree.one( "exceededDisclosuresLimit.fu.tree", function exceededDisclosuresLimit() { assert.equal( $tree.find( ".tree-branch.tree-open:not('.hidden')" ).length, 20, "20 folders open" ); $tree.one( "closedAll.fu.tree", function closedAll() { assert.equal( $tree.find( ".tree-branch.tree-open:not('.hidden')" ).length, 0, "0 folders open" ); $tree.data( "ignore-disclosures-limit", true ); $tree.one( "disclosedAll.fu.tree", function exceededDisclosuresLimit() { assert.equal( $tree.find( ".tree-branch.tree-open:not('.hidden')" ).length, 200, "200 folders open" ); ready(); } ); $tree.tree( "discloseAll" ); } ); $tree.tree( "closeAll" ); } ); $tree.tree( "discloseAll" ); } ); QUnit.test( "should refresh an already opened/cached folder with new nodes", function( assert ) { var $tree = $( html ).find( "#MyTree" ); var $folderToRefresh; var initialLoadedFolderId, refreshedLoadedFolderId; var selector = ".tree-branch-children > li:eq(0)"; $tree.tree( { dataSource: this.dataSource } ); $folderToRefresh = $tree.find( ".tree-branch:eq(1)" ); // Open folder $tree.tree( "discloseFolder", $folderToRefresh.find( ".tree-branch-name" ) ); assert.equal( $folderToRefresh.find( ".tree-branch-children > li" ).length, NUM_CHILDREN, "Folder has been populated with items/sub-folders" ); initialLoadedFolderId = $folderToRefresh.find( selector ).attr( "id" ); // Refresh and see if it's the same ID $tree.tree( "refreshFolder", $folderToRefresh ); refreshedLoadedFolderId = $folderToRefresh.find( ".tree-branch-children > li:eq(0)" ).attr( "id" ); assert.notEqual( refreshedLoadedFolderId, initialLoadedFolderId, "Folder has been refreshed and populated with different items/sub-folders" ); } ); QUnit.test( "should destroy control", function( assert ) { var $tree = $( html ).find( "#MyTree" ); $tree.tree( { dataSource: this.dataSource } ); assert.equal( typeof ( $tree.tree( "destroy" ) ), "string", "returns string (markup)" ); assert.equal( $tree.parent().length, false, "control has been removed from DOM" ); } ); QUnit.test( "Tree should accept TEXT as the NAME property in the datasource", function( assert ) { var $tree = $( html ).find( "#MyTree" ); $tree.tree( { dataSource: this.textDataSource } ); $tree.tree( "selectFolder", $tree.find( ".tree-branch-name:eq(1)" ) ); assert.equal( $tree.tree( "selectedItems" )[ 0 ].text, "node text", "Param TEXT used in the datasource" ); } ); } );