igniteui-angular-sovn
Version:
Ignite UI for Angular is a dependency-free Angular toolkit for building modern web apps
656 lines (549 loc) • 33 kB
text/typescript
import { EventEmitter } from '@angular/core';
import { configureTestSuite } from '../test-utils/configure-suite';
import { IgxTree, IgxTreeNode, IgxTreeSelectionType, ITreeNodeSelectionEvent } from './common';
import { TreeTestFunctions } from './tree-functions.spec';
import { IgxTreeNodeComponent } from './tree-node/tree-node.component';
import { IgxTreeSelectionService } from './tree-selection.service';
describe('IgxTreeSelectionService - Unit Tests #treeView', () => {
configureTestSuite();
let selectionService: IgxTreeSelectionService;
let mockEmitter: EventEmitter<ITreeNodeSelectionEvent>;
let mockTree: IgxTree;
let mockNodesLevel1: IgxTreeNodeComponent<any>[];
let mockNodesLevel2_1: IgxTreeNodeComponent<any>[];
let mockNodesLevel2_2: IgxTreeNodeComponent<any>[];
let mockNodesLevel3_1: IgxTreeNodeComponent<any>[];
let mockNodesLevel3_2: IgxTreeNodeComponent<any>[];
let allNodes: IgxTreeNodeComponent<any>[];
const mockQuery1: any = {};
const mockQuery2: any = {};
const mockQuery3: any = {};
const mockQuery4: any = {};
const mockQuery5: any = {};
const mockQuery6: any = {};
beforeEach(() => {
selectionService = new IgxTreeSelectionService();
mockNodesLevel1 = TreeTestFunctions.createNodeSpies(0, 3, null, [mockQuery2, mockQuery3], [mockQuery6, mockQuery3]);
mockNodesLevel2_1 = TreeTestFunctions.createNodeSpies(1, 2, mockNodesLevel1[0], [mockQuery4, mockQuery5], [mockQuery4, mockQuery5]);
mockNodesLevel2_2 = TreeTestFunctions.createNodeSpies(1, 1, mockNodesLevel1[1], null);
mockNodesLevel3_1 = TreeTestFunctions.createNodeSpies(2, 2, mockNodesLevel2_1[0], null);
mockNodesLevel3_2 = TreeTestFunctions.createNodeSpies(2, 2, mockNodesLevel2_1[1], null);
allNodes = [
mockNodesLevel1[0],
mockNodesLevel2_1[0],
...mockNodesLevel3_1,
mockNodesLevel2_1[1],
...mockNodesLevel3_2,
mockNodesLevel1[1],
...mockNodesLevel2_2,
mockNodesLevel1[2]
];
Object.assign(mockQuery1, TreeTestFunctions.createQueryListSpy(allNodes));
Object.assign(mockQuery2, TreeTestFunctions.createQueryListSpy(mockNodesLevel2_1));
Object.assign(mockQuery3, TreeTestFunctions.createQueryListSpy(mockNodesLevel2_2));
Object.assign(mockQuery4, TreeTestFunctions.createQueryListSpy(mockNodesLevel3_1));
Object.assign(mockQuery5, TreeTestFunctions.createQueryListSpy(mockNodesLevel3_2));
Object.assign(mockQuery6, TreeTestFunctions.createQueryListSpy([
mockNodesLevel2_1[0],
...mockNodesLevel3_1,
mockNodesLevel2_1[1],
...mockNodesLevel3_2
]));
});
describe('IgxTreeSelectionService - BiState & None', () => {
beforeEach(() => {
mockEmitter = jasmine.createSpyObj('emitter', ['emit']);
mockTree = jasmine.createSpyObj('tree', [''],
{ selection: IgxTreeSelectionType.BiState, nodeSelection: mockEmitter, nodes: mockQuery1 });
selectionService.register(mockTree);
});
it('Should properly register the specified tree', () => {
selectionService = new IgxTreeSelectionService();
expect((selectionService as any).tree).toBeFalsy();
selectionService.register(mockTree);
expect((selectionService as any).tree).toEqual(mockTree);
});
it('Should return proper value when isNodeSelected is called', () => {
const selectionSet: Set<IgxTreeNode<any>> = (selectionService as any).nodeSelection;
expect(selectionSet.size).toBe(0);
spyOn(selectionSet, 'clear').and.callThrough();
const mockNode1 = TreeTestFunctions.createNodeSpy();
const mockNode2 = TreeTestFunctions.createNodeSpy();
expect(selectionService.isNodeSelected(mockNode1)).toBeFalsy();
expect(selectionService.isNodeSelected(mockNode2)).toBeFalsy();
selectionSet.add(mockNode1);
expect(selectionService.isNodeSelected(mockNode1)).toBeTruthy();
expect(selectionService.isNodeSelected(mockNode2)).toBeFalsy();
expect(selectionSet.size).toBe(1);
selectionService.clearNodesSelection();
expect(selectionService.isNodeSelected(mockNode1)).toBeFalsy();
expect(selectionService.isNodeSelected(mockNode2)).toBeFalsy();
expect(selectionSet.clear).toHaveBeenCalled();
expect(selectionSet.size).toBe(0);
});
it('Should handle selection based on tree.selection', () => {
const mockSelectedChangeEmitter: EventEmitter<boolean> = jasmine.createSpyObj('emitter', ['emit']);
const mockNode = TreeTestFunctions.createNodeSpy({ selectedChange: mockSelectedChangeEmitter });
// None
(Object.getOwnPropertyDescriptor(mockTree, 'selection').get as jasmine.Spy<any>).and.returnValue(IgxTreeSelectionType.None);
selectionService.selectNode(mockNode);
expect(selectionService.isNodeSelected(mockNode)).toBeFalsy();
expect(mockTree.nodeSelection.emit).not.toHaveBeenCalled();
expect(mockNode.selectedChange.emit).not.toHaveBeenCalled();
// BiState
(Object.getOwnPropertyDescriptor(mockTree, 'selection').get as jasmine.Spy<any>)
.and.returnValue(IgxTreeSelectionType.BiState);
let expected: ITreeNodeSelectionEvent = {
oldSelection: [], newSelection: [mockNode],
added: [mockNode], removed: [], event: undefined, cancel: false, owner: mockTree
};
selectionService.selectNode(mockNode);
expect(selectionService.isNodeSelected(mockNode)).toBeTruthy();
expect(mockTree.nodeSelection.emit).toHaveBeenCalledTimes(1);
expect(mockTree.nodeSelection.emit).toHaveBeenCalledWith(expected);
expect(mockNode.selectedChange.emit).toHaveBeenCalledTimes(1);
expect(mockNode.selectedChange.emit).toHaveBeenCalledWith(true);
// Cascading
selectionService.deselectNode(mockNode);
(Object.getOwnPropertyDescriptor(mockTree, 'selection').get as jasmine.Spy<any>)
.and.returnValue(IgxTreeSelectionType.Cascading);
selectionService.selectNode(allNodes[1]);
expected = {
oldSelection: [], newSelection: [allNodes[1], allNodes[2], allNodes[3]],
added: [allNodes[1], allNodes[2], allNodes[3]], removed: [], event: undefined, cancel: false, owner: mockTree
};
expect(selectionService.isNodeSelected(allNodes[1])).toBeTruthy();
expect(selectionService.isNodeSelected(allNodes[2])).toBeTruthy();
expect(selectionService.isNodeSelected(allNodes[3])).toBeTruthy();
expect(selectionService.isNodeIndeterminate(allNodes[0])).toBeTruthy();
expect(mockTree.nodeSelection.emit).toHaveBeenCalledTimes(3);
expect(mockTree.nodeSelection.emit).toHaveBeenCalledWith(expected);
for (let i = 1; i < 4; i++) {
expect(allNodes[i].selectedChange.emit).toHaveBeenCalled();
expect(allNodes[i].selectedChange.emit).toHaveBeenCalledWith(true);
}
});
it('Should deselect nodes', () => {
const mockSelectedChangeEmitter: EventEmitter<boolean> = jasmine.createSpyObj('emitter', ['emit']);
const mockNode1 = TreeTestFunctions.createNodeSpy({ selectedChange: mockSelectedChangeEmitter });
const mockNode2 = TreeTestFunctions.createNodeSpy({ selectedChange: mockSelectedChangeEmitter });
selectionService.deselectNode(mockNode1);
expect(selectionService.isNodeSelected(mockNode1)).toBeFalsy();
expect(selectionService.isNodeSelected(mockNode2)).toBeFalsy();
expect(mockTree.nodeSelection.emit).not.toHaveBeenCalled();
expect(mockNode1.selectedChange.emit).not.toHaveBeenCalled();
// mark a node as selected
selectionService.selectNode(mockNode1);
expect(selectionService.isNodeSelected(mockNode1)).toBeTruthy();
expect(selectionService.isNodeSelected(mockNode2)).toBeFalsy();
expect(mockTree.nodeSelection.emit).toHaveBeenCalledTimes(1);
expect(mockNode1.selectedChange.emit).toHaveBeenCalledTimes(1);
expect(mockNode1.selectedChange.emit).toHaveBeenCalledWith(true);
// deselect node
const expected: ITreeNodeSelectionEvent = {
newSelection: [], oldSelection: [mockNode1],
removed: [mockNode1], added: [], event: undefined, cancel: false, owner: mockTree
};
selectionService.deselectNode(mockNode1);
expect(selectionService.isNodeSelected(mockNode1)).toBeFalsy();
expect(selectionService.isNodeSelected(mockNode2)).toBeFalsy();
expect(mockTree.nodeSelection.emit).toHaveBeenCalledTimes(2);
expect(mockTree.nodeSelection.emit).toHaveBeenCalledWith(expected);
expect(mockNode1.selectedChange.emit).toHaveBeenCalledTimes(2);
expect(mockNode1.selectedChange.emit).toHaveBeenCalledWith(false);
});
it('Should be able to deselect all nodes', () => {
selectionService.selectNodesWithNoEvent(allNodes.slice(0, 3));
for (const node of allNodes.slice(0, 3)) {
expect(selectionService.isNodeSelected(node)).toBeTruthy();
expect(node.selectedChange.emit).toHaveBeenCalled();
expect(node.selectedChange.emit).toHaveBeenCalledWith(true);
}
expect(mockTree.nodeSelection.emit).not.toHaveBeenCalled();
selectionService.deselectNodesWithNoEvent();
for (const node of allNodes.slice(0, 3)) {
expect(selectionService.isNodeSelected(node)).toBeFalsy();
expect(node.selectedChange.emit).toHaveBeenCalled();
expect(node.selectedChange.emit).toHaveBeenCalledWith(false);
}
expect(mockTree.nodeSelection.emit).not.toHaveBeenCalled();
});
it('Should be able to deselect range of nodes', () => {
selectionService.selectNodesWithNoEvent(allNodes.slice(0, 3));
for (const node of allNodes.slice(0, 3)) {
expect(selectionService.isNodeSelected(node)).toBeTruthy();
expect(node.selectedChange.emit).toHaveBeenCalled();
expect(node.selectedChange.emit).toHaveBeenCalledWith(true);
}
expect(mockTree.nodeSelection.emit).not.toHaveBeenCalled();
selectionService.deselectNodesWithNoEvent([allNodes[0], allNodes[2]]);
expect(selectionService.isNodeSelected(allNodes[0])).toBeFalsy();
expect(selectionService.isNodeSelected(allNodes[2])).toBeFalsy();
expect(allNodes[0].selectedChange.emit).toHaveBeenCalled();
expect(allNodes[0].selectedChange.emit).toHaveBeenCalledWith(false);
expect(allNodes[2].selectedChange.emit).toHaveBeenCalled();
expect(allNodes[2].selectedChange.emit).toHaveBeenCalledWith(false);
expect(mockTree.nodeSelection.emit).not.toHaveBeenCalled();
});
it('Should be able to select multiple nodes', () => {
selectionService.selectNodesWithNoEvent(allNodes.slice(0, 3));
for (const node of allNodes.slice(0, 3)) {
expect(selectionService.isNodeSelected(node)).toBeTruthy();
expect(node.selectedChange.emit).toHaveBeenCalled();
expect(node.selectedChange.emit).toHaveBeenCalledWith(true);
}
expect(selectionService.isNodeSelected(allNodes[3])).toBeFalsy();
selectionService.selectNodesWithNoEvent([allNodes[3]]);
for (const node of allNodes.slice(0, 4)) {
expect(selectionService.isNodeSelected(node)).toBeTruthy();
}
expect(allNodes[3].selectedChange.emit).toHaveBeenCalled();
expect(allNodes[3].selectedChange.emit).toHaveBeenCalledWith(true);
expect(mockTree.nodeSelection.emit).not.toHaveBeenCalled();
});
it('Should be able to clear selection when adding multiple nodes', () => {
selectionService.selectNodesWithNoEvent(allNodes.slice(0, 3));
for (const node of allNodes.slice(0, 3)) {
expect(selectionService.isNodeSelected(node)).toBeTruthy();
expect(node.selectedChange.emit).toHaveBeenCalled();
expect(node.selectedChange.emit).toHaveBeenCalledWith(true);
}
expect(selectionService.isNodeSelected(allNodes[3])).toBeFalsy();
selectionService.selectNodesWithNoEvent(allNodes.slice(1, 4), true);
for (const node of allNodes.slice(1, 4)) {
expect(selectionService.isNodeSelected(node)).toBeTruthy();
expect(node.selectedChange.emit).toHaveBeenCalled();
expect(node.selectedChange.emit).toHaveBeenCalledWith(true);
}
expect(selectionService.isNodeSelected(allNodes[0])).toBeFalsy();
expect(mockTree.nodeSelection.emit).not.toHaveBeenCalled();
});
it('Should add newly selected nodes to the existing selection', () => {
selectionService.selectNode(mockTree.nodes.first);
let expected: ITreeNodeSelectionEvent = {
oldSelection: [], newSelection: [mockQuery1.first],
added: [mockQuery1.first], removed: [], event: undefined, cancel: false, owner: mockTree
};
expect(selectionService.isNodeSelected(allNodes[0])).toBeTruthy();
expect(mockTree.nodes.first.selectedChange.emit).toHaveBeenCalled();
expect(mockTree.nodes.first.selectedChange.emit).toHaveBeenCalledWith(true);
for (let i = 1; i < allNodes.length; i++) {
expect(selectionService.isNodeSelected(allNodes[i])).toBeFalsy();
}
expect(mockTree.nodeSelection.emit).toHaveBeenCalledWith(expected);
expect(mockTree.nodeSelection.emit).toHaveBeenCalledTimes(1);
expected = {
oldSelection: [allNodes[0]], newSelection: [allNodes[0], allNodes[1]],
added: [allNodes[1]], removed: [], event: undefined, cancel: false, owner: mockTree
};
selectionService.selectNode(mockTree.nodes.toArray()[1]);
expect(mockTree.nodes.toArray()[1].selectedChange.emit).toHaveBeenCalled();
expect(mockTree.nodes.toArray()[1].selectedChange.emit).toHaveBeenCalledWith(true);
expect(mockTree.nodeSelection.emit).toHaveBeenCalledWith(expected);
expect(mockTree.nodeSelection.emit).toHaveBeenCalledTimes(2);
expect(selectionService.isNodeSelected(allNodes[0])).toBeTruthy();
expect(selectionService.isNodeSelected(allNodes[1])).toBeTruthy();
});
it('Should be able to select a range of nodes', () => {
selectionService.selectNode(allNodes[3]);
// only third node is selected
expect(selectionService.isNodeSelected(allNodes[3])).toBeTruthy();
expect(allNodes[3].selectedChange.emit).toHaveBeenCalled();
expect(allNodes[3].selectedChange.emit).toHaveBeenCalledWith(true);
for (let i = 0; i < allNodes.length; i++) {
if (i !== 3) {
expect(selectionService.isNodeSelected(allNodes[i])).toBeFalsy();
}
}
// select all nodes from third to eighth
selectionService.selectMultipleNodes(allNodes[8]);
allNodes.forEach((node, index) => {
if (index >= 3 && index <= 8) {
expect(selectionService.isNodeSelected(node)).toBeTruthy();
expect(node.selectedChange.emit).toHaveBeenCalled();
expect(node.selectedChange.emit).toHaveBeenCalledWith(true);
} else {
expect(selectionService.isNodeSelected(node)).toBeFalsy();
}
});
const expected: ITreeNodeSelectionEvent = {
oldSelection: [allNodes[3]], newSelection: allNodes.slice(3, 9),
added: allNodes.slice(4, 9), removed: [], event: undefined, cancel: false, owner: mockTree
};
expect(mockTree.nodeSelection.emit).toHaveBeenCalledWith(expected);
});
it('Should be able to select a range of nodes in reverse order', () => {
selectionService.selectNode(allNodes[8]);
// only eighth node is selected
expect(selectionService.isNodeSelected(allNodes[8])).toBeTruthy();
expect(allNodes[8].selectedChange.emit).toHaveBeenCalled();
expect(allNodes[8].selectedChange.emit).toHaveBeenCalledWith(true);
for (let i = 0; i < allNodes.length; i++) {
if (i !== 8) {
expect(selectionService.isNodeSelected(allNodes[i])).toBeFalsy();
}
}
// select all nodes from eighth to second
selectionService.selectMultipleNodes(allNodes[2]);
allNodes.forEach((node, index) => {
if (index >= 2 && index <= 8) {
expect(selectionService.isNodeSelected(node)).toBeTruthy();
expect(node.selectedChange.emit).toHaveBeenCalled();
expect(node.selectedChange.emit).toHaveBeenCalledWith(true);
} else {
expect(selectionService.isNodeSelected(node)).toBeFalsy();
}
});
const expected: ITreeNodeSelectionEvent = {
oldSelection: [allNodes[8]], newSelection: [allNodes[8], ...allNodes.slice(2, 8)],
added: allNodes.slice(2, 8), removed: [], event: undefined, cancel: false, owner: mockTree
};
expect(mockTree.nodeSelection.emit).toHaveBeenCalledWith(expected);
});
});
describe('IgxTreeSelectionService - Cascading', () => {
beforeEach(() => {
mockEmitter = jasmine.createSpyObj('emitter', ['emit']);
mockTree = jasmine.createSpyObj('tree', [''],
{ selection: IgxTreeSelectionType.Cascading, nodeSelection: mockEmitter, nodes: mockQuery1 });
selectionService.register(mockTree);
});
it('Should deselect nodes', () => {
selectionService.deselectNode(allNodes[1]);
for (const node of allNodes.slice(1, 4)) {
expect(selectionService.isNodeSelected(node)).toBeFalsy();
expect(node.selectedChange.emit).not.toHaveBeenCalled();
}
expect(mockTree.nodeSelection.emit).not.toHaveBeenCalled();
// mark a node as selected
selectionService.selectNode(allNodes[1]);
for (const node of allNodes.slice(1, 4)) {
expect(selectionService.isNodeSelected(node)).toBeTruthy();
expect(node.selectedChange.emit).toHaveBeenCalled();
expect(node.selectedChange.emit).toHaveBeenCalledWith(true);
}
expect(selectionService.isNodeIndeterminate(allNodes[0])).toBeTruthy();
expect(allNodes[0].selectedChange.emit).not.toHaveBeenCalled();
expect(mockTree.nodeSelection.emit).toHaveBeenCalledTimes(1);
const expected: ITreeNodeSelectionEvent = {
newSelection: [], oldSelection: [allNodes[1], allNodes[2], allNodes[3]],
removed: [allNodes[1], allNodes[2], allNodes[3]], added: [], event: undefined, cancel: false, owner: mockTree
};
// deselect node
selectionService.deselectNode(allNodes[1]);
for (const node of allNodes.slice(1, 4)) {
expect(selectionService.isNodeSelected(node)).toBeFalsy();
expect(node.selectedChange.emit).toHaveBeenCalled();
expect(node.selectedChange.emit).toHaveBeenCalledWith(false);
}
expect(selectionService.isNodeIndeterminate(allNodes[0])).toBeFalse();
expect(mockTree.nodeSelection.emit).toHaveBeenCalledTimes(2);
expect(mockTree.nodeSelection.emit).toHaveBeenCalledWith(expected);
});
it('Should be able to deselect range of nodes', () => {
selectionService.selectNodesWithNoEvent([allNodes[1], allNodes[4]]);
for (const node of allNodes.slice(0, 7)) {
expect(selectionService.isNodeSelected(node)).toBeTruthy();
expect(node.selectedChange.emit).toHaveBeenCalled();
expect(node.selectedChange.emit).toHaveBeenCalledWith(true);
}
expect(mockTree.nodeSelection.emit).not.toHaveBeenCalled();
selectionService.deselectNodesWithNoEvent([allNodes[1], allNodes[5]]);
for (const node of allNodes.slice(1, 4)) {
expect(selectionService.isNodeSelected(node)).toBeFalsy();
expect(node.selectedChange.emit).toHaveBeenCalled();
expect(node.selectedChange.emit).toHaveBeenCalledWith(false);
}
expect(selectionService.isNodeSelected(allNodes[5])).toBeFalsy();
expect(selectionService.isNodeSelected(allNodes[6])).toBeTruthy();
expect(selectionService.isNodeIndeterminate(allNodes[0])).toBeTruthy();
expect(selectionService.isNodeIndeterminate(allNodes[4])).toBeTruthy();
expect(mockTree.nodeSelection.emit).not.toHaveBeenCalled();
});
it('Should be able to select multiple nodes', () => {
selectionService.selectNodesWithNoEvent([allNodes[1], allNodes[8]]);
for (const node of allNodes.slice(1, 4)) {
expect(selectionService.isNodeSelected(node)).toBeTruthy();
expect(node.selectedChange.emit).toHaveBeenCalled();
expect(node.selectedChange.emit).toHaveBeenCalledWith(true);
}
expect(selectionService.isNodeSelected(allNodes[7])).toBeTruthy();
expect(selectionService.isNodeSelected(allNodes[8])).toBeTruthy();
expect(selectionService.isNodeIndeterminate(allNodes[0])).toBeTruthy();
expect(mockTree.nodeSelection.emit).not.toHaveBeenCalled();
});
it('Should be able to clear selection when adding multiple nodes', () => {
selectionService.selectNodesWithNoEvent([allNodes[1]], true);
for (const node of allNodes.slice(1, 4)) {
expect(selectionService.isNodeSelected(node)).toBeTruthy();
expect(node.selectedChange.emit).toHaveBeenCalled();
expect(node.selectedChange.emit).toHaveBeenCalledWith(true);
}
expect(selectionService.isNodeIndeterminate(allNodes[0])).toBeTruthy();
expect(mockTree.nodeSelection.emit).not.toHaveBeenCalled();
selectionService.selectNodesWithNoEvent([allNodes[3], allNodes[4]], true);
for (const node of allNodes.slice(3, 7)) {
expect(selectionService.isNodeSelected(node)).toBeTruthy();
expect(node.selectedChange.emit).toHaveBeenCalled();
expect(node.selectedChange.emit).toHaveBeenCalledWith(true);
}
expect(selectionService.isNodeIndeterminate(allNodes[0])).toBeTruthy();
expect(selectionService.isNodeIndeterminate(allNodes[1])).toBeTruthy();
expect(selectionService.isNodeSelected(allNodes[2])).toBeFalsy();
expect(mockTree.nodeSelection.emit).not.toHaveBeenCalled();
});
it('Should add newly selected nodes to the existing selection', () => {
selectionService.selectNode(allNodes[1]);
let expected: ITreeNodeSelectionEvent = {
oldSelection: [], newSelection: allNodes.slice(1, 4),
added: allNodes.slice(1, 4), removed: [], event: undefined, cancel: false, owner: mockTree
};
for (const node of allNodes.slice(1, 4)) {
expect(selectionService.isNodeSelected(node)).toBeTruthy();
expect(node.selectedChange.emit).toHaveBeenCalled();
expect(node.selectedChange.emit).toHaveBeenCalledWith(true);
}
for (let i = 4; i < allNodes.length; i++) {
expect(selectionService.isNodeSelected(allNodes[i])).toBeFalsy();
}
expect(selectionService.isNodeIndeterminate(allNodes[0])).toBeTruthy();
expect(mockTree.nodeSelection.emit).toHaveBeenCalledWith(expected);
expect(mockTree.nodeSelection.emit).toHaveBeenCalledTimes(1);
expected = {
oldSelection: allNodes.slice(1, 4), newSelection: [allNodes[1], allNodes[2], allNodes[3], allNodes[5]],
added: [allNodes[5]], removed: [], event: undefined, cancel: false, owner: mockTree
};
selectionService.selectNode(allNodes[5]);
for (const node of allNodes.slice(1, 4)) {
expect(selectionService.isNodeSelected(node)).toBeTruthy();
expect(node.selectedChange.emit).toHaveBeenCalled();
expect(node.selectedChange.emit).toHaveBeenCalledWith(true);
}
expect(selectionService.isNodeSelected(allNodes[5])).toBeTruthy();
expect(selectionService.isNodeIndeterminate(allNodes[0])).toBeTruthy();
expect(mockTree.nodeSelection.emit).toHaveBeenCalledWith(expected);
expect(mockTree.nodeSelection.emit).toHaveBeenCalledTimes(2);
});
it('Should be able to select a range of nodes', () => {
selectionService.selectNode(allNodes[3]);
expect(selectionService.isNodeSelected(allNodes[3])).toBeTruthy();
// select all nodes from first to eighth
selectionService.selectMultipleNodes(allNodes[8]);
allNodes.forEach((node, index) => {
if (index >= 4 && index <= 8) {
expect(selectionService.isNodeSelected(node)).toBeTruthy();
expect(node.selectedChange.emit).toHaveBeenCalled();
expect(node.selectedChange.emit).toHaveBeenCalledWith(true);
} else if (index === 3) {
expect(selectionService.isNodeSelected(node)).toBeTruthy();
} else {
expect(selectionService.isNodeSelected(node)).toBeFalsy();
}
});
const expected: ITreeNodeSelectionEvent = {
oldSelection: [allNodes[3]], newSelection: allNodes.slice(3, 9),
added: allNodes.slice(4, 9),
removed: [], event: undefined, cancel: false, owner: mockTree
};
expect(mockTree.nodeSelection.emit).toHaveBeenCalledWith(expected);
expect(selectionService.isNodeIndeterminate(allNodes[0])).toBeTruthy();
expect(selectionService.isNodeIndeterminate(allNodes[1])).toBeTruthy();
});
it('Should be able to select a range of nodes in reverse order', () => {
selectionService.selectNode(allNodes[8]);
// only seventh and eighth node are selected
expect(selectionService.isNodeSelected(allNodes[7])).toBeTruthy();
expect(selectionService.isNodeSelected(allNodes[8])).toBeTruthy();
expect(allNodes[7].selectedChange.emit).toHaveBeenCalled();
expect(allNodes[7].selectedChange.emit).toHaveBeenCalledWith(true);
expect(allNodes[8].selectedChange.emit).toHaveBeenCalled();
expect(allNodes[8].selectedChange.emit).toHaveBeenCalledWith(true);
expect(mockTree.nodeSelection.emit).toHaveBeenCalledTimes(1);
for (let i = 0; i < allNodes.length; i++) {
if (i !== 7 && i !== 8) {
expect(selectionService.isNodeSelected(allNodes[i])).toBeFalsy();
}
}
// select all nodes from eight to second
selectionService.selectMultipleNodes(allNodes[2]);
allNodes.forEach((node, index) => {
if (index <= 8) {
expect(selectionService.isNodeSelected(node)).toBeTruthy();
if (index < 7) {
expect(node.selectedChange.emit).toHaveBeenCalled();
expect(node.selectedChange.emit).toHaveBeenCalledWith(true);
}
} else {
expect(selectionService.isNodeSelected(node)).toBeFalsy();
}
});
const expected: ITreeNodeSelectionEvent = {
oldSelection: [allNodes[8], allNodes[7]],
newSelection: [allNodes[8], allNodes[7], ...allNodes.slice(2, 7), allNodes[1], allNodes[0]],
added: [...allNodes.slice(2, 7), allNodes[1], allNodes[0]], removed: [], event: undefined, cancel: false, owner: mockTree
};
expect(mockTree.nodeSelection.emit).toHaveBeenCalledWith(expected);
});
it('Should ensure correct state after a node entry is destroyed', () => {
// instant frames go 'BRRRR'
spyOn(window, 'requestAnimationFrame').and.callFake((callback: any) => callback());
const deselectSpy = spyOn(selectionService, 'deselectNodesWithNoEvent');
const selectSpy = spyOn(selectionService, 'selectNodesWithNoEvent');
const tree = {
selection: IgxTreeSelectionType.None
} as any;
const selectedNodeSpy = spyOn(selectionService, 'isNodeSelected').and.returnValue(false);
const mockNode = {
selected: false
} as any;
selectionService.register(tree);
selectionService.ensureStateOnNodeDelete(mockNode);
expect(deselectSpy).not.toHaveBeenCalled();
expect(selectSpy).not.toHaveBeenCalled();
expect(selectedNodeSpy).not.toHaveBeenCalled();
tree.selection = IgxTreeSelectionType.BiState;
selectionService.ensureStateOnNodeDelete(mockNode);
expect(deselectSpy).not.toHaveBeenCalled();
expect(selectSpy).not.toHaveBeenCalled();
expect(selectedNodeSpy).not.toHaveBeenCalled();
tree.selection = IgxTreeSelectionType.Cascading;
selectedNodeSpy.and.returnValue(true);
selectionService.ensureStateOnNodeDelete(mockNode);
expect(selectedNodeSpy).toHaveBeenCalledTimes(1);
expect(selectedNodeSpy).toHaveBeenCalledWith(mockNode);
expect(deselectSpy).toHaveBeenCalledTimes(1);
expect(deselectSpy).toHaveBeenCalledWith([mockNode], false);
expect(selectSpy).not.toHaveBeenCalled();
mockNode.parentNode = false;
selectedNodeSpy.and.returnValue(false);
selectionService.ensureStateOnNodeDelete(mockNode);
expect(selectedNodeSpy).toHaveBeenCalledTimes(2);
expect(deselectSpy).toHaveBeenCalledTimes(1);
expect(selectSpy).not.toHaveBeenCalled();
const childrenSpy = jasmine.createSpyObj('creep', ['find']);
childrenSpy.find.and.returnValue(null);
mockNode.parentNode = {
allChildren: childrenSpy
};
selectionService.ensureStateOnNodeDelete(mockNode);
expect(selectedNodeSpy).toHaveBeenCalledTimes(3);
expect(deselectSpy).toHaveBeenCalledTimes(1);
expect(selectSpy).not.toHaveBeenCalled();
const mockChild = {
selected: true
} as any;
childrenSpy.find.and.returnValue(mockChild);
selectionService.ensureStateOnNodeDelete(mockNode);
expect(selectedNodeSpy).toHaveBeenCalledTimes(4);
expect(deselectSpy).toHaveBeenCalledTimes(1);
expect(selectSpy).toHaveBeenCalledTimes(1);
expect(selectSpy).toHaveBeenCalledWith([mockChild], false, false);
mockChild.selected = false;
selectionService.ensureStateOnNodeDelete(mockNode);
expect(selectedNodeSpy).toHaveBeenCalledTimes(5);
expect(deselectSpy).toHaveBeenCalledTimes(2);
expect(deselectSpy).toHaveBeenCalledWith([mockChild], false);
expect(selectSpy).toHaveBeenCalledTimes(1);
});
});
});