Fix the server context menu showing database options after the tree state is restored. #7612 (#10580)
This commit is contained in:
@@ -474,10 +474,16 @@ define('pgadmin.node.database', [
|
||||
pgBrowser.Events.trigger(
|
||||
'pgadmin:database:connected', _item, _data
|
||||
);
|
||||
/* Call enable/disable menu function after database is connected.
|
||||
To make sure all the menus for database is in the right state */
|
||||
pgBrowser.enable_disable_menus(_item);
|
||||
pgBrowser.Nodes['database'].callbacks.selected(_item, _data);
|
||||
/* Refresh the menus after the database is connected, so that
|
||||
they are in the right state. The menus always belong to the
|
||||
selected node, which may not be this database: it can be
|
||||
connected by expanding it, e.g. whilst the previous tree state
|
||||
is restored, so only treat it as selected if it really is. */
|
||||
if (_tree.selected() === _item) {
|
||||
pgBrowser.Nodes['database'].callbacks.selected(_item, _data);
|
||||
} else {
|
||||
pgBrowser.enable_disable_menus();
|
||||
}
|
||||
|
||||
if (!_connected) {
|
||||
setTimeout(function() {
|
||||
|
||||
@@ -698,9 +698,11 @@ define('pgadmin.node.server', [
|
||||
// Load dashboard
|
||||
pgBrowser.Events.trigger('pgadmin-browser:tree:selected', _item, _data, node);
|
||||
|
||||
/* Call enable/disable menu function after database is connected.
|
||||
To make sure all the menus for database is in the right state */
|
||||
pgBrowser.enable_disable_menus(_item);
|
||||
/* Refresh the menus after the server is connected, so that they
|
||||
are in the right state. They always belong to the selected node,
|
||||
which may not be this server if it was connected by expanding
|
||||
it, so do not pass the server's item here. */
|
||||
pgBrowser.enable_disable_menus();
|
||||
|
||||
/* Below code is added to show the error message if
|
||||
connection is successful, but there is an error to
|
||||
|
||||
148
web/regression/javascript/browser/node_connect_menus_spec.js
Normal file
148
web/regression/javascript/browser/node_connect_menus_spec.js
Normal file
@@ -0,0 +1,148 @@
|
||||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2026, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
const mockPost = jest.fn();
|
||||
|
||||
jest.mock('../../../pgadmin/static/js/api_instance', () => ({
|
||||
__esModule: true,
|
||||
default: () => ({
|
||||
post: mockPost, get: jest.fn(() => Promise.resolve({data: {}})),
|
||||
delete: jest.fn(),
|
||||
}),
|
||||
parseApiError: (e) => e,
|
||||
}));
|
||||
jest.mock('../../../pgadmin/static/js/Dialogs/index', () => ({
|
||||
showServerPassword: jest.fn(),
|
||||
}));
|
||||
|
||||
const pgBrowser = {
|
||||
Nodes: {},
|
||||
Node: {
|
||||
extend: (props) => ({...props, generate_url: () => '/connect'}),
|
||||
callbacks: {selected: jest.fn()},
|
||||
},
|
||||
Collection: {extend: (props) => props},
|
||||
Events: {trigger: jest.fn(), on: jest.fn()},
|
||||
enable_disable_menus: jest.fn(),
|
||||
notifier: {success: jest.fn(), info: jest.fn(), warning: jest.fn()},
|
||||
stdW: {md: 650},
|
||||
};
|
||||
const pgAdmin = {Browser: pgBrowser};
|
||||
|
||||
// The node modules register themselves through an AMD style define(); load
|
||||
// them with a stub that hands each factory our fake browser.
|
||||
global.define = (_name, _deps, factory) => {
|
||||
factory((s) => s, () => '', pgAdmin, pgBrowser, {id: 1}, {});
|
||||
};
|
||||
require('../../../pgadmin/browser/server_groups/servers/databases/static/js/database');
|
||||
require('../../../pgadmin/browser/server_groups/servers/static/js/server');
|
||||
delete global.define;
|
||||
|
||||
// Let the mocked API calls resolve and the success handlers run.
|
||||
const flushPromises = async () => {
|
||||
for (let i = 0; i < 5; i++) {
|
||||
await Promise.resolve();
|
||||
}
|
||||
};
|
||||
|
||||
describe('database node connection', () => {
|
||||
let tree, serverItem, dbItem, dbData;
|
||||
|
||||
beforeEach(() => {
|
||||
jest.useFakeTimers();
|
||||
serverItem = {id: 'server'};
|
||||
dbItem = {id: 'db'};
|
||||
dbData = {_type: 'database', connected: false, allowConn: true, icon: 'x'};
|
||||
tree = {
|
||||
selected: jest.fn(),
|
||||
addIcon: jest.fn(),
|
||||
removeIcon: jest.fn(),
|
||||
select: jest.fn(),
|
||||
open: jest.fn(),
|
||||
};
|
||||
pgBrowser.tree = tree;
|
||||
pgBrowser.enable_disable_menus.mockClear();
|
||||
pgBrowser.Node.callbacks.selected.mockClear();
|
||||
mockPost.mockReset();
|
||||
mockPost.mockResolvedValue({data: {
|
||||
success: 1, info: 'Connected', data: {connected: true, icon: 'y'},
|
||||
}});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
const connectByExpanding = async () => {
|
||||
const node = pgBrowser.Nodes['database'];
|
||||
expect(node.callbacks.beforeopen.call(node, dbItem, dbData)).toBe(false);
|
||||
await flushPromises();
|
||||
};
|
||||
|
||||
it('keeps the menus on the selected server when a database is connected by expanding it', async () => {
|
||||
tree.selected.mockReturnValue(serverItem);
|
||||
|
||||
await connectByExpanding();
|
||||
|
||||
expect(dbData.connected).toBe(true);
|
||||
expect(pgBrowser.enable_disable_menus).toHaveBeenCalledWith();
|
||||
expect(pgBrowser.enable_disable_menus).not.toHaveBeenCalledWith(dbItem);
|
||||
expect(pgBrowser.Node.callbacks.selected).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('updates the menus for the database when it is the selected node', async () => {
|
||||
tree.selected.mockReturnValue(dbItem);
|
||||
|
||||
await connectByExpanding();
|
||||
|
||||
expect(dbData.connected).toBe(true);
|
||||
expect(pgBrowser.Node.callbacks.selected).toHaveBeenCalledWith(dbItem, dbData);
|
||||
});
|
||||
});
|
||||
|
||||
describe('server node connection', () => {
|
||||
let tree, otherItem, serverItem, serverData;
|
||||
|
||||
beforeEach(() => {
|
||||
jest.useFakeTimers();
|
||||
otherItem = {id: 'other'};
|
||||
serverItem = {id: 'server'};
|
||||
serverData = {_type: 'server', _id: 1, connected: false, icon: 'x'};
|
||||
tree = {
|
||||
selected: jest.fn(() => otherItem),
|
||||
addIcon: jest.fn(),
|
||||
removeIcon: jest.fn(),
|
||||
setLeaf: jest.fn(),
|
||||
setInode: jest.fn(),
|
||||
select: jest.fn(),
|
||||
open: jest.fn(),
|
||||
};
|
||||
pgBrowser.tree = tree;
|
||||
pgBrowser.enable_disable_menus.mockClear();
|
||||
mockPost.mockReset();
|
||||
mockPost.mockResolvedValue({data: {
|
||||
success: 1, info: 'Connected',
|
||||
data: {connected: true, icon: 'y', version: 180000},
|
||||
}});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
it('keeps the menus on the selected node when a server is connected by expanding it', async () => {
|
||||
const node = pgBrowser.Nodes['server'];
|
||||
expect(node.callbacks.beforeopen.call(node, serverItem, serverData)).toBe(false);
|
||||
await flushPromises();
|
||||
|
||||
expect(serverData.connected).toBe(true);
|
||||
expect(pgBrowser.enable_disable_menus).toHaveBeenCalledWith();
|
||||
expect(pgBrowser.enable_disable_menus).not.toHaveBeenCalledWith(serverItem);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user