mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-25 18:55:31 -06:00
Extract the tests and refactor some of the methods.
Extract some of the ACI Tree functionalities, and decouple it from the main source. Also - create some abstractions from the repeated code around the enable/disable the schema children object create/edit/delete functionalities, and also created the dialog wrappers for backup and restore dialogs. Reviewed by: Khushboo and Ashesh Refactored by: Ashesh
This commit is contained in:
committed by
Ashesh Vashi
parent
920934759f
commit
7dd6372eeb
205
web/regression/javascript/backup/backup_dialog_spec.js
Normal file
205
web/regression/javascript/backup/backup_dialog_spec.js
Normal file
@@ -0,0 +1,205 @@
|
||||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2018, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
import {BackupDialog} from '../../../pgadmin/tools/backup/static/js/backup_dialog';
|
||||
import {TreeFake} from '../tree/tree_fake';
|
||||
|
||||
const context = describe;
|
||||
|
||||
describe('BackupDialog', () => {
|
||||
let backupDialog;
|
||||
let pgBrowser;
|
||||
let jquerySpy;
|
||||
let alertifySpy;
|
||||
let backupModelSpy;
|
||||
|
||||
beforeEach(() => {
|
||||
pgBrowser = {
|
||||
treeMenu: new TreeFake(),
|
||||
Nodes: {
|
||||
server: {
|
||||
hasId: true,
|
||||
label: 'server',
|
||||
getTreeNodeHierarchy: jasmine.createSpy('server.getTreeNodeHierarchy'),
|
||||
},
|
||||
database: {
|
||||
hasId: true,
|
||||
label: 'database',
|
||||
getTreeNodeHierarchy: jasmine.createSpy('db.getTreeNodeHierarchy'),
|
||||
},
|
||||
schema: {
|
||||
hasId: true,
|
||||
label: 'schema',
|
||||
getTreeNodeHierarchy: jasmine.createSpy('db.getTreeNodeHierarchy'),
|
||||
},
|
||||
},
|
||||
};
|
||||
pgBrowser.Nodes.server.hasId = true;
|
||||
pgBrowser.Nodes.database.hasId = true;
|
||||
jquerySpy = jasmine.createSpy('jquerySpy');
|
||||
backupModelSpy = jasmine.createSpy('backupModelSpy');
|
||||
|
||||
const hierarchy = {
|
||||
children: [
|
||||
{
|
||||
id: 'root',
|
||||
children: [
|
||||
{
|
||||
id: 'serverTreeNode',
|
||||
data: {
|
||||
_id: 10,
|
||||
_type: 'server',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
id: 'some_database',
|
||||
data: {
|
||||
_type: 'database',
|
||||
_id: 11,
|
||||
label: 'some_database',
|
||||
_label: 'some_database_label',
|
||||
},
|
||||
}, {
|
||||
id: 'database_with_equal_in_name',
|
||||
data: {
|
||||
_type: 'database',
|
||||
label: 'some_database',
|
||||
_label: '=some_database_label',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'ppasServer',
|
||||
data: {
|
||||
_type: 'server',
|
||||
server_type: 'ppas',
|
||||
children: [
|
||||
{id: 'someNodeUnderneathPPASServer'},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
pgBrowser.treeMenu = TreeFake.build(hierarchy);
|
||||
});
|
||||
|
||||
describe('#draw', () => {
|
||||
beforeEach(() => {
|
||||
alertifySpy = jasmine.createSpyObj('alertify', ['alert', 'dialog']);
|
||||
alertifySpy['backup_objects'] = jasmine.createSpy('backup_objects');
|
||||
backupDialog = new BackupDialog(
|
||||
pgBrowser,
|
||||
jquerySpy,
|
||||
alertifySpy,
|
||||
backupModelSpy
|
||||
);
|
||||
|
||||
pgBrowser.get_preference = jasmine.createSpy('get_preferences');
|
||||
});
|
||||
|
||||
context('there are no ancestors of the type server', () => {
|
||||
it('does not create a dialog', () => {
|
||||
pgBrowser.treeMenu.selectNode([{id: 'root'}]);
|
||||
backupDialog.draw(null, null, null);
|
||||
expect(alertifySpy['backup_objects']).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('display an alert with a Backup Error', () => {
|
||||
backupDialog.draw(null, [{id: 'root'}], null);
|
||||
expect(alertifySpy.alert).toHaveBeenCalledWith(
|
||||
'Backup Error',
|
||||
'Please select server or child node from the browser tree.'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
context('there is an ancestor of the type server', () => {
|
||||
context('no preference can be found', () => {
|
||||
beforeEach(() => {
|
||||
pgBrowser.get_preference.and.returnValue(undefined);
|
||||
});
|
||||
|
||||
context('server is a ppas server', () => {
|
||||
it('display an alert with "Backup Error"', () => {
|
||||
backupDialog.draw(null, [{id: 'some_database'}], null);
|
||||
expect(alertifySpy.alert).toHaveBeenCalledWith(
|
||||
'Backup Error',
|
||||
'Failed to load preference pg_bin_dir of module paths'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
context('server is not a ppas server', () => {
|
||||
it('display an alert with "Backup Error"', () => {
|
||||
backupDialog.draw(null, [{id: 'ppasServer'}], null);
|
||||
expect(alertifySpy.alert).toHaveBeenCalledWith(
|
||||
'Backup Error',
|
||||
'Failed to load preference ppas_bin_dir of module paths'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
context('preference can be found', () => {
|
||||
context('binary folder is not configured', () => {
|
||||
beforeEach(() => {
|
||||
pgBrowser.get_preference.and.returnValue({});
|
||||
});
|
||||
|
||||
context('server is a ppas server', () => {
|
||||
it('display an alert with "Configuration required"', () => {
|
||||
backupDialog.draw(null, [{id: 'serverTreeNode'}], null);
|
||||
expect(alertifySpy.alert).toHaveBeenCalledWith(
|
||||
'Configuration required',
|
||||
'Please configure the PostgreSQL Binary Path in the Preferences dialog.'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
context('server is not a ppas server', () => {
|
||||
it('display an alert with "Configuration required"', () => {
|
||||
backupDialog.draw(null, [{id: 'ppasServer'}], null);
|
||||
expect(alertifySpy.alert).toHaveBeenCalledWith(
|
||||
'Configuration required',
|
||||
'Please configure the EDB Advanced Server Binary Path in the Preferences dialog.'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
context('binary folder is configured', () => {
|
||||
let backupDialogResizeToSpy;
|
||||
beforeEach(() => {
|
||||
backupDialogResizeToSpy = jasmine.createSpyObj('backupDialogResizeToSpy', ['resizeTo']);
|
||||
alertifySpy['backup_objects'].and
|
||||
.returnValue(backupDialogResizeToSpy);
|
||||
pgBrowser.get_preference.and.returnValue({value: '/some/path'});
|
||||
});
|
||||
|
||||
it('displays the dialog', () => {
|
||||
backupDialog.draw(null, [{id: 'serverTreeNode'}], null);
|
||||
expect(alertifySpy['backup_objects']).toHaveBeenCalledWith(true);
|
||||
expect(backupDialogResizeToSpy.resizeTo).toHaveBeenCalledWith('60%', '50%');
|
||||
});
|
||||
|
||||
context('database label contain "="', () => {
|
||||
it('should create alert dialog with backup error', () => {
|
||||
backupDialog.draw(null, [{id: 'database_with_equal_in_name'}], null);
|
||||
expect(alertifySpy.alert).toHaveBeenCalledWith('Backup Error',
|
||||
'Databases with = symbols in the name cannot be backed up or restored using this utility.');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
675
web/regression/javascript/backup/backup_dialog_wrapper_spec.js
Normal file
675
web/regression/javascript/backup/backup_dialog_wrapper_spec.js
Normal file
@@ -0,0 +1,675 @@
|
||||
import {TreeFake} from '../tree/tree_fake';
|
||||
import {BackupDialogWrapper} from '../../../pgadmin/tools/backup/static/js/backup_dialog_wrapper';
|
||||
import axios from 'axios/index';
|
||||
import MockAdapter from 'axios-mock-adapter';
|
||||
import {FakeModel} from '../fake_model';
|
||||
import {TreeNode} from '../../../pgadmin/static/js/tree/tree';
|
||||
|
||||
let context = describe;
|
||||
|
||||
describe('BackupDialogWrapper', () => {
|
||||
let jquerySpy;
|
||||
let pgBrowser;
|
||||
let alertifySpy;
|
||||
let dialogModelKlassSpy;
|
||||
let backform;
|
||||
let generatedBackupModel;
|
||||
let backupDialogWrapper;
|
||||
let noDataNode;
|
||||
let serverTreeNode;
|
||||
let databaseTreeNode;
|
||||
let viewSchema;
|
||||
let backupJQueryContainerSpy;
|
||||
let backupNodeChildNodeSpy;
|
||||
let backupNode;
|
||||
|
||||
beforeEach(() => {
|
||||
pgBrowser = {
|
||||
treeMenu: new TreeFake(),
|
||||
Nodes: {
|
||||
server: {
|
||||
hasId: true,
|
||||
getTreeNodeHierarchy: jasmine.createSpy('getTreeNodeHierarchy'),
|
||||
},
|
||||
database: {
|
||||
hasId: true,
|
||||
},
|
||||
},
|
||||
keyboardNavigation: jasmine.createSpyObj('keyboardNavigation', ['getDialogTabNavigator']),
|
||||
};
|
||||
noDataNode = pgBrowser.treeMenu.addNewNode('level1.1', undefined, [{id: 'level1'}]);
|
||||
serverTreeNode = pgBrowser.treeMenu.addNewNode('level2.1', {
|
||||
_type: 'server',
|
||||
_id: 10,
|
||||
label: 'some-tree-label',
|
||||
}, [{id: 'level2.1'}]);
|
||||
databaseTreeNode = new TreeNode('database-tree-node', {
|
||||
_type: 'database',
|
||||
_label: 'some-database-label',
|
||||
}, [{id: 'database-tree-node'}]);
|
||||
pgBrowser.treeMenu.addChild(serverTreeNode, databaseTreeNode);
|
||||
|
||||
jquerySpy = jasmine.createSpy('jquerySpy');
|
||||
backupNode = {
|
||||
__internal: {
|
||||
buttons: [{}, {}, {
|
||||
element: {
|
||||
disabled: false,
|
||||
},
|
||||
}],
|
||||
},
|
||||
elements: {
|
||||
body: {
|
||||
childNodes: [
|
||||
{},
|
||||
],
|
||||
},
|
||||
content: jasmine.createSpyObj('content', ['appendChild', 'attr']),
|
||||
},
|
||||
};
|
||||
|
||||
backupJQueryContainerSpy = jasmine.createSpyObj('backupJQueryContainer', ['get', 'attr']);
|
||||
backupJQueryContainerSpy.get.and.returnValue(backupJQueryContainerSpy);
|
||||
|
||||
generatedBackupModel = {};
|
||||
dialogModelKlassSpy = jasmine.createSpy('dialogModelKlass');
|
||||
dialogModelKlassSpy.and.returnValue(generatedBackupModel);
|
||||
|
||||
viewSchema = {};
|
||||
backform = jasmine.createSpyObj('backform', ['generateViewSchema', 'Dialog']);
|
||||
backform.generateViewSchema.and.returnValue(viewSchema);
|
||||
|
||||
backupNodeChildNodeSpy = jasmine.createSpyObj('something', ['addClass']);
|
||||
jquerySpy.and.callFake((selector) => {
|
||||
if (selector === '<div class=\'backup_dialog\'></div>') {
|
||||
return backupJQueryContainerSpy;
|
||||
} else if (selector === backupNode.elements.body.childNodes[0]) {
|
||||
return backupNodeChildNodeSpy;
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('#prepare', () => {
|
||||
beforeEach(() => {
|
||||
alertifySpy = jasmine.createSpyObj('alertify', ['alert', 'dialog']);
|
||||
backupDialogWrapper = new BackupDialogWrapper(
|
||||
'<div class=\'backup_dialog\'></div>',
|
||||
'backupDialogTitle',
|
||||
'backup',
|
||||
jquerySpy,
|
||||
pgBrowser,
|
||||
alertifySpy,
|
||||
dialogModelKlassSpy,
|
||||
backform
|
||||
);
|
||||
backupDialogWrapper = Object.assign(backupDialogWrapper, backupNode);
|
||||
});
|
||||
|
||||
context('no tree element is selected', () => {
|
||||
it('does not create a backform dialog', () => {
|
||||
backupDialogWrapper.prepare();
|
||||
expect(backform.Dialog).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('disables the button "submit button" until a filename is selected', () => {
|
||||
backupDialogWrapper.prepare();
|
||||
expect(backupDialogWrapper.__internal.buttons[2].element.disabled).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
context('selected tree node has no data', () => {
|
||||
beforeEach(() => {
|
||||
pgBrowser.treeMenu.selectNode(noDataNode.domNode);
|
||||
});
|
||||
|
||||
it('does not create a backform dialog', () => {
|
||||
backupDialogWrapper.prepare();
|
||||
expect(backform.Dialog).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('disables the button "submit button" until a filename is selected', () => {
|
||||
backupDialogWrapper.prepare();
|
||||
expect(backupDialogWrapper.__internal.buttons[2].element.disabled).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
context('tree element is selected', () => {
|
||||
let treeHierarchyInformation;
|
||||
let dialogSpy;
|
||||
|
||||
beforeEach(() => {
|
||||
treeHierarchyInformation = {
|
||||
server: {
|
||||
_type: 'server',
|
||||
_id: 10,
|
||||
priority: 0,
|
||||
label: 'some-tree-label',
|
||||
},
|
||||
};
|
||||
pgBrowser.treeMenu.selectNode(serverTreeNode.domNode);
|
||||
pgBrowser.Nodes['server'].getTreeNodeHierarchy.and
|
||||
.returnValue(treeHierarchyInformation);
|
||||
dialogSpy = jasmine.createSpyObj('newView', ['render']);
|
||||
dialogSpy.$el = jasmine.createSpyObj('$el', ['find', 'attr']);
|
||||
dialogSpy.model = jasmine.createSpyObj('model', ['on']);
|
||||
dialogSpy.$el.find.and.returnValue([]);
|
||||
|
||||
backform.Dialog.and.returnValue(dialogSpy);
|
||||
});
|
||||
|
||||
it('creates a backform dialog and displays it', () => {
|
||||
backupDialogWrapper.prepare();
|
||||
expect(backform.Dialog).toHaveBeenCalledWith({
|
||||
el: backupJQueryContainerSpy,
|
||||
model: generatedBackupModel,
|
||||
schema: viewSchema,
|
||||
});
|
||||
|
||||
expect(dialogSpy.render).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
||||
it('add alertify classes to restore node childnode', () => {
|
||||
backupDialogWrapper.prepare();
|
||||
expect(backupNodeChildNodeSpy.addClass)
|
||||
.toHaveBeenCalledWith('alertify_tools_dialog_properties obj_properties');
|
||||
});
|
||||
|
||||
it('disables the button submit button until a filename is selected', () => {
|
||||
backupDialogWrapper.prepare();
|
||||
expect(backupNode.__internal.buttons[2].element.disabled).toBe(true);
|
||||
});
|
||||
|
||||
it('generates a new backup model', () => {
|
||||
backupDialogWrapper.prepare();
|
||||
expect(dialogModelKlassSpy).toHaveBeenCalledWith(
|
||||
{type: 'backup'},
|
||||
{node_info: treeHierarchyInformation}
|
||||
);
|
||||
});
|
||||
|
||||
it('add the new dialog to the backup node HTML', () => {
|
||||
backupDialogWrapper.prepare();
|
||||
expect(backupNode.elements.content.appendChild).toHaveBeenCalledWith(backupJQueryContainerSpy);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('onButtonClicked', () => {
|
||||
let networkMock;
|
||||
beforeEach(() => {
|
||||
networkMock = new MockAdapter(axios);
|
||||
backupDialogWrapper = new BackupDialogWrapper(
|
||||
'<div class=\'backup_dialog\'></div>',
|
||||
'backupDialogTitle',
|
||||
'backup',
|
||||
jquerySpy,
|
||||
pgBrowser,
|
||||
alertifySpy,
|
||||
dialogModelKlassSpy,
|
||||
backform
|
||||
);
|
||||
|
||||
backupDialogWrapper = Object.assign(backupDialogWrapper, backupNode);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
networkMock.restore();
|
||||
});
|
||||
|
||||
context('dialog help button was pressed', () => {
|
||||
let networkCalled;
|
||||
beforeEach(() => {
|
||||
networkCalled = false;
|
||||
networkMock.onAny(/.*/).reply(() => {
|
||||
networkCalled = true;
|
||||
return [200, {}];
|
||||
});
|
||||
pgBrowser.treeMenu.selectNode(serverTreeNode.domNode);
|
||||
pgBrowser.showHelp = jasmine.createSpy('showHelp');
|
||||
|
||||
const event = {
|
||||
button: {
|
||||
element: {
|
||||
name: 'dialog_help',
|
||||
getAttribute: (attributeName) => {
|
||||
if (attributeName === 'url') {
|
||||
return 'http://someurl';
|
||||
} else if (attributeName === 'label') {
|
||||
return 'some label';
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
backupDialogWrapper.callback(event);
|
||||
});
|
||||
|
||||
it('displays help for dialog', () => {
|
||||
expect(pgBrowser.showHelp).toHaveBeenCalledWith(
|
||||
'dialog_help',
|
||||
'http://someurl',
|
||||
pgBrowser.Nodes['server'],
|
||||
serverTreeNode,
|
||||
'some label'
|
||||
);
|
||||
});
|
||||
|
||||
it('does not start the backup', () => {
|
||||
expect(networkCalled).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
context('object help button was pressed', () => {
|
||||
let networkCalled;
|
||||
beforeEach(() => {
|
||||
networkCalled = false;
|
||||
networkMock.onAny(/.*/).reply(() => {
|
||||
networkCalled = true;
|
||||
return [200, {}];
|
||||
});
|
||||
pgBrowser.treeMenu.selectNode(serverTreeNode.domNode);
|
||||
pgBrowser.showHelp = jasmine.createSpy('showHelp');
|
||||
|
||||
const event = {
|
||||
button: {
|
||||
element: {
|
||||
name: 'object_help',
|
||||
getAttribute: (attributeName) => {
|
||||
if (attributeName === 'url') {
|
||||
return 'http://someurl';
|
||||
} else if (attributeName === 'label') {
|
||||
return 'some label';
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
backupDialogWrapper.callback(event);
|
||||
});
|
||||
|
||||
it('displays help for dialog', () => {
|
||||
expect(pgBrowser.showHelp).toHaveBeenCalledWith(
|
||||
'object_help',
|
||||
'http://someurl',
|
||||
pgBrowser.Nodes['server'],
|
||||
serverTreeNode,
|
||||
'some label'
|
||||
);
|
||||
});
|
||||
|
||||
it('does not start the backup', () => {
|
||||
expect(networkCalled).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
context('backup button was pressed', () => {
|
||||
context('no tree node is selected', () => {
|
||||
it('does not start the backup', () => {
|
||||
let networkCalled = false;
|
||||
networkMock.onAny(/.*/).reply(() => {
|
||||
networkCalled = true;
|
||||
return [200, {}];
|
||||
});
|
||||
|
||||
let event = {
|
||||
button: {
|
||||
'data-btn-name': 'backup',
|
||||
element: {
|
||||
getAttribute: () => {
|
||||
return 'http://someurl';
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
backupDialogWrapper.callback(event);
|
||||
expect(networkCalled).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
context('tree node has no data', () => {
|
||||
it('does not start the backup', () => {
|
||||
pgBrowser.treeMenu.selectNode(noDataNode.domNode);
|
||||
|
||||
let networkCalled = false;
|
||||
networkMock.onAny(/.*/).reply(() => {
|
||||
networkCalled = true;
|
||||
return [200, {}];
|
||||
});
|
||||
|
||||
let event = {
|
||||
button: {
|
||||
'data-btn-name': 'backup',
|
||||
element: {
|
||||
getAttribute: () => {
|
||||
return 'http://someurl';
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
backupDialogWrapper.callback(event);
|
||||
expect(networkCalled).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
context('tree node has data', () => {
|
||||
context('when dialog type is global', () => {
|
||||
let event;
|
||||
beforeEach(() => {
|
||||
pgBrowser.treeMenu.selectNode(serverTreeNode.domNode);
|
||||
|
||||
backupDialogWrapper.view = {
|
||||
model: new FakeModel(),
|
||||
};
|
||||
|
||||
event = {
|
||||
button: {
|
||||
'data-btn-name': 'backup',
|
||||
element: {
|
||||
getAttribute: () => {
|
||||
return 'http://someurl';
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
context('when the backup job is created successfully', () => {
|
||||
let dataSentToServer;
|
||||
beforeEach(() => {
|
||||
pgBrowser.Events = jasmine.createSpyObj('Events', ['trigger']);
|
||||
alertifySpy.success = jasmine.createSpy('success');
|
||||
|
||||
networkMock.onPost('/backup/job/10').reply((request) => {
|
||||
dataSentToServer = request.data;
|
||||
return [200, {}];
|
||||
});
|
||||
});
|
||||
|
||||
it('creates a success alert box', (done) => {
|
||||
backupDialogWrapper.callback(event);
|
||||
setTimeout(() => {
|
||||
expect(alertifySpy.success).toHaveBeenCalledWith(
|
||||
'Backup job created.',
|
||||
5
|
||||
);
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
|
||||
it('trigger an event to background process', (done) => {
|
||||
backupDialogWrapper.callback(event);
|
||||
|
||||
setTimeout(() => {
|
||||
expect(pgBrowser.Events.trigger).toHaveBeenCalledWith(
|
||||
'pgadmin-bgprocess:created',
|
||||
backupDialogWrapper
|
||||
);
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
|
||||
it('send the correct paramenters to the backend', (done) => {
|
||||
backupDialogWrapper.callback(event);
|
||||
setTimeout(() => {
|
||||
expect(JSON.parse(dataSentToServer)).toEqual(
|
||||
{}
|
||||
);
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
});
|
||||
|
||||
context('when creating backup job fails', () => {
|
||||
it('creates an alert box', (done) => {
|
||||
alertifySpy.alert = jasmine.createSpy('alert');
|
||||
networkMock.onPost('/backup/job/10').reply(() => {
|
||||
return [400, {
|
||||
errormsg: 'some-error-message',
|
||||
}];
|
||||
});
|
||||
|
||||
backupDialogWrapper.callback(event);
|
||||
setTimeout(() => {
|
||||
expect(alertifySpy.alert).toHaveBeenCalledWith(
|
||||
'Backup job failed.',
|
||||
'some-error-message'
|
||||
);
|
||||
done();
|
||||
}, 0);
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
context('when dialog type is object', () => {
|
||||
let event;
|
||||
beforeEach(() => {
|
||||
backupDialogWrapper = new BackupDialogWrapper(
|
||||
'<div class=\'backup_dialog\'></div>',
|
||||
'backupDialogTitle',
|
||||
'backup_objects',
|
||||
jquerySpy,
|
||||
pgBrowser,
|
||||
alertifySpy,
|
||||
dialogModelKlassSpy,
|
||||
backform
|
||||
);
|
||||
|
||||
pgBrowser.treeMenu.selectNode(databaseTreeNode.domNode);
|
||||
|
||||
backupDialogWrapper.view = {
|
||||
model: new FakeModel(),
|
||||
};
|
||||
|
||||
event = {
|
||||
button: {
|
||||
'data-btn-name': 'backup',
|
||||
element: {
|
||||
getAttribute: () => {
|
||||
return 'http://someurl';
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
context('when the backup job is created successfully', () => {
|
||||
let dataSentToServer;
|
||||
beforeEach(() => {
|
||||
pgBrowser.Events = jasmine.createSpyObj('Events', ['trigger']);
|
||||
alertifySpy.success = jasmine.createSpy('success');
|
||||
|
||||
networkMock.onPost('/backup/job/10/object').reply((request) => {
|
||||
dataSentToServer = request.data;
|
||||
return [200, {}];
|
||||
});
|
||||
});
|
||||
|
||||
it('creates a success alert box', (done) => {
|
||||
backupDialogWrapper.callback(event);
|
||||
setTimeout(() => {
|
||||
expect(alertifySpy.success).toHaveBeenCalledWith(
|
||||
'Backup job created.',
|
||||
5
|
||||
);
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
|
||||
it('trigger an event to background process', (done) => {
|
||||
backupDialogWrapper.callback(event);
|
||||
|
||||
setTimeout(() => {
|
||||
expect(pgBrowser.Events.trigger).toHaveBeenCalledWith(
|
||||
'pgadmin-bgprocess:created',
|
||||
backupDialogWrapper
|
||||
);
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
|
||||
it('send the correct parameters to the backend', (done) => {
|
||||
backupDialogWrapper.callback(event);
|
||||
setTimeout(() => {
|
||||
expect(JSON.parse(dataSentToServer)).toEqual(
|
||||
{database: 'some-database-label'}
|
||||
);
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
});
|
||||
|
||||
context('when creating backup job fails', () => {
|
||||
it('creates an alert box', (done) => {
|
||||
alertifySpy.alert = jasmine.createSpy('alert');
|
||||
networkMock.onPost('/backup/job/10/object').reply(() => {
|
||||
return [400, {
|
||||
errormsg: 'some-error-message',
|
||||
}];
|
||||
});
|
||||
|
||||
backupDialogWrapper.callback(event);
|
||||
setTimeout(() => {
|
||||
expect(alertifySpy.alert).toHaveBeenCalledWith(
|
||||
'Backup job failed.',
|
||||
'some-error-message'
|
||||
);
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#setExtraParameters', () => {
|
||||
let selectedTreeNode;
|
||||
let treeInfo;
|
||||
let model;
|
||||
|
||||
context('when dialog type is global', () => {
|
||||
beforeEach(() => {
|
||||
backupDialogWrapper = new BackupDialogWrapper(
|
||||
'<div class=\'backup_dialog\'></div>',
|
||||
'backupDialogTitle',
|
||||
'backup',
|
||||
jquerySpy,
|
||||
pgBrowser,
|
||||
alertifySpy,
|
||||
dialogModelKlassSpy,
|
||||
backform
|
||||
);
|
||||
|
||||
treeInfo = {};
|
||||
model = new FakeModel();
|
||||
backupDialogWrapper.view = {
|
||||
model: model,
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
it('sets nothing on the view model', () => {
|
||||
backupDialogWrapper.setExtraParameters(selectedTreeNode, treeInfo);
|
||||
expect(model.toJSON()).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
context('when dialog type is object', () => {
|
||||
beforeEach(() => {
|
||||
backupDialogWrapper = new BackupDialogWrapper(
|
||||
'<div class=\'backup_dialog\'></div>',
|
||||
'backupDialogTitle',
|
||||
'backup_objects',
|
||||
jquerySpy,
|
||||
pgBrowser,
|
||||
alertifySpy,
|
||||
dialogModelKlassSpy,
|
||||
backform
|
||||
);
|
||||
|
||||
treeInfo = {
|
||||
database: {
|
||||
_label: 'some-database-label',
|
||||
},
|
||||
schema: {
|
||||
_label: 'some-treeinfo-label',
|
||||
},
|
||||
};
|
||||
|
||||
model = new FakeModel();
|
||||
selectedTreeNode = new TreeNode('some-selected-node',
|
||||
{_type: 'some-type', _label: 'some-selected-label'},
|
||||
[]);
|
||||
backupDialogWrapper.view = {
|
||||
model: model,
|
||||
};
|
||||
});
|
||||
|
||||
it('sets the database label on the model', () => {
|
||||
backupDialogWrapper.setExtraParameters(selectedTreeNode, treeInfo);
|
||||
expect(model.toJSON()).toEqual({
|
||||
'database': 'some-database-label',
|
||||
});
|
||||
});
|
||||
|
||||
context('when the selected is a schema type', () => {
|
||||
beforeEach(() => {
|
||||
selectedTreeNode = new TreeNode('some-selected-node',
|
||||
{_type: 'schema', _label: 'some-schema-label'},
|
||||
[]);
|
||||
});
|
||||
|
||||
it('sets the schema label on the model', () => {
|
||||
backupDialogWrapper.setExtraParameters(selectedTreeNode, treeInfo);
|
||||
expect(model.toJSON()).toEqual({
|
||||
'database': 'some-database-label',
|
||||
'schemas': ['some-schema-label'],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
context('when the selected is a table type', () => {
|
||||
beforeEach(() => {
|
||||
selectedTreeNode = new TreeNode('some-selected-node',
|
||||
{_type: 'table', _label: 'some-table-label'},
|
||||
[]);
|
||||
});
|
||||
|
||||
it('sets the schema label on the model', () => {
|
||||
backupDialogWrapper.setExtraParameters(selectedTreeNode, treeInfo);
|
||||
expect(model.toJSON()).toEqual({
|
||||
'database': 'some-database-label',
|
||||
'tables': [['some-treeinfo-label', 'some-table-label']],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
context('when the model has no ratio value', () => {
|
||||
beforeEach(() => {
|
||||
model.set('ratio', '');
|
||||
});
|
||||
|
||||
it('sets clears the ratio value', () => {
|
||||
backupDialogWrapper.setExtraParameters(selectedTreeNode, treeInfo);
|
||||
expect(model.get('ratio')).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
context('when the model has a valid ratio value', () => {
|
||||
beforeEach(() => {
|
||||
model.set('ratio', '0.25');
|
||||
});
|
||||
|
||||
it('sets clears the ratio value', () => {
|
||||
backupDialogWrapper.setExtraParameters(selectedTreeNode, treeInfo);
|
||||
expect(model.get('ratio')).toEqual('0.25');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,168 @@
|
||||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2018, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
import {BackupDialog} from '../../../pgadmin/tools/backup/static/js/backup_dialog';
|
||||
import {TreeFake} from '../tree/tree_fake';
|
||||
|
||||
const context = describe;
|
||||
|
||||
describe('GlobalServerBackupDialog', () => {
|
||||
let backupDialog;
|
||||
let pgBrowser;
|
||||
let jquerySpy;
|
||||
let alertifySpy;
|
||||
let backupModelSpy;
|
||||
|
||||
|
||||
let rootNode;
|
||||
let serverTreeNode;
|
||||
let ppasServerTreeNode;
|
||||
|
||||
beforeEach(() => {
|
||||
pgBrowser = {
|
||||
treeMenu: new TreeFake(),
|
||||
Nodes: {
|
||||
server: jasmine.createSpyObj('Node[server]', ['getTreeNodeHierarchy']),
|
||||
},
|
||||
};
|
||||
pgBrowser.Nodes.server.hasId = true;
|
||||
jquerySpy = jasmine.createSpy('jquerySpy');
|
||||
backupModelSpy = jasmine.createSpy('backupModelSpy');
|
||||
|
||||
rootNode = pgBrowser.treeMenu.addNewNode('level1', {}, undefined, []);
|
||||
serverTreeNode = pgBrowser.treeMenu.addNewNode('level1.1', {
|
||||
_type: 'server',
|
||||
_id: 10,
|
||||
}, undefined, ['level1']);
|
||||
ppasServerTreeNode = pgBrowser.treeMenu.addNewNode('level1.2', {
|
||||
_type: 'server',
|
||||
server_type: 'ppas',
|
||||
}, undefined, ['level1']);
|
||||
pgBrowser.treeMenu.addNewNode('level3', {}, undefined, ['level1', 'level1.2']);
|
||||
pgBrowser.treeMenu.addNewNode('level3.1', undefined, undefined, ['level1', 'level1.2', 'level3']);
|
||||
});
|
||||
|
||||
describe('#draw', () => {
|
||||
beforeEach(() => {
|
||||
alertifySpy = jasmine.createSpyObj('alertify', ['alert', 'dialog']);
|
||||
alertifySpy['BackupDialog_globals'] = jasmine.createSpy('BackupDialog_globals');
|
||||
alertifySpy['BackupDialog_server'] = jasmine.createSpy('BackupDialog_server');
|
||||
backupDialog = new BackupDialog(
|
||||
pgBrowser,
|
||||
jquerySpy,
|
||||
alertifySpy,
|
||||
backupModelSpy
|
||||
);
|
||||
|
||||
pgBrowser.get_preference = jasmine.createSpy('get_preferences');
|
||||
});
|
||||
|
||||
context('there are no ancestors of the type server', () => {
|
||||
it('does not create a dialog', () => {
|
||||
pgBrowser.treeMenu.selectNode([{id: 'level1'}]);
|
||||
backupDialog.draw(null, null, null);
|
||||
expect(alertifySpy['BackupDialog_globals']).not.toHaveBeenCalled();
|
||||
expect(alertifySpy['BackupDialog_server']).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('display an alert with a Backup Error', () => {
|
||||
backupDialog.draw(null, [rootNode], null);
|
||||
expect(alertifySpy.alert).toHaveBeenCalledWith(
|
||||
'Backup Error',
|
||||
'Please select server or child node from the browser tree.'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
context('there is an ancestor of the type server', () => {
|
||||
context('no preference can be found', () => {
|
||||
beforeEach(() => {
|
||||
pgBrowser.get_preference.and.returnValue(undefined);
|
||||
});
|
||||
|
||||
context('server is a ppas server', () => {
|
||||
it('display an alert with "Backup Error"', () => {
|
||||
backupDialog.draw(null, [serverTreeNode], null);
|
||||
expect(alertifySpy.alert).toHaveBeenCalledWith(
|
||||
'Backup Error',
|
||||
'Failed to load preference pg_bin_dir of module paths'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
context('server is not a ppas server', () => {
|
||||
it('display an alert with "Backup Error"', () => {
|
||||
backupDialog.draw(null, [ppasServerTreeNode], null);
|
||||
expect(alertifySpy.alert).toHaveBeenCalledWith(
|
||||
'Backup Error',
|
||||
'Failed to load preference ppas_bin_dir of module paths'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
context('preference can be found', () => {
|
||||
context('binary folder is not configured', () => {
|
||||
beforeEach(() => {
|
||||
pgBrowser.get_preference.and.returnValue({});
|
||||
});
|
||||
|
||||
context('server is a ppas server', () => {
|
||||
it('display an alert with "Configuration required"', () => {
|
||||
backupDialog.draw(null, [serverTreeNode], null);
|
||||
expect(alertifySpy.alert).toHaveBeenCalledWith(
|
||||
'Configuration required',
|
||||
'Please configure the PostgreSQL Binary Path in the Preferences dialog.'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
context('server is not a ppas server', () => {
|
||||
it('display an alert with "Configuration required"', () => {
|
||||
backupDialog.draw(null, [ppasServerTreeNode], null);
|
||||
expect(alertifySpy.alert).toHaveBeenCalledWith(
|
||||
'Configuration required',
|
||||
'Please configure the EDB Advanced Server Binary Path in the Preferences dialog.'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
context('binary folder is configured', () => {
|
||||
let globalResizeToSpy;
|
||||
let serverResizeToSpy;
|
||||
beforeEach(() => {
|
||||
globalResizeToSpy = jasmine.createSpyObj('globals', ['resizeTo']);
|
||||
alertifySpy['BackupDialog_globals'].and
|
||||
.returnValue(globalResizeToSpy);
|
||||
serverResizeToSpy = jasmine.createSpyObj('server', ['resizeTo']);
|
||||
alertifySpy['BackupDialog_server'].and
|
||||
.returnValue(serverResizeToSpy);
|
||||
pgBrowser.get_preference.and.returnValue({value: '/some/path'});
|
||||
});
|
||||
|
||||
context('dialog for global backup', () => {
|
||||
it('displays the dialog', () => {
|
||||
backupDialog.draw(null, [serverTreeNode], {globals: true});
|
||||
expect(alertifySpy['BackupDialog_globals']).toHaveBeenCalledWith(true);
|
||||
expect(globalResizeToSpy.resizeTo).toHaveBeenCalledWith('60%', '50%');
|
||||
});
|
||||
});
|
||||
|
||||
context('dialog for server backup', () => {
|
||||
it('displays the dialog', () => {
|
||||
backupDialog.draw(null, [serverTreeNode], {server: true});
|
||||
expect(alertifySpy['BackupDialog_server']).toHaveBeenCalledWith(true);
|
||||
expect(serverResizeToSpy.resizeTo).toHaveBeenCalledWith('60%', '50%');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
55
web/regression/javascript/backup/menu_utils_spec.js
Normal file
55
web/regression/javascript/backup/menu_utils_spec.js
Normal file
@@ -0,0 +1,55 @@
|
||||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2018, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
import {menuEnabledServer} from '../../../pgadmin/tools/backup/static/js/menu_utils';
|
||||
|
||||
const context = describe;
|
||||
|
||||
describe('backup.menuUtils', () => {
|
||||
describe('#menuEnabledServer', () => {
|
||||
context('provided node data is undefined', () => {
|
||||
it('returns false', () => {
|
||||
expect(menuEnabledServer(undefined)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
context('provided node data is null', () => {
|
||||
it('returns false', () => {
|
||||
expect(menuEnabledServer(null)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
context('current node type is not of the type server', () => {
|
||||
it('returns false', () => {
|
||||
expect(menuEnabledServer({_type: 'schema'})).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
context('current node type is of the type server', () => {
|
||||
context('is connected', () => {
|
||||
it('returns true', () => {
|
||||
expect(menuEnabledServer({
|
||||
_type: 'server',
|
||||
connected: true,
|
||||
})).toBe(true);
|
||||
});
|
||||
});
|
||||
context('is not connected', () => {
|
||||
it('returns false', () => {
|
||||
expect(menuEnabledServer({
|
||||
_type: 'server',
|
||||
connected: false,
|
||||
})).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -11,10 +11,6 @@ import keyboardShortcuts from 'sources/keyboard_shortcuts';
|
||||
|
||||
describe('the keyboard shortcuts', () => {
|
||||
const F1_KEY = 112;
|
||||
// const EDIT_KEY = 71; // Key: G -> Grid values
|
||||
// const LEFT_ARROW_KEY = 37;
|
||||
// const RIGHT_ARROW_KEY = 39;
|
||||
// const MOVE_NEXT = 'right';
|
||||
|
||||
let debuggerElementSpy, event, debuggerUserShortcutSpy;
|
||||
debuggerUserShortcutSpy = jasmine.createSpyObj(
|
||||
|
||||
82
web/regression/javascript/datagrid/get_panel_title_spec.js
Normal file
82
web/regression/javascript/datagrid/get_panel_title_spec.js
Normal file
@@ -0,0 +1,82 @@
|
||||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2018, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
import {getPanelTitle} from '../../../pgadmin/tools/datagrid/static/js/get_panel_title';
|
||||
import {TreeFake} from '../tree/tree_fake';
|
||||
import {TreeNode} from '../../../pgadmin/static/js/tree/tree';
|
||||
|
||||
const context = describe;
|
||||
|
||||
describe('#getPanelTitle', () => {
|
||||
let pgBrowser;
|
||||
let tree;
|
||||
beforeEach(() => {
|
||||
tree = new TreeFake();
|
||||
pgBrowser = {
|
||||
treeMenu: tree,
|
||||
Nodes: {
|
||||
server: {
|
||||
hasId: true,
|
||||
_type: 'server',
|
||||
},
|
||||
database: {
|
||||
hasId: true,
|
||||
_type: 'database',
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
context('selected node does not belong to a server', () => {
|
||||
it('returns undefined', () => {
|
||||
const root = tree.addNewNode('level1', {_type: 'server_groups'});
|
||||
tree.addChild(root, new TreeNode('level1.1', {_type: 'other'}));
|
||||
tree.selectNode([{id: 'level1'}]);
|
||||
expect(getPanelTitle(pgBrowser)).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
context('selected node belong to a server', () => {
|
||||
context('selected node does not belong to a database', () => {
|
||||
it('returns the server label and the username', () => {
|
||||
tree.addNewNode('level1', {
|
||||
_type: 'server',
|
||||
db: 'other db label',
|
||||
user: {name: 'some user name'},
|
||||
label: 'server label',
|
||||
}, []);
|
||||
|
||||
tree.selectNode([{id: 'level1'}]);
|
||||
expect(getPanelTitle(pgBrowser))
|
||||
.toBe('other db label on some user name@server label');
|
||||
});
|
||||
});
|
||||
|
||||
context('selected node belongs to a database', () => {
|
||||
it('returns the database label and the username', () => {
|
||||
const root = tree.addNewNode('level1', {
|
||||
_type: 'server',
|
||||
db: 'other db label',
|
||||
user: {name: 'some user name'},
|
||||
label: 'server label',
|
||||
});
|
||||
const level1 = new TreeNode('level1.1', {
|
||||
_type: 'database',
|
||||
label: 'db label',
|
||||
});
|
||||
tree.addChild(root, level1);
|
||||
tree.addChild(level1,
|
||||
new TreeNode('level1.1.1', {_type: 'table'}));
|
||||
tree.selectNode([{id: 'level1.1.1'}]);
|
||||
expect(getPanelTitle(pgBrowser))
|
||||
.toBe('db label on some user name@server label');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
171
web/regression/javascript/datagrid/show_data_spec.js
Normal file
171
web/regression/javascript/datagrid/show_data_spec.js
Normal file
@@ -0,0 +1,171 @@
|
||||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2018, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
import {showDataGrid} from '../../../pgadmin/tools/datagrid/static/js/show_data';
|
||||
import {TreeFake} from '../tree/tree_fake';
|
||||
import {TreeNode} from '../../../pgadmin/static/js/tree/tree';
|
||||
|
||||
const context = describe;
|
||||
|
||||
describe('#show_data', () => {
|
||||
let datagrid;
|
||||
let pgBrowser;
|
||||
let alertify;
|
||||
beforeEach(() => {
|
||||
alertify = jasmine.createSpyObj('alertify', ['alert']);
|
||||
datagrid = {
|
||||
create_transaction: jasmine.createSpy('create_transaction'),
|
||||
};
|
||||
pgBrowser = {
|
||||
treeMenu: new TreeFake(),
|
||||
Nodes: {
|
||||
server_group: {
|
||||
_type: 'server_group',
|
||||
hasId: true,
|
||||
},
|
||||
server: {
|
||||
_type: 'server',
|
||||
hasId: true,
|
||||
},
|
||||
database: {
|
||||
_type: 'database',
|
||||
hasId: true,
|
||||
},
|
||||
schema: {
|
||||
_type: 'schema',
|
||||
hasId: true,
|
||||
},
|
||||
view: {
|
||||
_type: 'view',
|
||||
hasId: true,
|
||||
},
|
||||
catalog: {
|
||||
_type: 'catalog',
|
||||
hasId: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
const parent = pgBrowser.treeMenu.addNewNode('parent', {_type: 'parent'}, []);
|
||||
const serverGroup1 = new TreeNode('server_group1', {
|
||||
_type: 'server_group',
|
||||
_id: 1,
|
||||
});
|
||||
pgBrowser.treeMenu.addChild(parent, serverGroup1);
|
||||
|
||||
const server1 = new TreeNode('server1', {
|
||||
_type: 'server',
|
||||
label: 'server1',
|
||||
server_type: 'pg',
|
||||
_id: 2,
|
||||
}, ['parent', 'server_group1']);
|
||||
pgBrowser.treeMenu.addChild(serverGroup1, server1);
|
||||
|
||||
const database1 = new TreeNode('database1', {
|
||||
_type: 'database',
|
||||
label: 'database1',
|
||||
_id: 3,
|
||||
}, ['parent', 'server_group1', 'server1']);
|
||||
pgBrowser.treeMenu.addChild(server1, database1);
|
||||
|
||||
const schema1 = new TreeNode('schema1', {
|
||||
_type: 'schema',
|
||||
label: 'schema1',
|
||||
_id: 4,
|
||||
});
|
||||
pgBrowser.treeMenu.addChild(database1, schema1);
|
||||
|
||||
const view1 = new TreeNode('view1', {
|
||||
_type: 'view',
|
||||
label: 'view1',
|
||||
_id: 5,
|
||||
}, ['parent', 'server_group1', 'server1', 'database1']);
|
||||
pgBrowser.treeMenu.addChild(database1, view1);
|
||||
|
||||
const catalog1 = new TreeNode('catalog1', {
|
||||
_type: 'catalog',
|
||||
label: 'catalog1',
|
||||
_id: 6,
|
||||
}, ['parent', 'server_group1', 'server1', 'database1']);
|
||||
pgBrowser.treeMenu.addChild(database1, catalog1);
|
||||
});
|
||||
|
||||
context('cannot find the tree node', () => {
|
||||
it('does not create a transaction', () => {
|
||||
showDataGrid(datagrid, pgBrowser, alertify, {}, [{id: '10'}]);
|
||||
expect(datagrid.create_transaction).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('display alert', () => {
|
||||
showDataGrid(datagrid, pgBrowser, alertify, {}, [{id: '10'}]);
|
||||
expect(alertify.alert).toHaveBeenCalledWith(
|
||||
'Data Grid Error',
|
||||
'No object selected.'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
context('current node is not underneath a server', () => {
|
||||
it('does not create a transaction', () => {
|
||||
showDataGrid(datagrid, pgBrowser, alertify, {}, [{id: 'parent'}]);
|
||||
expect(datagrid.create_transaction).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
context('current node is not underneath a schema or view or catalog', () => {
|
||||
it('does not create a transaction', () => {
|
||||
showDataGrid(datagrid, pgBrowser, alertify, {}, [{id: 'database1'}]);
|
||||
expect(datagrid.create_transaction).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
context('current node is underneath a schema', () => {
|
||||
it('does not create a transaction', () => {
|
||||
showDataGrid(datagrid, pgBrowser, alertify, {mnuid: 11}, [{id: 'schema1'}]);
|
||||
expect(datagrid.create_transaction).toHaveBeenCalledWith(
|
||||
'/initialize/datagrid/11/schema/1/2/3/4',
|
||||
null,
|
||||
'false',
|
||||
'pg',
|
||||
'',
|
||||
'server1 - database1 - schema1.schema1',
|
||||
''
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
context('current node is underneath a view', () => {
|
||||
it('does not create a transaction', () => {
|
||||
showDataGrid(datagrid, pgBrowser, alertify, {mnuid: 11}, [{id: 'view1'}]);
|
||||
expect(datagrid.create_transaction).toHaveBeenCalledWith(
|
||||
'/initialize/datagrid/11/view/1/2/3/5',
|
||||
null,
|
||||
'false',
|
||||
'pg',
|
||||
'',
|
||||
'server1 - database1 - view1.view1',
|
||||
''
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
context('current node is underneath a catalog', () => {
|
||||
it('does not create a transaction', () => {
|
||||
showDataGrid(datagrid, pgBrowser, alertify, {mnuid: 11}, [{id: 'catalog1'}]);
|
||||
expect(datagrid.create_transaction).toHaveBeenCalledWith(
|
||||
'/initialize/datagrid/11/catalog/1/2/3/6',
|
||||
null,
|
||||
'false',
|
||||
'pg',
|
||||
'',
|
||||
'server1 - database1 - catalog1.catalog1',
|
||||
''
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
125
web/regression/javascript/datagrid/show_query_tool_spec.js
Normal file
125
web/regression/javascript/datagrid/show_query_tool_spec.js
Normal file
@@ -0,0 +1,125 @@
|
||||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2018, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
import {TreeFake} from '../tree/tree_fake';
|
||||
import {showQueryTool} from '../../../pgadmin/tools/datagrid/static/js/show_query_tool';
|
||||
import {TreeNode} from '../../../pgadmin/static/js/tree/tree';
|
||||
|
||||
const context = describe;
|
||||
|
||||
describe('#showQueryTool', () => {
|
||||
let queryTool;
|
||||
let pgBrowser;
|
||||
let alertify;
|
||||
beforeEach(() => {
|
||||
alertify = jasmine.createSpyObj('alertify', ['alert']);
|
||||
queryTool = {
|
||||
create_transaction: jasmine.createSpy('create_transaction'),
|
||||
};
|
||||
pgBrowser = {
|
||||
treeMenu: new TreeFake(),
|
||||
Nodes: {
|
||||
server_group: {
|
||||
_type: 'server_group',
|
||||
hasId: true,
|
||||
},
|
||||
server: {
|
||||
_type: 'server',
|
||||
hasId: true,
|
||||
},
|
||||
database: {
|
||||
_type: 'database',
|
||||
hasId: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
const parent = pgBrowser.treeMenu.addNewNode('parent', {_type: 'parent'});
|
||||
const serverGroup1 = new TreeNode('server_group1', {
|
||||
_type: 'server_group',
|
||||
_id: 1,
|
||||
}, ['parent']);
|
||||
pgBrowser.treeMenu.addChild(parent, serverGroup1);
|
||||
|
||||
const server1 = new TreeNode('server1', {
|
||||
_type: 'server',
|
||||
label: 'server1',
|
||||
server_type: 'pg',
|
||||
_id: 2,
|
||||
});
|
||||
pgBrowser.treeMenu.addChild(serverGroup1, server1);
|
||||
|
||||
const database1 = new TreeNode('database1', {
|
||||
_type: 'database',
|
||||
label: 'database1',
|
||||
_id: 3,
|
||||
});
|
||||
pgBrowser.treeMenu.addChild(server1, database1);
|
||||
});
|
||||
|
||||
context('cannot find the tree node', () => {
|
||||
beforeEach(() => {
|
||||
showQueryTool(queryTool, pgBrowser, alertify, '', [{id: '10'}], 'title');
|
||||
});
|
||||
it('does not create a transaction', () => {
|
||||
expect(queryTool.create_transaction).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('display alert', () => {
|
||||
expect(alertify.alert).toHaveBeenCalledWith(
|
||||
'Query Tool Error',
|
||||
'No object selected.'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
context('current node is not underneath a server', () => {
|
||||
it('does not create a transaction', () => {
|
||||
showQueryTool(queryTool, pgBrowser, alertify, '', [{id: 'parent'}], 'title');
|
||||
expect(queryTool.create_transaction).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('no alert is displayed', () => {
|
||||
expect(alertify.alert).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
context('current node is underneath a server', () => {
|
||||
context('current node is not underneath a database', () => {
|
||||
it('creates a transaction', () => {
|
||||
showQueryTool(queryTool, pgBrowser, alertify, 'http://someurl', [{id: 'server1'}], 'title');
|
||||
expect(queryTool.create_transaction).toHaveBeenCalledWith(
|
||||
'/initialize/query_tool/1/2',
|
||||
null,
|
||||
'true',
|
||||
'pg',
|
||||
'http://someurl',
|
||||
'title',
|
||||
'',
|
||||
false
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
context('current node is underneath a database', () => {
|
||||
it('creates a transaction', () => {
|
||||
showQueryTool(queryTool, pgBrowser, alertify, 'http://someurl', [{id: 'database1'}], 'title');
|
||||
expect(queryTool.create_transaction).toHaveBeenCalledWith(
|
||||
'/initialize/query_tool/1/2/3',
|
||||
null,
|
||||
'true',
|
||||
'pg',
|
||||
'http://someurl',
|
||||
'title',
|
||||
'',
|
||||
false
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
12
web/regression/javascript/fake_browser/browser.js
Normal file
12
web/regression/javascript/fake_browser/browser.js
Normal file
@@ -0,0 +1,12 @@
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2018, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
let treeMenu = null;
|
||||
|
||||
export {treeMenu};
|
||||
@@ -12,5 +12,11 @@ define(function () {
|
||||
'static': '/base/pgadmin/static/<path:filename>',
|
||||
'sqleditor.poll': '/sqleditor/query_tool/poll/<path:trans_id>',
|
||||
'sqleditor.query_tool_start': '/sqleditor/query_tool/start/<path:trans_id>',
|
||||
'backup.create_server_job': '/backup/job/<int:sid>',
|
||||
'backup.create_object_job': '/backup/job/<int:sid>/object',
|
||||
'datagrid.initialize_datagrid': '/initialize/datagrid/<int:cmd_type>/<obj_type>/<int:sgid>/<int:sid>/<int:did>/<int:obj_id>',
|
||||
'datagrid.initialize_query_tool': '/initialize/query_tool/<int:sgid>/<int:sid>',
|
||||
'datagrid.initialize_query_tool_with_did': '/initialize/query_tool/<int:sgid>/<int:sid>/<int:did>',
|
||||
'restore.create_job': '/restore/job/<int:sid>',
|
||||
};
|
||||
});
|
||||
|
||||
21
web/regression/javascript/fake_model.js
Normal file
21
web/regression/javascript/fake_model.js
Normal file
@@ -0,0 +1,21 @@
|
||||
export class FakeModel {
|
||||
constructor() {
|
||||
this.values = {};
|
||||
}
|
||||
|
||||
set(key, value) {
|
||||
this.values[key] = value;
|
||||
}
|
||||
|
||||
get(key) {
|
||||
return this.values[key];
|
||||
}
|
||||
|
||||
unset(key) {
|
||||
delete this.values[key];
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
return Object.assign({}, this.values);
|
||||
}
|
||||
}
|
||||
253
web/regression/javascript/nodes/schema/child_menu_spec.js
Normal file
253
web/regression/javascript/nodes/schema/child_menu_spec.js
Normal file
@@ -0,0 +1,253 @@
|
||||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2018, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
/////////////////////////////////////////////////////////////
|
||||
|
||||
import {
|
||||
isTreeItemOfChildOfSchema, childCreateMenuEnabled,
|
||||
} from 'pgadmin.schema.dir/schema_child_tree_node';
|
||||
|
||||
import * as pgBrowser from 'pgbrowser/browser';
|
||||
import {TreeFake} from '../../tree/tree_fake';
|
||||
|
||||
describe('#childCreateMenuEnabled', () => {
|
||||
let data;
|
||||
let tree;
|
||||
|
||||
describe(' - when data is not null', () => {
|
||||
beforeEach(() => {
|
||||
data = {};
|
||||
});
|
||||
describe(' and check is false', () => {
|
||||
beforeEach(() => {
|
||||
data = {check: false};
|
||||
});
|
||||
it(', then it returns true', () => {
|
||||
expect(childCreateMenuEnabled({}, {}, data)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe(' and check', () => {
|
||||
describe(' is true', () => {
|
||||
beforeEach(() => {
|
||||
data = {check: true};
|
||||
});
|
||||
|
||||
describe(', on schema node', () => {
|
||||
beforeEach(() => {
|
||||
let hierarchy = {
|
||||
id: 'root',
|
||||
children: [{
|
||||
id: 'level2',
|
||||
data: {_type: 'schema'},
|
||||
}],
|
||||
};
|
||||
|
||||
tree = TreeFake.build(hierarchy);
|
||||
pgBrowser.treeMenu = tree;
|
||||
});
|
||||
it(' it is true', () => {
|
||||
expect(childCreateMenuEnabled(
|
||||
{}, [{id: 'level2'}], data
|
||||
)).toBe(true);
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
describe(', on child collection node under schema node ', () => {
|
||||
beforeEach(() => {
|
||||
let hierarchy = {
|
||||
id: 'root',
|
||||
children: [{
|
||||
id: 'level2',
|
||||
data: {_type: 'schema'},
|
||||
children: [{
|
||||
id: 'coll-table',
|
||||
data: {_type: 'coll-table'},
|
||||
}],
|
||||
}],
|
||||
};
|
||||
|
||||
tree = TreeFake.build(hierarchy);
|
||||
pgBrowser.treeMenu = tree;
|
||||
});
|
||||
|
||||
it(' it is true', () => {
|
||||
expect(childCreateMenuEnabled(
|
||||
{}, [{id: 'coll-table'}], data
|
||||
)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe(', on one of the child node under schema node ', () => {
|
||||
beforeEach(() => {
|
||||
let hierarchy = {
|
||||
id: 'root',
|
||||
children: [{
|
||||
id: 'level2',
|
||||
data: {_type: 'schema'},
|
||||
children: [{
|
||||
id: 'coll-table',
|
||||
data: {_type: 'coll-table'},
|
||||
children: [{
|
||||
id: 'table/1',
|
||||
data: {_type: 'table'},
|
||||
}],
|
||||
}],
|
||||
}],
|
||||
};
|
||||
|
||||
tree = TreeFake.build(hierarchy);
|
||||
pgBrowser.treeMenu = tree;
|
||||
});
|
||||
|
||||
it(' it is true', () => {
|
||||
expect(childCreateMenuEnabled(
|
||||
{}, [{id: 'table/1'}], data
|
||||
)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe(', on catalog node', () => {
|
||||
beforeEach(() => {
|
||||
let hierarchy = {
|
||||
id: 'root',
|
||||
children: [{
|
||||
id: 'level2',
|
||||
data: {_type: 'catalog'},
|
||||
}],
|
||||
};
|
||||
|
||||
tree = TreeFake.build(hierarchy);
|
||||
pgBrowser.treeMenu = tree;
|
||||
});
|
||||
it(' it is false', () => {
|
||||
expect(
|
||||
childCreateMenuEnabled({}, [{id: 'level2'}], data)
|
||||
).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe(', on child collection node under catalog node ', () => {
|
||||
beforeEach(() => {
|
||||
let hierarchy = {
|
||||
id: 'root',
|
||||
children: [{
|
||||
id: 'level2',
|
||||
data: {_type: 'catalog'},
|
||||
children: [{
|
||||
id: 'coll-table',
|
||||
data: {_type: 'coll-table'},
|
||||
}],
|
||||
}],
|
||||
};
|
||||
|
||||
tree = TreeFake.build(hierarchy);
|
||||
pgBrowser.treeMenu = tree;
|
||||
});
|
||||
|
||||
it(' it is false', () => {
|
||||
expect(childCreateMenuEnabled(
|
||||
{}, [{id: 'coll-table'}], data
|
||||
)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe(', on one of the child node under catalog node ', () => {
|
||||
beforeEach(() => {
|
||||
let hierarchy = {
|
||||
id: 'root',
|
||||
children: [{
|
||||
id: 'level2',
|
||||
data: {_type: 'catalog'},
|
||||
children: [{
|
||||
id: 'coll-table',
|
||||
data: {_type: 'coll-table'},
|
||||
children: [{
|
||||
id: 'table/1',
|
||||
data: {_type: 'table'},
|
||||
}],
|
||||
}],
|
||||
}],
|
||||
};
|
||||
|
||||
tree = TreeFake.build(hierarchy);
|
||||
pgBrowser.treeMenu = tree;
|
||||
});
|
||||
|
||||
it(' it is false', () => {
|
||||
expect(childCreateMenuEnabled(
|
||||
{}, [{id: 'table/1'}], data
|
||||
)).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#childDropMenuEnabled', () => {
|
||||
let tree;
|
||||
|
||||
describe(' - the child node under schema node ', () => {
|
||||
beforeEach(() => {
|
||||
let hierarchy = {
|
||||
id: 'root',
|
||||
children: [{
|
||||
id: 'level2',
|
||||
data: {_type: 'schema'},
|
||||
children: [{
|
||||
id: 'coll-table',
|
||||
data: {_type: 'coll-table'},
|
||||
children: [{
|
||||
id: 'table/1',
|
||||
data: {_type: 'table'},
|
||||
}],
|
||||
}],
|
||||
}],
|
||||
};
|
||||
|
||||
tree = TreeFake.build(hierarchy);
|
||||
pgBrowser.treeMenu = tree;
|
||||
});
|
||||
|
||||
it(' it is true', () => {
|
||||
expect(isTreeItemOfChildOfSchema(
|
||||
{}, [{id: 'table/1'}]
|
||||
)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('- the child node under the catalog node ', () => {
|
||||
beforeEach(() => {
|
||||
let hierarchy = {
|
||||
id: 'root',
|
||||
children: [{
|
||||
id: 'level2',
|
||||
data: {_type: 'catalog'},
|
||||
children: [{
|
||||
id: 'coll-table',
|
||||
data: {_type: 'coll-table'},
|
||||
children: [{
|
||||
id: 'table/1',
|
||||
data: {_type: 'table'},
|
||||
}],
|
||||
}],
|
||||
}],
|
||||
};
|
||||
|
||||
tree = TreeFake.build(hierarchy);
|
||||
pgBrowser.treeMenu = tree;
|
||||
});
|
||||
|
||||
it(' it is false', () => {
|
||||
expect(isTreeItemOfChildOfSchema(
|
||||
{}, [{id: 'table/1'}]
|
||||
)).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
203
web/regression/javascript/restore/restore_dialog_spec.js
Normal file
203
web/regression/javascript/restore/restore_dialog_spec.js
Normal file
@@ -0,0 +1,203 @@
|
||||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2018, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
import {TreeFake} from '../tree/tree_fake';
|
||||
import {RestoreDialog} from '../../../pgadmin/tools/restore/static/js/restore_dialog';
|
||||
|
||||
const context = describe;
|
||||
|
||||
describe('RestoreDialog', () => {
|
||||
let restoreDialog;
|
||||
let pgBrowser;
|
||||
let jquerySpy;
|
||||
let alertifySpy;
|
||||
let restoreModelSpy;
|
||||
|
||||
beforeEach(() => {
|
||||
pgBrowser = {
|
||||
treeMenu: new TreeFake(),
|
||||
Nodes: {
|
||||
server: jasmine.createSpyObj('Node[server]', ['getTreeNodeHierarchy']),
|
||||
database: jasmine.createSpyObj('Node[database]', ['getTreeNodeHierarchy']),
|
||||
},
|
||||
};
|
||||
pgBrowser.Nodes.server.hasId = true;
|
||||
pgBrowser.Nodes.database.hasId = true;
|
||||
jquerySpy = jasmine.createSpy('jquerySpy');
|
||||
restoreModelSpy = jasmine.createSpy('restoreModelSpy');
|
||||
|
||||
const hierarchy = {
|
||||
children: [
|
||||
{
|
||||
id: 'root',
|
||||
children: [
|
||||
{
|
||||
id: 'serverTreeNode',
|
||||
data: {
|
||||
_id: 10,
|
||||
_type: 'server',
|
||||
label: 'some-tree-label',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
id: 'some_database',
|
||||
data: {
|
||||
_type: 'database',
|
||||
_id: 11,
|
||||
label: 'some_database',
|
||||
_label: 'some_database_label',
|
||||
},
|
||||
}, {
|
||||
id: 'database_with_equal_in_name',
|
||||
data: {
|
||||
_type: 'database',
|
||||
label: 'some_database',
|
||||
_label: '=some_database_label',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'ppasServer',
|
||||
data: {
|
||||
_type: 'server',
|
||||
server_type: 'ppas',
|
||||
children: [
|
||||
{id: 'someNodeUnderneathPPASServer'},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
pgBrowser.treeMenu = TreeFake.build(hierarchy);
|
||||
});
|
||||
|
||||
describe('#draw', () => {
|
||||
beforeEach(() => {
|
||||
alertifySpy = jasmine.createSpyObj('alertify', ['alert', 'dialog']);
|
||||
alertifySpy['pg_restore'] = jasmine.createSpy('pg_restore');
|
||||
restoreDialog = new RestoreDialog(
|
||||
pgBrowser,
|
||||
jquerySpy,
|
||||
alertifySpy,
|
||||
restoreModelSpy
|
||||
);
|
||||
|
||||
pgBrowser.get_preference = jasmine.createSpy('get_preferences');
|
||||
});
|
||||
|
||||
context('there are no ancestors of the type server', () => {
|
||||
it('does not create a dialog', () => {
|
||||
pgBrowser.treeMenu.selectNode([{id: 'root'}]);
|
||||
restoreDialog.draw(null, null, null);
|
||||
expect(alertifySpy['pg_restore']).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('display an alert with a Restore Error', () => {
|
||||
restoreDialog.draw(null, [{id: 'root'}], null);
|
||||
expect(alertifySpy.alert).toHaveBeenCalledWith(
|
||||
'Restore Error',
|
||||
'Please select server or child node from the browser tree.'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
context('there is an ancestor of the type server', () => {
|
||||
context('no preference can be found', () => {
|
||||
beforeEach(() => {
|
||||
pgBrowser.get_preference.and.returnValue(undefined);
|
||||
});
|
||||
|
||||
context('server is a ppas server', () => {
|
||||
it('display an alert with "Restore Error"', () => {
|
||||
restoreDialog.draw(null, [{id: 'serverTreeNode'}], null);
|
||||
expect(alertifySpy.alert).toHaveBeenCalledWith(
|
||||
'Restore Error',
|
||||
'Failed to load preference pg_bin_dir of module paths'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
context('server is not a ppas server', () => {
|
||||
it('display an alert with "Restore Error"', () => {
|
||||
restoreDialog.draw(null, [{id: 'ppasServer'}], null);
|
||||
expect(alertifySpy.alert).toHaveBeenCalledWith(
|
||||
'Restore Error',
|
||||
'Failed to load preference ppas_bin_dir of module paths'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
context('preference can be found', () => {
|
||||
context('binary folder is not configured', () => {
|
||||
beforeEach(() => {
|
||||
pgBrowser.get_preference.and.returnValue({});
|
||||
});
|
||||
|
||||
context('server is a ppas server', () => {
|
||||
it('display an alert with "Configuration required"', () => {
|
||||
restoreDialog.draw(null, [{id: 'serverTreeNode'}], null);
|
||||
expect(alertifySpy.alert).toHaveBeenCalledWith(
|
||||
'Configuration required',
|
||||
'Please configure the PostgreSQL Binary Path in the Preferences dialog.'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
context('server is not a ppas server', () => {
|
||||
it('display an alert with "Configuration required"', () => {
|
||||
restoreDialog.draw(null, [{id: 'ppasServer'}], null);
|
||||
expect(alertifySpy.alert).toHaveBeenCalledWith(
|
||||
'Configuration required',
|
||||
'Please configure the EDB Advanced Server Binary Path in the Preferences dialog.'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
context('binary folder is configured', () => {
|
||||
let spy;
|
||||
beforeEach(() => {
|
||||
spy = jasmine.createSpyObj('globals', ['resizeTo']);
|
||||
alertifySpy['pg_restore'].and
|
||||
.returnValue(spy);
|
||||
pgBrowser.get_preference.and.returnValue({value: '/some/path'});
|
||||
pgBrowser.Nodes.server.label = 'some-server-label';
|
||||
});
|
||||
|
||||
it('displays the dialog', () => {
|
||||
restoreDialog.draw(null, [{id: 'serverTreeNode'}], {server: true});
|
||||
expect(alertifySpy['pg_restore']).toHaveBeenCalledWith(
|
||||
'Restore (some-server-label: some-tree-label)',
|
||||
[{id: 'serverTreeNode'}],
|
||||
{
|
||||
_id: 10,
|
||||
_type: 'server',
|
||||
label: 'some-tree-label',
|
||||
},
|
||||
pgBrowser.Nodes.server
|
||||
);
|
||||
expect(spy.resizeTo).toHaveBeenCalledWith('65%', '60%');
|
||||
});
|
||||
|
||||
context('database label contain "="', () => {
|
||||
it('should create alert dialog with restore error', () => {
|
||||
restoreDialog.draw(null, [{id: 'database_with_equal_in_name'}], null);
|
||||
expect(alertifySpy.alert).toHaveBeenCalledWith('Restore Error',
|
||||
'Databases with = symbols in the name cannot be backed up or restored using this utility.');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
593
web/regression/javascript/restore/restore_dialog_wrapper_spec.js
Normal file
593
web/regression/javascript/restore/restore_dialog_wrapper_spec.js
Normal file
@@ -0,0 +1,593 @@
|
||||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2018, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
import {TreeFake} from '../tree/tree_fake';
|
||||
import {RestoreDialogWrapper} from '../../../pgadmin/tools/restore/static/js/restore_dialog_wrapper';
|
||||
import MockAdapter from 'axios-mock-adapter';
|
||||
import axios from 'axios/index';
|
||||
import {FakeModel} from '../fake_model';
|
||||
import {TreeNode} from '../../../pgadmin/static/js/tree/tree';
|
||||
|
||||
let context = describe;
|
||||
|
||||
describe('RestoreDialogWrapper', () => {
|
||||
let jquerySpy;
|
||||
let pgBrowser;
|
||||
let alertifySpy;
|
||||
let dialogModelKlassSpy;
|
||||
let backform;
|
||||
let generatedRestoreModel;
|
||||
let restoreDialogWrapper;
|
||||
let noDataNode;
|
||||
let serverTreeNode;
|
||||
let viewSchema;
|
||||
let restoreJQueryContainerSpy;
|
||||
let restoreNodeChildNodeSpy;
|
||||
let restoreNode;
|
||||
|
||||
beforeEach(() => {
|
||||
pgBrowser = {
|
||||
treeMenu: new TreeFake(),
|
||||
Nodes: {
|
||||
server: {
|
||||
hasId: true,
|
||||
getTreeNodeHierarchy: jasmine.createSpy('getTreeNodeHierarchy'),
|
||||
},
|
||||
},
|
||||
keyboardNavigation: jasmine.createSpyObj('keyboardNavigation', ['getDialogTabNavigator']),
|
||||
};
|
||||
|
||||
noDataNode = pgBrowser.treeMenu.addNewNode('level1.1', undefined, [{id: 'level1'}]);
|
||||
serverTreeNode = pgBrowser.treeMenu.addNewNode('level2.1', {
|
||||
_type: 'server',
|
||||
_id: 10,
|
||||
label: 'some-tree-label',
|
||||
}, [{id: 'level2.1'}]);
|
||||
jquerySpy = jasmine.createSpy('jquerySpy');
|
||||
dialogModelKlassSpy = jasmine.createSpy('dialogModelKlass');
|
||||
generatedRestoreModel = {};
|
||||
viewSchema = {};
|
||||
backform = jasmine.createSpyObj('backform', ['generateViewSchema', 'Dialog']);
|
||||
backform.generateViewSchema.and.returnValue(viewSchema);
|
||||
dialogModelKlassSpy.and.returnValue(generatedRestoreModel);
|
||||
restoreJQueryContainerSpy = jasmine.createSpyObj('restoreJQueryContainer', ['get', 'attr']);
|
||||
restoreJQueryContainerSpy.get.and.returnValue(restoreJQueryContainerSpy);
|
||||
|
||||
restoreNode = {
|
||||
__internal: {
|
||||
buttons: [
|
||||
{}, {},
|
||||
{
|
||||
element: {
|
||||
disabled: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
elements: {
|
||||
body: {
|
||||
childNodes: [
|
||||
{},
|
||||
],
|
||||
},
|
||||
content: jasmine.createSpyObj('content', ['appendChild', 'attr']),
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
restoreNodeChildNodeSpy = jasmine.createSpyObj('something', ['addClass']);
|
||||
|
||||
jquerySpy.and.callFake((selector) => {
|
||||
if (selector === '<div class=\'restore_dialog\'></div>') {
|
||||
return restoreJQueryContainerSpy;
|
||||
} else if (selector === restoreNode.elements.body.childNodes[0]) {
|
||||
return restoreNodeChildNodeSpy;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('#prepare', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
alertifySpy = jasmine.createSpyObj('alertify', ['alert', 'dialog']);
|
||||
restoreDialogWrapper = new RestoreDialogWrapper(
|
||||
'<div class=\'restore_dialog\'></div>',
|
||||
'restoreDialogTitle',
|
||||
'restore',
|
||||
jquerySpy,
|
||||
pgBrowser,
|
||||
alertifySpy,
|
||||
dialogModelKlassSpy,
|
||||
backform
|
||||
);
|
||||
restoreDialogWrapper = Object.assign(restoreDialogWrapper, restoreNode);
|
||||
});
|
||||
context('no tree element is selected', () => {
|
||||
it('does not create a backform dialog', () => {
|
||||
restoreDialogWrapper.prepare();
|
||||
expect(backform.Dialog).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('disables the button "submit button" until a filename is selected', () => {
|
||||
restoreDialogWrapper.prepare();
|
||||
expect(restoreDialogWrapper.__internal.buttons[2].element.disabled).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
context('selected tree node has no data', () => {
|
||||
beforeEach(() => {
|
||||
pgBrowser.treeMenu.selectNode(noDataNode.domNode);
|
||||
});
|
||||
|
||||
it('does not create a backform dialog', () => {
|
||||
restoreDialogWrapper.prepare();
|
||||
expect(backform.Dialog).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('disables the button "submit button" until a filename is selected', () => {
|
||||
restoreDialogWrapper.prepare();
|
||||
expect(restoreDialogWrapper.__internal.buttons[2].element.disabled).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
context('tree element is selected', () => {
|
||||
let treeHierarchyInformation;
|
||||
let dialogSpy;
|
||||
beforeEach(() => {
|
||||
treeHierarchyInformation = {
|
||||
server: {
|
||||
_type: 'server',
|
||||
_id: 10,
|
||||
priority: 0,
|
||||
label: 'some-tree-label',
|
||||
},
|
||||
};
|
||||
pgBrowser.treeMenu.selectNode(serverTreeNode.domNode);
|
||||
pgBrowser.Nodes['server'].getTreeNodeHierarchy.and
|
||||
.returnValue(treeHierarchyInformation);
|
||||
dialogSpy = jasmine.createSpyObj('newView', ['render']);
|
||||
dialogSpy.$el = jasmine.createSpyObj('$el', ['find', 'attr']);
|
||||
dialogSpy.model = jasmine.createSpyObj('model', ['on']);
|
||||
dialogSpy.$el.find.and.returnValue([]);
|
||||
|
||||
backform.Dialog.and.returnValue(dialogSpy);
|
||||
});
|
||||
|
||||
it('creates a backform dialog and displays it', () => {
|
||||
restoreDialogWrapper.prepare();
|
||||
expect(backform.Dialog).toHaveBeenCalledWith({
|
||||
el: restoreJQueryContainerSpy,
|
||||
model: generatedRestoreModel,
|
||||
schema: viewSchema,
|
||||
});
|
||||
|
||||
expect(dialogSpy.render).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('add alertify classes to restore node childnode', () => {
|
||||
restoreDialogWrapper.prepare();
|
||||
expect(restoreNodeChildNodeSpy.addClass)
|
||||
.toHaveBeenCalledWith('alertify_tools_dialog_properties obj_properties');
|
||||
});
|
||||
|
||||
it('disables the button submit button until a filename is selected', () => {
|
||||
restoreDialogWrapper.prepare();
|
||||
expect(restoreNode.__internal.buttons[2].element.disabled).toBe(true);
|
||||
});
|
||||
|
||||
it('generates a new restore model', () => {
|
||||
restoreDialogWrapper.prepare();
|
||||
expect(dialogModelKlassSpy).toHaveBeenCalledWith(
|
||||
{node_data: pgBrowser.Nodes['server']},
|
||||
{node_info: treeHierarchyInformation}
|
||||
);
|
||||
});
|
||||
|
||||
it('add the new dialog to the restore node HTML', () => {
|
||||
restoreDialogWrapper.prepare();
|
||||
expect(restoreNode.elements.content.appendChild).toHaveBeenCalledWith(restoreJQueryContainerSpy);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('onButtonClicked', () => {
|
||||
let networkMock;
|
||||
|
||||
beforeEach(() => {
|
||||
pgBrowser.showHelp = jasmine.createSpy('showHelp');
|
||||
networkMock = new MockAdapter(axios);
|
||||
alertifySpy = jasmine.createSpyObj('alertify', ['success', 'alert']);
|
||||
restoreDialogWrapper = new RestoreDialogWrapper(
|
||||
'<div class=\'restore_dialog\'></div>',
|
||||
'restoreDialogTitle',
|
||||
'restore',
|
||||
jquerySpy,
|
||||
pgBrowser,
|
||||
alertifySpy,
|
||||
dialogModelKlassSpy,
|
||||
backform
|
||||
);
|
||||
restoreDialogWrapper = Object.assign(restoreDialogWrapper, restoreNode);
|
||||
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
networkMock.restore();
|
||||
});
|
||||
|
||||
context('dialog help button was pressed', () => {
|
||||
let networkCalled;
|
||||
beforeEach(() => {
|
||||
networkCalled = false;
|
||||
pgBrowser.treeMenu.selectNode(serverTreeNode.domNode);
|
||||
networkMock.onAny(/.+/).reply(() => {
|
||||
networkCalled = true;
|
||||
return [200, {}];
|
||||
});
|
||||
|
||||
const event = {
|
||||
button: {
|
||||
element: {
|
||||
name: 'dialog_help',
|
||||
getAttribute: (attributeName) => {
|
||||
if (attributeName === 'url') {
|
||||
return 'http://someurl';
|
||||
} else if (attributeName === 'label') {
|
||||
return 'some label';
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
restoreDialogWrapper.callback(event);
|
||||
});
|
||||
|
||||
it('displays help for dialog', () => {
|
||||
expect(pgBrowser.showHelp).toHaveBeenCalledWith(
|
||||
'dialog_help',
|
||||
'http://someurl',
|
||||
pgBrowser.Nodes['server'],
|
||||
serverTreeNode,
|
||||
'some label'
|
||||
);
|
||||
});
|
||||
|
||||
it('does not start the restore', () => {
|
||||
expect(networkCalled).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
context('object help button was pressed', () => {
|
||||
let networkCalled;
|
||||
beforeEach(() => {
|
||||
networkCalled = false;
|
||||
pgBrowser.treeMenu.selectNode(serverTreeNode.domNode);
|
||||
networkMock.onAny(/.+/).reply(() => {
|
||||
networkCalled = true;
|
||||
return [200, {}];
|
||||
});
|
||||
|
||||
const event = {
|
||||
button: {
|
||||
element: {
|
||||
name: 'object_help',
|
||||
getAttribute: (attributeName) => {
|
||||
if (attributeName === 'url') {
|
||||
return 'http://someurl';
|
||||
} else if (attributeName === 'label') {
|
||||
return 'some label';
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
restoreDialogWrapper.callback(event);
|
||||
});
|
||||
|
||||
it('displays help for dialog', () => {
|
||||
expect(pgBrowser.showHelp).toHaveBeenCalledWith(
|
||||
'object_help',
|
||||
'http://someurl',
|
||||
pgBrowser.Nodes['server'],
|
||||
serverTreeNode,
|
||||
'some label'
|
||||
);
|
||||
});
|
||||
|
||||
it('does not start the restore', () => {
|
||||
expect(networkCalled).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
context('restore button was pressed', () => {
|
||||
let networkCalled;
|
||||
let event;
|
||||
|
||||
context('no tree node is selected', () => {
|
||||
beforeEach(() => {
|
||||
networkCalled = false;
|
||||
networkMock.onAny(/.+/).reply(() => {
|
||||
networkCalled = true;
|
||||
return [200, {}];
|
||||
});
|
||||
event = {
|
||||
button: {
|
||||
'data-btn-name': 'restore',
|
||||
element: {
|
||||
getAttribute: () => {
|
||||
return 'http://someurl';
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
it('does not start the restore', () => {
|
||||
restoreDialogWrapper.callback(event);
|
||||
expect(networkCalled).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
context('tree node selected has no data', () => {
|
||||
beforeEach(() => {
|
||||
networkCalled = false;
|
||||
networkMock.onAny(/.+/).reply(() => {
|
||||
networkCalled = true;
|
||||
return [200, {}];
|
||||
});
|
||||
event = {
|
||||
button: {
|
||||
'data-btn-name': 'restore',
|
||||
element: {
|
||||
getAttribute: () => {
|
||||
return 'http://someurl';
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
pgBrowser.treeMenu.selectNode(noDataNode.domNode);
|
||||
});
|
||||
|
||||
it('does not start the restore', () => {
|
||||
restoreDialogWrapper.callback(event);
|
||||
expect(networkCalled).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
context('tree node select has data', () => {
|
||||
|
||||
let databaseTreeNode;
|
||||
|
||||
beforeEach(() => {
|
||||
databaseTreeNode = pgBrowser.treeMenu.addNewNode('level3.1', {
|
||||
_type: 'database',
|
||||
_id: 10,
|
||||
_label: 'some-database-label',
|
||||
}, [{id: 'level3.1'}]);
|
||||
pgBrowser.treeMenu.addChild(serverTreeNode, databaseTreeNode);
|
||||
pgBrowser.Nodes.database = {
|
||||
hasId: true,
|
||||
_label: 'some-database-label',
|
||||
};
|
||||
let fakeModel = new FakeModel();
|
||||
fakeModel.set('some-key', 'some-value');
|
||||
restoreDialogWrapper.view = {
|
||||
model: fakeModel,
|
||||
};
|
||||
pgBrowser.treeMenu.selectNode(databaseTreeNode.domNode);
|
||||
pgBrowser.Events = jasmine.createSpyObj('pgBrowserEventsSpy', ['trigger']);
|
||||
event = {
|
||||
button: {
|
||||
'data-btn-name': 'restore',
|
||||
element: {
|
||||
getAttribute: () => {
|
||||
return 'http://someurl';
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
context('restore job created successfully', () => {
|
||||
let dataSentToServer;
|
||||
beforeEach(() => {
|
||||
networkMock.onPost('/restore/job/10').reply((request) => {
|
||||
dataSentToServer = request.data;
|
||||
return [200, {}];
|
||||
});
|
||||
});
|
||||
|
||||
it('create an success alert box', (done) => {
|
||||
restoreDialogWrapper.callback(event);
|
||||
setTimeout(() => {
|
||||
expect(alertifySpy.success).toHaveBeenCalledWith(
|
||||
'Restore job created.',
|
||||
5
|
||||
);
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
|
||||
it('trigger background process', (done) => {
|
||||
restoreDialogWrapper.callback(event);
|
||||
setTimeout(() => {
|
||||
expect(pgBrowser.Events.trigger).toHaveBeenCalledWith(
|
||||
'pgadmin-bgprocess:created',
|
||||
restoreDialogWrapper
|
||||
);
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
|
||||
it('send correct data to server', (done) => {
|
||||
restoreDialogWrapper.callback(event);
|
||||
setTimeout(() => {
|
||||
expect(JSON.parse(dataSentToServer)).toEqual({
|
||||
'some-key': 'some-value',
|
||||
'database': 'some-database-label',
|
||||
});
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
});
|
||||
|
||||
context('error creating restore job', () => {
|
||||
beforeEach(() => {
|
||||
networkMock.onPost('/restore/job/10').reply(() => {
|
||||
return [400, {}];
|
||||
});
|
||||
});
|
||||
|
||||
it('creates an alert box', (done) => {
|
||||
restoreDialogWrapper.callback(event);
|
||||
setTimeout(() => {
|
||||
expect(alertifySpy.alert).toHaveBeenCalledWith(
|
||||
'Restore job failed.',
|
||||
undefined
|
||||
);
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('setExtraParameters', () => {
|
||||
let selectedNode;
|
||||
let treeInfo;
|
||||
let model;
|
||||
|
||||
beforeEach(() => {
|
||||
restoreDialogWrapper = new RestoreDialogWrapper(
|
||||
'<div class=\'restore_dialog\'></div>',
|
||||
'restoreDialogTitle',
|
||||
'restore',
|
||||
jquerySpy,
|
||||
pgBrowser,
|
||||
alertifySpy,
|
||||
dialogModelKlassSpy,
|
||||
backform
|
||||
);
|
||||
|
||||
model = new FakeModel();
|
||||
restoreDialogWrapper.view = {
|
||||
model: model,
|
||||
};
|
||||
});
|
||||
|
||||
context('when it is a custom model', () => {
|
||||
beforeEach(() => {
|
||||
model.set('custom', true);
|
||||
treeInfo = {
|
||||
'database': {
|
||||
'_label': 'some-database-label',
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
it('only sets the database', () => {
|
||||
restoreDialogWrapper.setExtraParameters(selectedNode, treeInfo);
|
||||
expect(model.toJSON()).toEqual({
|
||||
'custom': true,
|
||||
'database': 'some-database-label',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
context('when it is not a custom model', () => {
|
||||
beforeEach(() => {
|
||||
model.set('custom', false);
|
||||
treeInfo = {
|
||||
'database': {
|
||||
'_label': 'some-database-label',
|
||||
},
|
||||
'schema': {
|
||||
'_label': 'some-schema-label',
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
context('when selected node is a schema', () => {
|
||||
it('sets schemas on the model', () => {
|
||||
selectedNode = new TreeNode('schema', {_type: 'schema', _label: 'some-schema-label'}, '');
|
||||
restoreDialogWrapper.setExtraParameters(selectedNode, treeInfo);
|
||||
expect(model.toJSON()).toEqual({
|
||||
custom: false,
|
||||
database: 'some-database-label',
|
||||
schemas: ['some-schema-label'],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
context('when selected node is a table', () => {
|
||||
it('sets schemas and table on the model', () => {
|
||||
selectedNode = new TreeNode('table', {_type: 'table', _label: 'some-table-label'}, '');
|
||||
restoreDialogWrapper.setExtraParameters(selectedNode, treeInfo);
|
||||
expect(model.toJSON()).toEqual({
|
||||
custom: false,
|
||||
database: 'some-database-label',
|
||||
schemas: ['some-schema-label'],
|
||||
tables: ['some-table-label'],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
context('when selected node is a function', () => {
|
||||
it('sets schemas and function on the model', () => {
|
||||
selectedNode = new TreeNode('function', {_type: 'function', _label: 'some-function-label'}, '');
|
||||
restoreDialogWrapper.setExtraParameters(selectedNode, treeInfo);
|
||||
expect(model.toJSON()).toEqual({
|
||||
custom: false,
|
||||
database: 'some-database-label',
|
||||
schemas: ['some-schema-label'],
|
||||
functions: ['some-function-label'],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
context('when selected node is an index', () => {
|
||||
it('sets schemas and index on the model', () => {
|
||||
selectedNode = new TreeNode('index', {_type: 'index', _label: 'some-index-label'}, '');
|
||||
restoreDialogWrapper.setExtraParameters(selectedNode, treeInfo);
|
||||
expect(model.toJSON()).toEqual({
|
||||
custom: false,
|
||||
database: 'some-database-label',
|
||||
schemas: ['some-schema-label'],
|
||||
indexes: ['some-index-label'],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
context('when selected node is a trigger', () => {
|
||||
it('sets schemas and trigger on the model', () => {
|
||||
selectedNode = new TreeNode('trigger', {_type: 'trigger', _label: 'some-trigger-label'}, '');
|
||||
restoreDialogWrapper.setExtraParameters(selectedNode, treeInfo);
|
||||
expect(model.toJSON()).toEqual({
|
||||
custom: false,
|
||||
database: 'some-database-label',
|
||||
schemas: ['some-schema-label'],
|
||||
triggers: ['some-trigger-label'],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
context('when selected node is a trigger_func', () => {
|
||||
it('sets schemas and trigger_func on the model', () => {
|
||||
selectedNode = new TreeNode('trigger_func', {_type: 'trigger_func', _label: 'some-trigger_func-label'}, '');
|
||||
restoreDialogWrapper.setExtraParameters(selectedNode, treeInfo);
|
||||
expect(model.toJSON()).toEqual({
|
||||
custom: false,
|
||||
database: 'some-database-label',
|
||||
schemas: ['some-schema-label'],
|
||||
trigger_funcs: ['some-trigger_func-label'],
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -7,10 +7,8 @@
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
import filterDialog from 'sources/sqleditor/filter_dialog';
|
||||
// import filterDialogModel from 'sources/sqleditor/filter_dialog_model';
|
||||
|
||||
describe('filterDialog', () => {
|
||||
jasmine.createSpy('sqlEditorController');
|
||||
describe('filterDialog', () => {
|
||||
describe('when using filter dialog', () => {
|
||||
beforeEach(() => {
|
||||
|
||||
271
web/regression/javascript/table/enable_disable_triggers_spec.js
Normal file
271
web/regression/javascript/table/enable_disable_triggers_spec.js
Normal file
@@ -0,0 +1,271 @@
|
||||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2018, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
import MockAdapter from 'axios-mock-adapter';
|
||||
import axios from 'axios/index';
|
||||
import {
|
||||
enableTriggers,
|
||||
disableTriggers,
|
||||
} from '../../../pgadmin/browser/server_groups/servers/databases/schemas/tables/static/js/enable_disable_triggers';
|
||||
import {TreeFake} from '../tree/tree_fake';
|
||||
import {TreeNode} from '../../../pgadmin/static/js/tree/tree';
|
||||
|
||||
describe('#enableTriggers', () => {
|
||||
let networkMock;
|
||||
let tree;
|
||||
let alertify;
|
||||
let generateUrlSpy;
|
||||
beforeEach(() => {
|
||||
networkMock = new MockAdapter(axios);
|
||||
tree = new TreeFake();
|
||||
const server1 = tree.addNewNode('server1', {_id: 1}, ['<li>server1</li>']);
|
||||
const database1 = tree.addNewNode('database1', {_type: 'database'}, ['<li>database1</li>']);
|
||||
tree.addChild(server1, database1);
|
||||
|
||||
const schema1 = tree.addNewNode('schema1', {_type: 'schema'}, ['<li>schema1</li>']);
|
||||
tree.addChild(database1, schema1);
|
||||
|
||||
const table1 = tree.addNewNode('table1', {_type: 'table'}, ['<li>table1</li>']);
|
||||
tree.addChild(schema1, table1);
|
||||
|
||||
const column1 = tree.addNewNode('column1', {_type: 'column'}, ['<li>column1</li>']);
|
||||
tree.addChild(table1, column1);
|
||||
|
||||
const tableNoData = tree.addNewNode('table-no-data', undefined, ['<li>table-no-data</li>']);
|
||||
tree.addChild(schema1, tableNoData);
|
||||
|
||||
alertify = jasmine.createSpyObj('alertify', ['success', 'error']);
|
||||
generateUrlSpy = jasmine.createSpy('generateUrl');
|
||||
generateUrlSpy.and.returnValue('/some/place');
|
||||
});
|
||||
|
||||
describe('no node is selected', () => {
|
||||
it('does not send the request to the backend', (done) => {
|
||||
networkMock.onAny('.*').reply(200, () => {
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
expect(enableTriggers(tree, alertify, generateUrlSpy, {})).toBe(false);
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('a node is selected', () => {
|
||||
describe('node as no data', () => {
|
||||
it('does not send the request to the backend', () => {
|
||||
tree.selectNode([{id: 'table-no-data'}]);
|
||||
|
||||
networkMock.onAny('.*').reply(200, () => {
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
expect(enableTriggers(tree, alertify, generateUrlSpy, {})).toBe(false);
|
||||
}, 0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('node as data', () => {
|
||||
describe('backend responds with success', () => {
|
||||
let networkMockCalledWith;
|
||||
beforeEach(() => {
|
||||
networkMockCalledWith = false;
|
||||
networkMock.onPut(/.*/).reply((configuration) => {
|
||||
networkMockCalledWith = configuration;
|
||||
return [200, {
|
||||
success: 1,
|
||||
info: 'some information',
|
||||
}];
|
||||
});
|
||||
});
|
||||
|
||||
it('displays an alert box with success', (done) => {
|
||||
tree.selectNode([{id: 'table1'}]);
|
||||
enableTriggers(tree, alertify, generateUrlSpy, {});
|
||||
setTimeout(() => {
|
||||
expect(alertify.success).toHaveBeenCalledWith('some information');
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
|
||||
it('reloads the node', (done) => {
|
||||
enableTriggers(tree, alertify, generateUrlSpy, {item: [{id: 'table1'}]});
|
||||
setTimeout(() => {
|
||||
expect(tree.selected()).toEqual(['<li>table1</li>']);
|
||||
done();
|
||||
}, 20);
|
||||
});
|
||||
|
||||
it('call backend with the correct parameters', (done) => {
|
||||
enableTriggers(tree, alertify, generateUrlSpy, {item: [{id: 'table1'}]});
|
||||
setTimeout(() => {
|
||||
expect(networkMockCalledWith.data).toEqual(JSON.stringify({enable: 'true'}));
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('backend responds with error', () => {
|
||||
beforeEach(() => {
|
||||
networkMock.onPut(/.*/).reply(() => {
|
||||
return [500, {
|
||||
success: 0,
|
||||
errormsg: 'some error message',
|
||||
}];
|
||||
});
|
||||
});
|
||||
|
||||
it('displays an error alert', (done) => {
|
||||
tree.selectNode([{id: 'table1'}]);
|
||||
enableTriggers(tree, alertify, generateUrlSpy, {});
|
||||
setTimeout(() => {
|
||||
expect(alertify.error).toHaveBeenCalledWith('some error message');
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
|
||||
it('unload the node', (done) => {
|
||||
enableTriggers(tree, alertify, generateUrlSpy, {item: [{id: 'table1'}]});
|
||||
|
||||
setTimeout(() => {
|
||||
expect(tree.findNodeByDomElement([{id: 'table1'}]).children.length).toBe(0);
|
||||
done();
|
||||
}, 20);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#disableTriggers', () => {
|
||||
let networkMock;
|
||||
let tree;
|
||||
let alertify;
|
||||
let generateUrlSpy;
|
||||
beforeEach(() => {
|
||||
networkMock = new MockAdapter(axios);
|
||||
tree = new TreeFake();
|
||||
const server1 = tree.addNewNode('server1', {_id: 1}, ['<li>server1</li>']);
|
||||
const database1 = new TreeNode('database1', {_type: 'database'}, ['<li>database1</li>']);
|
||||
tree.addChild(server1, database1);
|
||||
|
||||
const schema1 = new TreeNode('schema1', {_type: 'schema'}, ['<li>schema1</li>']);
|
||||
tree.addChild(database1, schema1);
|
||||
|
||||
const table1 = new TreeNode('table1', {_type: 'table'}, ['<li>table1</li>']);
|
||||
tree.addChild(schema1, table1);
|
||||
|
||||
const column1 = new TreeNode('column1', {_type: 'column'}, ['<li>column1</li>']);
|
||||
tree.addChild(table1, column1);
|
||||
|
||||
const tableNoData = new TreeNode('table-no-data', undefined, ['<li>table-no-data</li>']);
|
||||
tree.addChild(schema1, tableNoData);
|
||||
|
||||
alertify = jasmine.createSpyObj('alertify', ['success', 'error']);
|
||||
generateUrlSpy = jasmine.createSpy('generateUrl');
|
||||
generateUrlSpy.and.returnValue('/some/place');
|
||||
});
|
||||
|
||||
describe('no node is selected', () => {
|
||||
it('does not send the request to the backend', (done) => {
|
||||
networkMock.onAny('.*').reply(200, () => {
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
expect(disableTriggers(tree, alertify, generateUrlSpy, {})).toBe(false);
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('a node is selected', () => {
|
||||
describe('node as no data', () => {
|
||||
it('does not send the request to the backend', () => {
|
||||
tree.selectNode([{id: 'table-no-data'}]);
|
||||
|
||||
networkMock.onAny('.*').reply(200, () => {
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
expect(disableTriggers(tree, alertify, generateUrlSpy, {})).toBe(false);
|
||||
}, 0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('node as data', () => {
|
||||
describe('backend responds with success', () => {
|
||||
let networkMockCalledWith;
|
||||
beforeEach(() => {
|
||||
networkMockCalledWith = false;
|
||||
networkMock.onPut(/.*/).reply((configuration) => {
|
||||
networkMockCalledWith = configuration;
|
||||
return [200, {
|
||||
success: 1,
|
||||
info: 'some information',
|
||||
}];
|
||||
});
|
||||
});
|
||||
|
||||
it('displays an alert box with success', (done) => {
|
||||
tree.selectNode([{id: 'table1'}]);
|
||||
disableTriggers(tree, alertify, generateUrlSpy, {});
|
||||
setTimeout(() => {
|
||||
expect(alertify.success).toHaveBeenCalledWith('some information');
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
|
||||
it('reloads the node', (done) => {
|
||||
disableTriggers(tree, alertify, generateUrlSpy, {item: [{id: 'table1'}]});
|
||||
setTimeout(() => {
|
||||
expect(tree.selected()).toEqual(['<li>table1</li>']);
|
||||
done();
|
||||
}, 20);
|
||||
});
|
||||
|
||||
it('call backend with the correct parameters', (done) => {
|
||||
disableTriggers(tree, alertify, generateUrlSpy, {item: [{id: 'table1'}]});
|
||||
setTimeout(() => {
|
||||
expect(networkMockCalledWith.data).toEqual(JSON.stringify({enable: 'false'}));
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('backend responds with error', () => {
|
||||
beforeEach(() => {
|
||||
networkMock.onPut(/.*/).reply(() => {
|
||||
return [500, {
|
||||
success: 0,
|
||||
errormsg: 'some error message',
|
||||
}];
|
||||
});
|
||||
});
|
||||
|
||||
it('displays an error alert', (done) => {
|
||||
tree.selectNode([{id: 'table1'}]);
|
||||
disableTriggers(tree, alertify, generateUrlSpy, {});
|
||||
setTimeout(() => {
|
||||
expect(alertify.error).toHaveBeenCalledWith('some error message');
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
|
||||
it('unload the node', (done) => {
|
||||
disableTriggers(tree, alertify, generateUrlSpy, {item: [{id: 'table1'}]});
|
||||
|
||||
setTimeout(() => {
|
||||
expect(tree.findNodeByDomElement([{id: 'table1'}]).children.length).toBe(0);
|
||||
done();
|
||||
}, 20);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
353
web/regression/javascript/tree/pgadmin_tree_node_spec.js
Normal file
353
web/regression/javascript/tree/pgadmin_tree_node_spec.js
Normal file
@@ -0,0 +1,353 @@
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2018, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
import {
|
||||
getTreeNodeHierarchyFromElement,
|
||||
getTreeNodeHierarchyFromIdentifier,
|
||||
} from '../../../pgadmin/static/js/tree/pgadmin_tree_node';
|
||||
import {TreeNode} from '../../../pgadmin/static/js/tree/tree';
|
||||
import {TreeFake} from './tree_fake';
|
||||
|
||||
const context = describe;
|
||||
|
||||
describe('tree#node#getTreeNodeHierarchy', () => {
|
||||
let browser;
|
||||
let newTree;
|
||||
beforeEach(() => {
|
||||
newTree = new TreeFake();
|
||||
browser = {
|
||||
Nodes: {
|
||||
'special one': {hasId: true},
|
||||
'child special': {hasId: true},
|
||||
'other type': {hasId: true},
|
||||
'table': {hasId: true},
|
||||
'partition': {hasId: true},
|
||||
'no id': {hasId: false},
|
||||
},
|
||||
};
|
||||
browser.treeMenu = newTree;
|
||||
});
|
||||
|
||||
context('getTreeNodeHierarchy is called with aciTreeNode object', () => {
|
||||
describe('When the current node is root element', () => {
|
||||
beforeEach(() => {
|
||||
newTree.addNewNode('root', {
|
||||
'some key': 'some value',
|
||||
'_type': 'special one',
|
||||
});
|
||||
});
|
||||
|
||||
it('returns a object with the element type passed data and priority == 0', () => {
|
||||
const result = getTreeNodeHierarchyFromIdentifier.bind(browser)([{id: 'root'}]);
|
||||
expect(result).toEqual({
|
||||
'special one': {
|
||||
'some key': 'some value',
|
||||
'_type': 'special one',
|
||||
'priority': 0,
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('When the current node is not of a known type', () => {
|
||||
beforeEach(() => {
|
||||
newTree.addNewNode('root', {
|
||||
'some key': 'some value',
|
||||
'_type': 'do not exist',
|
||||
}, []);
|
||||
});
|
||||
|
||||
it('returns a empty object', () => {
|
||||
const result = getTreeNodeHierarchyFromIdentifier.bind(browser)('root');
|
||||
expect(result).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
describe('When the current node type has no id', () => {
|
||||
beforeEach(() => {
|
||||
newTree.addNewNode('root', {
|
||||
'some key': 'some value',
|
||||
'_type': 'no id',
|
||||
}, []);
|
||||
});
|
||||
|
||||
it('returns a empty object', () => {
|
||||
const result = getTreeNodeHierarchyFromIdentifier.bind(browser)('root');
|
||||
expect(result).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
describe('When the current node is at the second level', () => {
|
||||
beforeEach(() => {
|
||||
const root = newTree.addNewNode('root', {
|
||||
'some key': 'some value',
|
||||
'_type': 'special one',
|
||||
});
|
||||
const firstChild = new TreeNode('first child', {
|
||||
'some key': 'some other value',
|
||||
'_type': 'child special',
|
||||
}, ['root']);
|
||||
newTree.addChild(root, firstChild);
|
||||
});
|
||||
|
||||
it('returns a empty object', () => {
|
||||
const result = getTreeNodeHierarchyFromIdentifier.bind(browser)([{id: 'first child'}]);
|
||||
expect(result).toEqual({
|
||||
'child special': {
|
||||
'some key': 'some other value',
|
||||
'_type': 'child special',
|
||||
'priority': 0,
|
||||
},
|
||||
'special one': {
|
||||
'some key': 'some value',
|
||||
'_type': 'special one',
|
||||
'priority': -1,
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
context('When tree as "special type"', () => {
|
||||
context('When "special type" have "other type"', () => {
|
||||
context('When "other type" have "special type"', () => {
|
||||
describe('When retrieving lead node', () => {
|
||||
it('does not override previous node type data', () => {
|
||||
const rootNode = newTree.addNewNode('root', {
|
||||
'some key': 'some value',
|
||||
'_type': 'special one',
|
||||
}, []);
|
||||
|
||||
const level1 = new TreeNode('level 1', {
|
||||
'some key': 'some value',
|
||||
'_type': 'other type',
|
||||
});
|
||||
newTree.addChild(rootNode, level1);
|
||||
|
||||
newTree.addChild(level1, new TreeNode('level 2', {
|
||||
'some key': 'expected value',
|
||||
'_type': 'special one',
|
||||
'some other key': 'some other value',
|
||||
}));
|
||||
|
||||
const result = getTreeNodeHierarchyFromIdentifier.bind(browser)([{id: 'level 2'}]);
|
||||
expect(result).toEqual({
|
||||
'special one': {
|
||||
'some key': 'expected value',
|
||||
'_type': 'special one',
|
||||
'some other key': 'some other value',
|
||||
'priority': 0,
|
||||
},
|
||||
'other type': {
|
||||
'some key': 'some value',
|
||||
'_type': 'other type',
|
||||
'priority': -1,
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
context('When tree has table', () => {
|
||||
context('when table has partition', () => {
|
||||
it('returns table with partition parameters', () => {
|
||||
const root = newTree.addNewNode('root', {
|
||||
'some key': 'some value',
|
||||
'_type': 'special one',
|
||||
}, []);
|
||||
const level1 = new TreeNode('level 1', {
|
||||
'some key': 'some value',
|
||||
'_type': 'table',
|
||||
});
|
||||
newTree.addChild(root, level1);
|
||||
newTree.addChild(level1, new TreeNode('level 2', {
|
||||
'some key': 'expected value',
|
||||
'_type': 'partition',
|
||||
'some other key': 'some other value',
|
||||
}));
|
||||
|
||||
const result = getTreeNodeHierarchyFromIdentifier.bind(browser)([{id:'level 2'}]);
|
||||
expect(result).toEqual({
|
||||
'special one': {
|
||||
'some key': 'some value',
|
||||
'_type': 'special one',
|
||||
'priority': -1,
|
||||
},
|
||||
'table': {
|
||||
'some key': 'expected value',
|
||||
'some other key': 'some other value',
|
||||
'_type': 'partition',
|
||||
'priority': 0,
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
context('getTreeNodeHierarchy is called with TreeNode object', () => {
|
||||
let treeNode;
|
||||
describe('When the current node is root element', () => {
|
||||
beforeEach(() => {
|
||||
treeNode = newTree.addNewNode('root', {
|
||||
'some key': 'some value',
|
||||
'_type': 'special one',
|
||||
}, []);
|
||||
});
|
||||
|
||||
it('returns a object with the element type passed data and priority == 0', () => {
|
||||
const result = getTreeNodeHierarchyFromElement(browser, treeNode);
|
||||
expect(result).toEqual({
|
||||
'special one': {
|
||||
'some key': 'some value',
|
||||
'_type': 'special one',
|
||||
'priority': 0,
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('When the current node is not of a known type', () => {
|
||||
beforeEach(() => {
|
||||
treeNode = newTree.addNewNode('root', {
|
||||
'some key': 'some value',
|
||||
'_type': 'do not exist',
|
||||
}, []);
|
||||
});
|
||||
|
||||
it('returns a empty object', () => {
|
||||
const result = getTreeNodeHierarchyFromElement(browser, treeNode);
|
||||
expect(result).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
describe('When the current node type has no id', () => {
|
||||
beforeEach(() => {
|
||||
treeNode = newTree.addNewNode('root', {
|
||||
'some key': 'some value',
|
||||
'_type': 'no id',
|
||||
}, []);
|
||||
});
|
||||
|
||||
it('returns a empty object', () => {
|
||||
const result = getTreeNodeHierarchyFromElement(browser, treeNode);
|
||||
expect(result).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
describe('When the current node is at the second level', () => {
|
||||
beforeEach(() => {
|
||||
const root = newTree.addNewNode('root', {
|
||||
'some key': 'some value',
|
||||
'_type': 'special one',
|
||||
}, []);
|
||||
treeNode = new TreeNode('first child', {
|
||||
'some key': 'some other value',
|
||||
'_type': 'child special',
|
||||
});
|
||||
newTree.addChild(root, treeNode);
|
||||
});
|
||||
|
||||
it('returns a empty object', () => {
|
||||
const result = getTreeNodeHierarchyFromElement(browser, treeNode);
|
||||
expect(result).toEqual({
|
||||
'child special': {
|
||||
'some key': 'some other value',
|
||||
'_type': 'child special',
|
||||
'priority': 0,
|
||||
},
|
||||
'special one': {
|
||||
'some key': 'some value',
|
||||
'_type': 'special one',
|
||||
'priority': -1,
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
context('When tree as "special type"', () => {
|
||||
context('When "special type" have "other type"', () => {
|
||||
context('When "other type" have "special type"', () => {
|
||||
describe('When retrieving lead node', () => {
|
||||
it('does not override previous node type data', () => {
|
||||
const root = newTree.addNewNode('root', {
|
||||
'some key': 'some value',
|
||||
'_type': 'special one',
|
||||
}, []);
|
||||
const level1 = new TreeNode('level 1', {
|
||||
'some key': 'some value',
|
||||
'_type': 'other type',
|
||||
});
|
||||
newTree.addChild(root, level1);
|
||||
treeNode = new TreeNode('level 2', {
|
||||
'some key': 'expected value',
|
||||
'_type': 'special one',
|
||||
'some other key': 'some other value',
|
||||
});
|
||||
newTree.addChild(level1, treeNode);
|
||||
|
||||
const result = getTreeNodeHierarchyFromElement(browser, treeNode);
|
||||
expect(result).toEqual({
|
||||
'special one': {
|
||||
'some key': 'expected value',
|
||||
'_type': 'special one',
|
||||
'some other key': 'some other value',
|
||||
'priority': 0,
|
||||
},
|
||||
'other type': {
|
||||
'some key': 'some value',
|
||||
'_type': 'other type',
|
||||
'priority': -1,
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
context('When tree has table', () => {
|
||||
context('when table has partition', () => {
|
||||
it('returns table with partition parameters', () => {
|
||||
const root = newTree.addNewNode('root', {
|
||||
'some key': 'some value',
|
||||
'_type': 'special one',
|
||||
});
|
||||
const level1 = newTree.addNewNode('level 1', {
|
||||
'some key': 'some value',
|
||||
'_type': 'table',
|
||||
});
|
||||
newTree.addChild(root, level1);
|
||||
treeNode = new TreeNode('level 2', {
|
||||
'some key': 'expected value',
|
||||
'_type': 'partition',
|
||||
'some other key': 'some other value',
|
||||
});
|
||||
newTree.addChild(level1, treeNode);
|
||||
|
||||
const result = getTreeNodeHierarchyFromElement(browser, treeNode);
|
||||
expect(result).toEqual({
|
||||
'special one': {
|
||||
'some key': 'some value',
|
||||
'_type': 'special one',
|
||||
'priority': -1,
|
||||
},
|
||||
'table': {
|
||||
'some key': 'expected value',
|
||||
'some other key': 'some other value',
|
||||
'_type': 'partition',
|
||||
'priority': 0,
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -10,6 +10,32 @@
|
||||
import {Tree} from '../../../pgadmin/static/js/tree/tree';
|
||||
|
||||
export class TreeFake extends Tree {
|
||||
static build(structure) {
|
||||
let tree = new TreeFake();
|
||||
let rootNode = tree.rootNode;
|
||||
|
||||
if (structure.children !== undefined) {
|
||||
structure.children.forEach((child) => {
|
||||
TreeFake.recursivelyAddNodes(tree, child, rootNode);
|
||||
});
|
||||
}
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
static recursivelyAddNodes(tree, newNode, parent) {
|
||||
let id = newNode.id;
|
||||
let data = newNode.data ? newNode.data : {};
|
||||
let domNode = newNode.domNode ? newNode.domNode : [{id: id}];
|
||||
tree.addNewNode(id, data, domNode, tree.translateTreeNodeIdFromACITree([parent]));
|
||||
|
||||
if (newNode.children !== undefined) {
|
||||
newNode.children.forEach((child) => {
|
||||
TreeFake.recursivelyAddNodes(tree, child, newNode);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.aciTreeToOurTreeTranslator = {};
|
||||
@@ -45,7 +71,7 @@ export class TreeFake extends Tree {
|
||||
}
|
||||
|
||||
translateTreeNodeIdFromACITree(aciTreeNode) {
|
||||
if(aciTreeNode === undefined || aciTreeNode[0] === undefined) {
|
||||
if (aciTreeNode === undefined || aciTreeNode[0] === undefined) {
|
||||
return null;
|
||||
}
|
||||
return this.aciTreeToOurTreeTranslator[aciTreeNode[0].id];
|
||||
|
||||
Reference in New Issue
Block a user