Fix a number of broken connection detection scenarios.

This commit is contained in:
Akshay Joshi authored and Dave Page committed 2018-03-21 08:38:18 +00:00
1 parent d358369ed5
commit 637f3b9d1a
12 files changed
+154 -73

No files matched your search

+24 -10
View File
@@ -444,19 +444,26 @@ define('pgadmin.dashboard', [
pgAdmin.Dashboard.render_chart(container, data, dataset, sid, did, url, options, counter, refresh); pgAdmin.Dashboard.render_chart(container, data, dataset, sid, did, url, options, counter, refresh);
}, },
error: function(xhr) { error: function(xhr) {
var err = $.parseJSON(xhr.responseText), let err = '';
msg = err.errormsg, let msg = '';
cls; let cls = 'info';
if (xhr.readyState === 0) {
msg = gettext('Not connected to the server or the connection to the server has been closed.');
} else {
err = JSON.parse(xhr.responseText);
msg = err.errormsg;
// If we get a 428, it means the server isn't connected // If we get a 428, it means the server isn't connected
if (xhr.status == 428) { if (xhr.status === 428) {
if (_.isUndefined(msg) || _.isNull(msg)) { if (_.isUndefined(msg) || _.isNull(msg)) {
msg = gettext('Please connect to the selected server to view the graph.'); msg = gettext('Please connect to the selected server to view the graph.');
} }
cls = 'info';
} else { } else {
msg = gettext('An error occurred whilst rendering the graph.'); msg = gettext('An error occurred whilst rendering the graph.');
cls = 'danger'; cls = 'danger';
} }
}
$(container).addClass('graph-error'); $(container).addClass('graph-error');
$(container).html( $(container).html(
@@ -576,19 +583,26 @@ define('pgadmin.dashboard', [
filter.search(); filter.search();
}, },
error: function(model, xhr) { error: function(model, xhr) {
var err = $.parseJSON(xhr.responseText), let err = '';
msg = err.errormsg, let msg = '';
cls; let cls = 'info';
if (xhr.readyState === 0) {
msg = gettext('Not connected to the server or the connection to the server has been closed.');
} else {
err = JSON.parse(xhr.responseText);
msg = err.errormsg;
// If we get a 428, it means the server isn't connected // If we get a 428, it means the server isn't connected
if (xhr.status == 428) { if (xhr.status === 428) {
if (_.isUndefined(msg) || _.isNull(msg)) { if (_.isUndefined(msg) || _.isNull(msg)) {
msg = gettext('Please connect to the selected server to view the table.'); msg = gettext('Please connect to the selected server to view the table.');
} }
cls = 'info';
} else { } else {
msg = gettext('An error occurred whilst rendering the table.'); msg = gettext('An error occurred whilst rendering the table.');
cls = 'danger'; cls = 'danger';
} }
}
// Replace the content with the error, if not already present. Always update the message // Replace the content with the error, if not already present. Always update the message
if (!$(container).hasClass('grid-error')) { if (!$(container).hasClass('grid-error')) {
@@ -52,7 +52,7 @@ class ExecuteQuery {
}, self.sqlServerObject.POLL_FALLBACK_TIME()); }, self.sqlServerObject.POLL_FALLBACK_TIME());
} }
execute(sqlStatement, explainPlan) { execute(sqlStatement, explainPlan, connect) {
// If it is an empty query, do nothing. // If it is an empty query, do nothing.
if (sqlStatement.length <= 0) return; if (sqlStatement.length <= 0) return;
@@ -63,11 +63,8 @@ class ExecuteQuery {
const sqlStatementWithAnalyze = ExecuteQuery.prepareAnalyzeSql(sqlStatement, explainPlan); const sqlStatementWithAnalyze = ExecuteQuery.prepareAnalyzeSql(sqlStatement, explainPlan);
self.initializeExecutionOnSqlEditor(sqlStatementWithAnalyze); self.initializeExecutionOnSqlEditor(sqlStatementWithAnalyze);
service.post( service.post(
url_for('sqleditor.query_tool_start', { this.generateURLReconnectionFlag(connect),
'trans_id': self.sqlServerObject.transId,
}),
JSON.stringify(sqlStatementWithAnalyze), JSON.stringify(sqlStatementWithAnalyze),
{headers: {'Content-Type': 'application/json'}}) {headers: {'Content-Type': 'application/json'}})
.then(function (result) { .then(function (result) {
@@ -90,11 +87,22 @@ class ExecuteQuery {
self.sqlServerObject._highlight_error(httpMessageData.data.result); self.sqlServerObject._highlight_error(httpMessageData.data.result);
} }
}).catch(function (error) { }).catch(function (error) {
self.onExecuteHTTPError(error.response.data); self.onExecuteHTTPError(error);
} }
); );
} }
generateURLReconnectionFlag(shouldReconnect) {
let url = url_for('sqleditor.query_tool_start', {
'trans_id': this.sqlServerObject.transId,
});
if (shouldReconnect) {
url += '?connect=1';
}
return url;
}
poll() { poll() {
const self = this; const self = this;
let service = axios.create({}); let service = axios.create({});
@@ -129,18 +137,21 @@ class ExecuteQuery {
} }
).catch( ).catch(
error => { error => {
const errorData = error.response.data;
// Enable/Disable query tool button only if is_query_tool is true. // Enable/Disable query tool button only if is_query_tool is true.
self.sqlServerObject.resetQueryHistoryObject(self.sqlServerObject); self.sqlServerObject.resetQueryHistoryObject(self.sqlServerObject);
self.loadingScreen.hide(); self.loadingScreen.hide();
if (self.sqlServerObject.is_query_tool) { if (self.sqlServerObject.is_query_tool) {
self.enableSQLEditorButtons(); self.enableSQLEditorButtons();
} }
if (ExecuteQuery.wasConnectionLostToServer(errorData)) { if (ExecuteQuery.wasConnectionLostToPythonServer(error.response)) {
self.handleConnectionToServerLost(); self.handleConnectionToServerLost();
return; return;
} }
const errorData = error.response.data;
if (self.userManagement.is_pga_login_required(errorData)) { if (self.userManagement.is_pga_login_required(errorData)) {
return self.userManagement.pga_login(); return self.userManagement.pga_login();
} }
@@ -182,39 +193,36 @@ class ExecuteQuery {
this.loadingScreen.hide(); this.loadingScreen.hide();
this.enableSQLEditorButtons(); this.enableSQLEditorButtons();
if (ExecuteQuery.wasConnectionLostToServer(httpMessage)) { if (ExecuteQuery.wasConnectionLostToPythonServer(httpMessage.response)) {
this.handleConnectionToServerLost(); this.handleConnectionToServerLost();
return; return;
} }
if (this.userManagement.is_pga_login_required(httpMessage)) { if (this.userManagement.is_pga_login_required(httpMessage.response)) {
this.sqlServerObject.save_state('execute', [this.explainPlan]); this.sqlServerObject.save_state('execute', [this.explainPlan]);
this.userManagement.pga_login(); this.userManagement.pga_login();
} }
if (transaction.is_new_transaction_required(httpMessage)) { if (transaction.is_new_transaction_required(httpMessage.response)) {
this.sqlServerObject.save_state('execute', [this.explainPlan]); this.sqlServerObject.save_state('execute', [this.explainPlan]);
this.sqlServerObject.init_transaction(); this.sqlServerObject.init_transaction();
} }
let msg = httpMessage.errormsg; if (this.wasDatabaseConnectionLost(httpMessage)) {
if (httpMessage.responseJSON !== undefined) {
if (httpMessage.responseJSON.errormsg !== undefined) {
msg = httpMessage.responseJSON.errormsg;
}
if (httpMessage.status === 503 && httpMessage.responseJSON.info !== undefined &&
httpMessage.responseJSON.info === 'CONNECTION_LOST') {
setTimeout(function () {
this.sqlServerObject.save_state('execute', [this.explainPlan]); this.sqlServerObject.save_state('execute', [this.explainPlan]);
this.sqlServerObject.handle_connection_lost(false, httpMessage); this.sqlServerObject.handle_connection_lost(false, httpMessage);
});
}
} }
let msg = httpMessage.response.data.errormsg;
this.sqlServerObject.update_msg_history(false, msg); this.sqlServerObject.update_msg_history(false, msg);
} }
wasDatabaseConnectionLost(httpMessage) {
return httpMessage.response.status === 503 &&
httpMessage.response.data.info !== undefined &&
httpMessage.response.data.info === 'CONNECTION_LOST';
}
removeGridViewMarker() { removeGridViewMarker() {
if (this.sqlServerObject.gridView.marker) { if (this.sqlServerObject.gridView.marker) {
this.sqlServerObject.gridView.marker.clear(); this.sqlServerObject.gridView.marker.clear();
@@ -236,8 +244,8 @@ class ExecuteQuery {
$('#btn-cancel-query').prop('disabled', false); $('#btn-cancel-query').prop('disabled', false);
} }
static wasConnectionLostToServer(errorMessage) { static wasConnectionLostToPythonServer(httpResponse) {
return errorMessage.readyState === 0; return _.isUndefined(httpResponse) || _.isUndefined(httpResponse.data);
} }
handleConnectionToServerLost() { handleConnectionToServerLost() {
@@ -8,6 +8,15 @@
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
export function is_new_transaction_required(xhr) { export function is_new_transaction_required(xhr) {
/* If responseJSON is undefined then it could be object of
* axios(Promise HTTP) response, so we should check accordingly.
*/
if (xhr.responseJSON === undefined && xhr.data !== undefined) {
return xhr.status === 404 && xhr.data &&
xhr.data.info &&
xhr.data.info === 'DATAGRID_TRANSACTION_REQUIRED';
}
return xhr.status === 404 && xhr.responseJSON && return xhr.status === 404 && xhr.responseJSON &&
xhr.responseJSON.info && xhr.responseJSON.info &&
xhr.responseJSON.info === 'DATAGRID_TRANSACTION_REQUIRED'; xhr.responseJSON.info === 'DATAGRID_TRANSACTION_REQUIRED';
+3 -1
View File
@@ -298,8 +298,10 @@ def start_query_tool(trans_id):
request.data, request.args, request.form request.data, request.args, request.form
) )
connect = 'connect' in request.args and request.args['connect'] == '1'
return StartRunningQuery(blueprint, current_app).execute( return StartRunningQuery(blueprint, current_app).execute(
sql, trans_id, session sql, trans_id, session, connect
) )
@@ -1847,13 +1847,21 @@ define('tools.querytool', [
}, },
handle_connection_lost: function(create_transaction, xhr) { handle_connection_lost: function(create_transaction, xhr) {
var self= this; /* If responseJSON is undefined then it could be object of
if (xhr.responseJSON.data && !xhr.responseJSON.data.conn_id) { * axios(Promise HTTP) response, so we should check accordingly.
*/
if (xhr.responseJSON !== undefined &&
xhr.responseJSON.data && !xhr.responseJSON.data.conn_id) {
// if conn_id is null then this is maintenance db. // if conn_id is null then this is maintenance db.
// so attempt connection connect without prompt. // so attempt connection connect without prompt.
self.init_connection(create_transaction); this.init_connection(create_transaction);
} else if (xhr.data !== undefined &&
xhr.data.data && !xhr.data.data.conn_id) {
// if conn_id is null then this is maintenance db.
// so attempt connection connect without prompt.
this.init_connection(create_transaction);
} else { } else {
self.warn_before_continue(); this.warn_before_continue();
} }
}, },
warn_before_continue: function() { warn_before_continue: function() {
@@ -3730,7 +3738,7 @@ define('tools.querytool', [
// This function will fetch the sql query from the text box // This function will fetch the sql query from the text box
// and execute the query. // and execute the query.
execute: function(explain_prefix) { execute: function(explain_prefix, shouldReconnect=false) {
var self = this, var self = this,
sql = ''; sql = '';
@@ -3747,7 +3755,7 @@ define('tools.querytool', [
sql = self.gridView.query_tool_obj.getValue(); sql = self.gridView.query_tool_obj.getValue();
const executeQuery = new ExecuteQuery.ExecuteQuery(this, pgAdmin.Browser.UserManagement); const executeQuery = new ExecuteQuery.ExecuteQuery(this, pgAdmin.Browser.UserManagement);
executeQuery.execute(sql, explain_prefix); executeQuery.execute(sql, explain_prefix, shouldReconnect);
}, },
/* This function is used to highlight the error line and /* This function is used to highlight the error line and
@@ -42,6 +42,6 @@ class StartQueryTool(BaseTestGenerator):
self.assertEquals(response.status, '200 OK') self.assertEquals(response.status, '200 OK')
self.assertEquals(response.data, b'some result') self.assertEquals(response.data, b'some result')
StartRunningQuery_execute_mock \ StartRunningQuery_execute_mock \
.assert_called_with('transformed sql', 1234, ANY) .assert_called_with('transformed sql', 1234, ANY, False)
extract_sql_from_network_parameters_mock \ extract_sql_from_network_parameters_mock \
.assert_called_with(b'"some sql statement"', ANY, ANY) .assert_called_with(b'"some sql statement"', ANY, ANY)
@@ -36,7 +36,7 @@ class StartRunningQuery:
self.connection_id = str(random.randint(1, 9999999)) self.connection_id = str(random.randint(1, 9999999))
self.logger = logger self.logger = logger
def execute(self, sql, trans_id, http_session): def execute(self, sql, trans_id, http_session, connect=False):
session_obj = StartRunningQuery.retrieve_session_information( session_obj = StartRunningQuery.retrieve_session_information(
http_session, http_session,
trans_id trans_id
@@ -68,7 +68,7 @@ class StartRunningQuery:
return internal_server_error(errormsg=str(e)) return internal_server_error(errormsg=str(e))
# Connect to the Server if not connected. # Connect to the Server if not connected.
if not conn.connected(): if connect and not conn.connected():
status, msg = conn.connect() status, msg = conn.connect()
if not status: if not status:
self.logger.error(msg) self.logger.error(msg)
@@ -108,7 +108,6 @@ class StartRunningQuery:
self.connection_id = conn_id self.connection_id = conn_id
def __execute_query(self, conn, session_obj, sql, trans_id, trans_obj): def __execute_query(self, conn, session_obj, sql, trans_id, trans_obj):
if conn.connected():
# on successful connection set the connection id to the # on successful connection set the connection id to the
# transaction object # transaction object
trans_obj.set_connection_id(self.connection_id) trans_obj.set_connection_id(self.connection_id)
@@ -136,11 +135,7 @@ class StartRunningQuery:
if StartRunningQuery.is_rollback_statement_required(trans_obj, if StartRunningQuery.is_rollback_statement_required(trans_obj,
conn): conn):
conn.execute_void("ROLLBACK;") conn.execute_void("ROLLBACK;")
else:
status = False
result = gettext(
'Not connected to server or connection with the server has '
'been closed.')
return result, status return result, status
@staticmethod @staticmethod
@@ -21,6 +21,7 @@ else:
from unittest.mock import patch, MagicMock from unittest.mock import patch, MagicMock
get_driver_exception = Exception('get_driver exception') get_driver_exception = Exception('get_driver exception')
get_connection_lost_exception = Exception('Unable to connect to server')
class StartRunningQueryTest(BaseTestGenerator): class StartRunningQueryTest(BaseTestGenerator):
@@ -38,6 +39,7 @@ class StartRunningQueryTest(BaseTestGenerator):
), ),
pickle_load_return=None, pickle_load_return=None,
get_driver_exception=False, get_driver_exception=False,
get_connection_lost_exception=False,
manager_connection_exception=None, manager_connection_exception=None,
is_connected_to_server=False, is_connected_to_server=False,
@@ -67,6 +69,7 @@ class StartRunningQueryTest(BaseTestGenerator):
), ),
pickle_load_return=None, pickle_load_return=None,
get_driver_exception=False, get_driver_exception=False,
get_connection_lost_exception=False,
manager_connection_exception=None, manager_connection_exception=None,
is_connected_to_server=False, is_connected_to_server=False,
@@ -97,6 +100,7 @@ class StartRunningQueryTest(BaseTestGenerator):
), ),
pickle_load_return=None, pickle_load_return=None,
get_driver_exception=False, get_driver_exception=False,
get_connection_lost_exception=False,
manager_connection_exception=None, manager_connection_exception=None,
is_connected_to_server=False, is_connected_to_server=False,
@@ -131,6 +135,7 @@ class StartRunningQueryTest(BaseTestGenerator):
pickle_load_return=MagicMock(conn_id=1, pickle_load_return=MagicMock(conn_id=1,
update_fetched_row_cnt=MagicMock()), update_fetched_row_cnt=MagicMock()),
get_driver_exception=True, get_driver_exception=True,
get_connection_lost_exception=False,
manager_connection_exception=None, manager_connection_exception=None,
is_connected_to_server=False, is_connected_to_server=False,
@@ -161,6 +166,7 @@ class StartRunningQueryTest(BaseTestGenerator):
update_fetched_row_cnt=MagicMock() update_fetched_row_cnt=MagicMock()
), ),
get_driver_exception=False, get_driver_exception=False,
get_connection_lost_exception=False,
manager_connection_exception=ConnectionLost('1', '2', '3'), manager_connection_exception=ConnectionLost('1', '2', '3'),
is_connected_to_server=False, is_connected_to_server=False,
@@ -188,6 +194,7 @@ class StartRunningQueryTest(BaseTestGenerator):
update_fetched_row_cnt=MagicMock() update_fetched_row_cnt=MagicMock()
), ),
get_driver_exception=False, get_driver_exception=False,
get_connection_lost_exception=True,
manager_connection_exception=None, manager_connection_exception=None,
is_connected_to_server=False, is_connected_to_server=False,
@@ -202,7 +209,7 @@ class StartRunningQueryTest(BaseTestGenerator):
expect_internal_server_error_called_with=dict( expect_internal_server_error_called_with=dict(
errormsg='Unable to connect to server' errormsg='Unable to connect to server'
), ),
expected_logger_error='Unable to connect to server', expected_logger_error=get_connection_lost_exception,
expect_execute_void_called_with='some sql', expect_execute_void_called_with='some sql',
)), )),
('When server is connected and start query async request, ' ('When server is connected and start query async request, '
@@ -223,6 +230,7 @@ class StartRunningQueryTest(BaseTestGenerator):
can_filter=lambda: True can_filter=lambda: True
), ),
get_driver_exception=False, get_driver_exception=False,
get_connection_lost_exception=False,
manager_connection_exception=None, manager_connection_exception=None,
is_connected_to_server=True, is_connected_to_server=True,
@@ -265,6 +273,7 @@ class StartRunningQueryTest(BaseTestGenerator):
can_filter=lambda: True can_filter=lambda: True
), ),
get_driver_exception=False, get_driver_exception=False,
get_connection_lost_exception=False,
manager_connection_exception=None, manager_connection_exception=None,
is_connected_to_server=True, is_connected_to_server=True,
@@ -307,6 +316,7 @@ class StartRunningQueryTest(BaseTestGenerator):
can_filter=lambda: True can_filter=lambda: True
), ),
get_driver_exception=False, get_driver_exception=False,
get_connection_lost_exception=False,
manager_connection_exception=None, manager_connection_exception=None,
is_connected_to_server=True, is_connected_to_server=True,
@@ -349,6 +359,7 @@ class StartRunningQueryTest(BaseTestGenerator):
can_filter=lambda: True can_filter=lambda: True
), ),
get_driver_exception=False, get_driver_exception=False,
get_connection_lost_exception=False,
manager_connection_exception=None, manager_connection_exception=None,
is_connected_to_server=True, is_connected_to_server=True,
@@ -431,6 +442,8 @@ class StartRunningQueryTest(BaseTestGenerator):
manager = self.__create_manager() manager = self.__create_manager()
if self.get_driver_exception: if self.get_driver_exception:
get_driver_mock.side_effect = get_driver_exception get_driver_mock.side_effect = get_driver_exception
elif self.get_connection_lost_exception:
get_driver_mock.side_effect = get_connection_lost_exception
else: else:
get_driver_mock.return_value = MagicMock( get_driver_mock.return_value = MagicMock(
connection_manager=lambda session_id: manager) connection_manager=lambda session_id: manager)
@@ -130,9 +130,18 @@ define([
}, },
is_pga_login_required(xhr) { is_pga_login_required(xhr) {
return xhr.status == 401 && xhr.responseJSON && /* If responseJSON is undefined then it could be object of
* axios(Promise HTTP) response, so we should check accordingly.
*/
if (xhr.responseJSON === undefined && xhr.data !== undefined) {
return xhr.status === 401 && xhr.data &&
xhr.data.info &&
xhr.data.info === 'PGADMIN_LOGIN_REQUIRED';
}
return xhr.status === 401 && xhr.responseJSON &&
xhr.responseJSON.info && xhr.responseJSON.info &&
xhr.responseJSON.info == 'PGADMIN_LOGIN_REQUIRED'; xhr.responseJSON.info === 'PGADMIN_LOGIN_REQUIRED';
}, },
// Callback to draw pgAdmin4 login dialog. // Callback to draw pgAdmin4 login dialog.
@@ -19,6 +19,7 @@ from flask_babel import gettext
from pgadmin.utils.crypto import decrypt from pgadmin.utils.crypto import decrypt
from .connection import Connection from .connection import Connection
from pgadmin.model import Server from pgadmin.model import Server
from pgadmin.utils.exception import ConnectionLost
class ServerManager(object): class ServerManager(object):
@@ -42,6 +42,7 @@ describe('ExecuteQuery', () => {
'_init_polling_flags', '_init_polling_flags',
'save_state', 'save_state',
'init_transaction', 'init_transaction',
'handle_connection_lost',
]); ]);
sqlEditorMock.transId = 123; sqlEditorMock.transId = 123;
sqlEditorMock.rows_affected = 1000; sqlEditorMock.rows_affected = 1000;
@@ -49,6 +50,10 @@ describe('ExecuteQuery', () => {
isNewTransactionRequiredMock = spyOn(transaction, 'is_new_transaction_required'); isNewTransactionRequiredMock = spyOn(transaction, 'is_new_transaction_required');
}); });
afterEach(() => {
networkMock.restore();
});
describe('#poll', () => { describe('#poll', () => {
let cancelButtonSpy; let cancelButtonSpy;
let response; let response;
@@ -62,9 +67,6 @@ describe('ExecuteQuery', () => {
executeQuery.delayedPoll = jasmine.createSpy('ExecuteQuery.delayedPoll'); executeQuery.delayedPoll = jasmine.createSpy('ExecuteQuery.delayedPoll');
}); });
afterEach(() => {
});
context('when SQLEditor is the query tool', () => { context('when SQLEditor is the query tool', () => {
beforeEach(() => { beforeEach(() => {
sqlEditorMock.is_query_tool = true; sqlEditorMock.is_query_tool = true;
@@ -569,8 +571,7 @@ describe('ExecuteQuery', () => {
describe('when cannot reach the Python Server', () => { describe('when cannot reach the Python Server', () => {
beforeEach(() => { beforeEach(() => {
response = {readyState: 0}; networkMock.onGet('/sqleditor/query_tool/poll/123').reply(404, undefined);
networkMock.onGet('/sqleditor/query_tool/poll/123').reply(401, response);
executeQuery.poll(); executeQuery.poll();
}); });
@@ -972,8 +973,7 @@ describe('ExecuteQuery', () => {
describe('when cannot reach the Python Server', () => { describe('when cannot reach the Python Server', () => {
beforeEach(() => { beforeEach(() => {
response = {readyState: 0}; networkMock.onGet('/sqleditor/query_tool/poll/123').reply(404, undefined);
networkMock.onGet('/sqleditor/query_tool/poll/123').reply(401, response);
executeQuery.poll(); executeQuery.poll();
}); });
@@ -1143,9 +1143,9 @@ describe('ExecuteQuery', () => {
describe('when HTTP return 200', () => { describe('when HTTP return 200', () => {
describe('when backend informs that query started successfully', () => { describe('when backend informs that query started successfully', () => {
beforeEach(() => { beforeEach(() => {
networkMock.onAny('/sqleditor/query_tool/start/123').reply(200, response); networkMock.onPost('/sqleditor/query_tool/start/123?connect=1').reply(200, response);
pollSpy = spyOn(executeQuery, 'delayedPoll'); pollSpy = spyOn(executeQuery, 'delayedPoll');
executeQuery.execute('some sql query', ''); executeQuery.execute('some sql query', '', true);
}); });
it('should changes the loading message to "Waiting for the query execution to complete"', (done) => { it('should changes the loading message to "Waiting for the query execution to complete"', (done) => {
@@ -1310,10 +1310,7 @@ describe('ExecuteQuery', () => {
describe('when cannot reach the Python Server', () => { describe('when cannot reach the Python Server', () => {
beforeEach(() => { beforeEach(() => {
response = { networkMock.onAny('/sqleditor/query_tool/start/123').reply(500, undefined);
readyState: 0,
};
networkMock.onAny('/sqleditor/query_tool/start/123').reply(500, response);
executeQuery.execute('some sql query', ''); executeQuery.execute('some sql query', '');
@@ -1657,7 +1654,32 @@ describe('ExecuteQuery', () => {
}, 0); }, 0);
}); });
}); });
describe('when connection to database is lost', () => {
beforeEach(() => {
isNewTransactionRequiredMock.and.returnValue(false);
response.info = 'CONNECTION_LOST';
networkMock.onAny('/sqleditor/query_tool/start/123').reply(503, response);
executeQuery.execute('some sql query', '');
}); });
it('saves state', () => {
setTimeout(() => {
expect(sqlEditorMock.save_state).toHaveBeenCalledWith(
'execute',
['']
);
}, 0);
});
it('calls handle_connection_lost', () => {
setTimeout(() => {
expect(sqlEditorMock.handle_connection_lost).toHaveBeenCalled();
}, 0);
});
});
});
}); });
}); });
@@ -19,7 +19,7 @@ describe('#is_new_transaction_required', () => {
}); });
describe('when status is 404', () => { describe('when status is 404', () => {
describe('when responseJSON is not present', () => { describe('when data is not present', () => {
it('should return false', () => { it('should return false', () => {
expect(is_new_transaction_required({ expect(is_new_transaction_required({
status: 404, status: 404,
@@ -27,22 +27,22 @@ describe('#is_new_transaction_required', () => {
}); });
}); });
describe('when responseJSON is present', () => { describe('when data is present', () => {
describe('when info is not present inside responseJSON', () => { describe('when info is not present inside data', () => {
it('should return false', () => { it('should return false', () => {
expect(is_new_transaction_required({ expect(is_new_transaction_required({
status: 404, status: 404,
responseJSON: {}, data: {},
})).toBeFalsy(); })).toBeFalsy();
}); });
}); });
describe('when info is present inside responseJSON', () => { describe('when info is present inside data', () => {
describe('when info value is not "DATAGRID_TRANSACTION_REQUIRED"', () => { describe('when info value is not "DATAGRID_TRANSACTION_REQUIRED"', () => {
it('should return false', () => { it('should return false', () => {
expect(is_new_transaction_required({ expect(is_new_transaction_required({
status: 404, status: 404,
responseJSON: { data: {
info: 'some information', info: 'some information',
}, },
})).toBe(false); })).toBe(false);
@@ -53,7 +53,7 @@ describe('#is_new_transaction_required', () => {
it('should return false', () => { it('should return false', () => {
expect(is_new_transaction_required({ expect(is_new_transaction_required({
status: 404, status: 404,
responseJSON: { data: {
info: 'DATAGRID_TRANSACTION_REQUIRED', info: 'DATAGRID_TRANSACTION_REQUIRED',
}, },
})).toBe(true); })).toBe(true);