pgadmin4/web/regression/javascript/tree/tree_spec.js
2022-01-20 16:58:21 +05:30

377 lines
12 KiB
JavaScript

//////////////////////////////////////////////////////////////////////////
//
// pgAdmin 4 PostgreSQL Tools
//
// Copyright (C) 2013 2021, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
import {Tree} from '../../../pgadmin/static/js/tree/tree';
import {TreeNode, ManageTreeNodes} from '../../../pgadmin/static/js/tree/tree_nodes';
import {TreeFake} from './tree_fake';
const context = describe;
const treeTests = (treeClass, setDefaultCallBack) => {
let tree;
beforeEach(() => {
let manageTree = new ManageTreeNodes();
let reactTree = jasmine.createSpyObj(
'tree', ['onTreeEvents', 'getActiveFile']);
tree = new treeClass(reactTree, manageTree);
});
describe('#addNewNode', () => {
beforeEach(() => {
tree.rootNode = new TreeNode(undefined, {});
});
describe('when add a new root element', () => {
context('using undefined as the parent', () => {
beforeEach(() => {
tree.addNewNode('some new node', {data: 'interesting'}, undefined, undefined);
});
it('can be retrieved', () => {
const node = tree.findNode('/browser/some new node');
expect(node.data).toEqual({data: 'interesting'});
});
it('return false for #hasParent()', () => {
const node = tree.findNode('/browser/some new node');
expect(node.hasParent()).toEqual(false);
});
it('return null for #parent()', () => {
const node = tree.findNode('/browser/some new node');
expect(node.parent()).toBeNull();
});
});
context('using null as the parent', () => {
beforeEach(() => {
tree.addNewNode('some new node', {data: 'interesting'}, undefined, null);
});
it('can be retrieved', () => {
const node = tree.findNode('/browser/some new node');
expect(node.data).toEqual({data: 'interesting'});
});
it('return false for #hasParent()', () => {
const node = tree.findNode('/browser/some new node');
expect(node.hasParent()).toEqual(false);
});
it('return null for #parent()', () => {
const node = tree.findNode('/browser/some new node');
expect(node.parent()).toBeNull();
});
});
});
describe('when add a new element as a child', () => {
let parentNode;
beforeEach(() => {
parentNode = tree.addNewNode('parent node', {data: 'parent data'}, undefined, undefined);
tree.addNewNode('some new node', {data: 'interesting'}, undefined, '/browser/parent node');
});
it('can be retrieved', () => {
const node = tree.findNode('/browser/parent node/some new node');
expect(node.data).toEqual({data: 'interesting'});
});
it('return true for #hasParent()', () => {
const node = tree.findNode('/browser/parent node/some new node');
expect(node.hasParent()).toEqual(true);
});
it('return "parent node" object for #parent()', () => {
const node = tree.findNode('/browser/parent node/some new node');
expect(node.parent()).toEqual(parentNode);
});
});
describe('when add an element that already exists under a parent', () => {
beforeEach(() => {
tree.addNewNode('parent node', {data: 'parent data'}, undefined, undefined);
tree.addNewNode('some new node', {data: 'interesting'}, undefined, '/browser/parent node');
});
it('does not add a new child', () => {
tree.addNewNode('some new node', {data: 'interesting 1'}, undefined, '/browser/parent node');
const parentNode = tree.findNode('/browser/parent node');
expect(parentNode.children.length).toEqual(1);
});
it('updates the existing node data', () => {
tree.addNewNode('some new node', {data: 'interesting 1'}, undefined, '/browser/parent node');
const node = tree.findNode('/browser/parent node/some new node');
expect(node.data).toEqual({data: 'interesting 1'});
});
});
});
describe('#selected', () => {
context('a node in the tree is selected', () => {
it('returns that node object', () => {
let selectedNode = new TreeNode('bamm', {}, []);
setDefaultCallBack(tree, selectedNode);
expect(tree.selected()).toEqual(selectedNode);
});
});
});
describe('#findNodeByTreeElement', () => {
context('retrieve data from node not found', () => {
it('return undefined', () => {
let reactTree = jasmine.createSpyObj('tree', [
'hasParent',
'parent',
'getId',
'onTreeEvents',
]);
reactTree.getId.and.callFake((node) => {
return node[0].id;
});
tree.tree = reactTree;
expect(tree.findNodeByDomElement(['<li>something</li>'])).toBeUndefined();
});
});
});
};
describe('tree tests', () => {
describe('TreeNode', () => {
describe('#hasParent', () => {
context('parent is null', () => {
it('returns false', () => {
let treeNode = new TreeNode('123', {}, [], null);
expect(treeNode.hasParent()).toEqual(false);
});
});
context('parent is undefined', () => {
it('returns false', () => {
let treeNode = new TreeNode('123', {}, [], undefined);
expect(treeNode.hasParent()).toEqual(false);
});
});
context('parent exists', () => {
it('returns true', () => {
let parentNode = new TreeNode('456', {}, []);
let treeNode = new TreeNode('123', {}, [], parentNode);
expect(treeNode.hasParent()).toEqual(true);
});
});
});
describe('#reload', () => {
let tree;
let level2;
beforeEach(() => {
tree = new TreeFake();
tree.addNewNode('level1', {data: 'interesting'}, [{id: 'level1'}], undefined);
level2 = tree.addNewNode('level2', {data: 'data'}, [{id: 'level2'}], ['level1']);
tree.addNewNode('level3', {data: 'more data'}, [{id: 'level3'}], ['level1', 'level2']);
tree.tree = jasmine.createSpyObj(
'tree', ['unload', 'onTreeEvents',
'setActiveFile', 'closeDirectory', 'getActiveFile',
'deSelectActiveFile']);
tree.tree.unload.and.callFake(function() {
return Promise.resolve('Success!');
});
});
it('reloads the node and its children', (done) => {
level2.reload(tree)
.then(()=>{
expect(tree.findNodeByDomElement([{id: 'level2'}])).toEqual(level2);
done();
})
.catch((error)=>{
fail(error);
});
});
it('does not reload the children of node', (done) => {
level2.reload(tree)
.then(()=>{
expect(tree.findNodeByDomElement([{id: 'level3'}])).toBeNull();
done();
})
.catch((error)=>{
fail(error);
});
});
it('select the node', (done) => {
level2.reload(tree)
.then(()=>{
setTimeout(() => {
expect(tree.selected()).toEqual([{id: 'level2'}]);
done();
}, 20);
})
.catch((error)=>{
fail(error);
});
});
describe('ReactTree specific', () => {
it('sets the current node as a Inode, changing the Icon back to +', (done) => {
level2.reload(tree)
.then(()=>{
expect(tree.tree.closeDirectory).toHaveBeenCalledWith([{id: 'level2'}]);
done();
})
.catch((error)=>{
fail(error);
});
});
it('deselect the node and selects it again to trigger React tree' +
' events', (done) => {
level2.reload(tree)
.then(()=>{
setTimeout(() => {
expect(tree.tree.deSelectActiveFile).toHaveBeenCalledWith([{id: 'level2'}]);
done();
}, 20);
})
.catch((error)=>{
fail(error);
});
});
});
});
describe('#unload', () => {
let tree;
let level2;
beforeEach(() => {
tree = new TreeFake();
tree.addNewNode('level1', {data: 'interesting'}, ['<li>level1</li>'], undefined);
level2 = tree.addNewNode('level2', {data: 'data'}, ['<li>level2</li>'], ['level1']);
tree.addNewNode('level3', {data: 'more data'}, ['<li>level3</li>'], ['level1','level2']);
tree.tree = jasmine.createSpyObj('tree', ['unload']);
tree.tree.unload.and.callFake(() => {
return Promise.resolve('Success!');
});
});
it('unloads the children of the current node', (done) => {
level2.unload(tree)
.then(()=>{
expect(tree.findNodeByDomElement([{id: 'level2'}])).toEqual(level2);
expect(tree.findNodeByDomElement([{id: 'level3'}])).toBeNull();
done();
})
.catch((error)=>{
fail(error);
});
});
it('calls unload on the React Tree', (done) => {
level2.unload(tree)
.then(()=>{
expect(tree.tree.unload).toHaveBeenCalledWith(['<li>level2</li>']);
done();
})
.catch((error)=>{
fail(error);
});
});
});
});
describe('Tree', () => {
function realTreeSelectNode(tree, selectedNode) {
let reactTree = jasmine.createSpyObj('tree', [
'getActiveFile',
]);
tree.tree = reactTree;
reactTree.getActiveFile.and.returnValue(selectedNode);
}
treeTests(Tree, realTreeSelectNode);
});
describe('TreeFake', () => {
function fakeTreeSelectNode(tree, selectedNode) {
tree.selectNode(selectedNode);
}
treeTests(TreeFake, fakeTreeSelectNode);
describe('#hasParent', () => {
context('tree contains multiple levels', () => {
let tree;
beforeEach(() => {
tree = new TreeFake();
tree.addNewNode('level1', {data: 'interesting'}, undefined, undefined);
tree.addNewNode('level2', {data: 'interesting'}, undefined, '/browser/level1');
});
context('node is at the first level', () => {
it('returns false', () => {
expect(tree.hasParent([{id: 'level1'}])).toEqual(false);
});
});
context('node is at the second level', () => {
it('returns true', () => {
expect(tree.hasParent([{id: 'level2'}])).toEqual(true);
});
});
});
});
describe('#parent', () => {
let tree;
beforeEach(() => {
tree = new TreeFake();
tree.addNewNode('level1', {data: 'interesting'}, undefined, undefined);
tree.addNewNode('level2', {data: 'interesting'}, undefined, ['level1']);
});
context('node is the root', () => {
it('returns null', () => {
expect(tree.parent([{id: 'level1'}])).toBeNull();
});
});
context('node is not root', () => {
it('returns root element', () => {
expect(tree.parent([{id: 'level2'}])).toEqual([{id: 'level1'}]);
});
});
});
describe('#addChild', () => {
let root, child;
beforeEach(() => {
let tree = new TreeFake();
root = tree.addNewNode('root', {}, [{id: 'root'}]);
child = new TreeNode('node.1', {}, [{id: 'node.1'}]);
tree.addChild(root, child);
});
it('adds a new child to a node', () => {
expect(root.children).toEqual([child]);
});
it('changes the parent of the child node', () => {
expect(root.children[0].parentNode).toEqual(root);
expect(child.parentNode).toEqual(root);
});
it('changes the path of the child', () => {
expect(child.path).toEqual('/browser/root/node.1');
});
});
});
});