Refactor keyboard shortcut functions in the query tool. Fix some incorrect keycodes and update docs.

Initial work by Sarah & Violet @ Pivotal, with additional tweaks by Murtuza @ EDB.
This commit is contained in:
Sarah McAlear 2017-08-21 15:27:29 +01:00 committed by Dave Page
parent 2e2ca26020
commit b585063a26
8 changed files with 3977 additions and 3488 deletions

View File

@ -41,11 +41,11 @@ When using the syntax-highlighting SQL editors, the following shortcuts are avai
+--------------------------+------------------+-------------------------------------+
| Ctrl+Alt+Right | Cmd+Option+Right | Move right one word |
+--------------------------+------------------+-------------------------------------+
| Ctrl+Shift+/ | Cmd+Shift+/ | Comment selected code (Inline) |
| Ctrl+/ | Cmd+/ | Comment selected code (Inline) |
+--------------------------+------------------+-------------------------------------+
| Ctrl+Shift+. | Cmd+Shift+. | Uncomment selected code (Inline) |
| Ctrl+. | Cmd+. | Uncomment selected code (Inline) |
+--------------------------+------------------+-------------------------------------+
| Ctrl+/ | Cmd+/ | Comment/Uncomment code (Block) |
| Ctrl+Shift+/ | Cmd+Shift+/ | Comment/Uncomment code (Block) |
+--------------------------+------------------+-------------------------------------+
| Ctrl+A | Cmd+A | Select all |
+--------------------------+------------------+-------------------------------------+

View File

@ -2,10 +2,9 @@ const F5_KEY = 116,
F7_KEY = 118,
F8_KEY = 119,
PERIOD_KEY = 190,
FWD_SLASH_KEY = 191,
IS_CMD_KEY = window.navigator.platform.search('Mac') != -1;
FWD_SLASH_KEY = 191;
function keyboardShortcuts(sqlEditorController, event) {
function keyboardShortcuts(sqlEditorController, queryToolActions, event) {
if (sqlEditorController.isQueryRunning()) {
return;
}
@ -14,28 +13,28 @@ function keyboardShortcuts(sqlEditorController, event) {
if (keyCode === F5_KEY) {
event.preventDefault();
sqlEditorController.executeQuery();
queryToolActions.executeQuery(sqlEditorController);
} else if (event.shiftKey && keyCode === F7_KEY) {
_stopEventPropagation();
sqlEditorController.explainAnalyze(event);
queryToolActions.explainAnalyze(sqlEditorController);
} else if (keyCode === F7_KEY) {
_stopEventPropagation();
sqlEditorController.explain(event);
queryToolActions.explain(sqlEditorController);
} else if (keyCode === F8_KEY) {
event.preventDefault();
sqlEditorController.download();
} else if (((IS_CMD_KEY && event.metaKey) || (!IS_CMD_KEY && event.ctrlKey)) &&
event.shiftKey && keyCode === FWD_SLASH_KEY) {
queryToolActions.download(sqlEditorController);
} else if (((this.isMac() && event.metaKey) || (!this.isMac() && event.ctrlKey)) &&
event.shiftKey && keyCode === FWD_SLASH_KEY) {
_stopEventPropagation();
sqlEditorController.commentLineCode();
} else if (((IS_CMD_KEY && event.metaKey) || (!IS_CMD_KEY && event.ctrlKey)) &&
event.shiftKey && keyCode === PERIOD_KEY) {
queryToolActions.commentBlockCode(sqlEditorController);
} else if (((this.isMac() && event.metaKey) || (!this.isMac() && event.ctrlKey)) &&
keyCode === FWD_SLASH_KEY) {
_stopEventPropagation();
sqlEditorController.uncommentLineCode();
} else if (((IS_CMD_KEY && event.metaKey) || (!IS_CMD_KEY && event.ctrlKey)) &&
keyCode === FWD_SLASH_KEY) {
queryToolActions.commentLineCode(sqlEditorController);
} else if (((this.isMac() && event.metaKey) || (!this.isMac() && event.ctrlKey)) &&
keyCode === PERIOD_KEY) {
_stopEventPropagation();
sqlEditorController.commentBlockCode();
queryToolActions.uncommentLineCode(sqlEditorController);
}
function _stopEventPropagation() {
@ -46,6 +45,11 @@ function keyboardShortcuts(sqlEditorController, event) {
}
}
function isMac() {
return window.navigator.platform.search('Mac') != -1;
}
module.exports = {
processEvent: keyboardShortcuts,
isMac: isMac,
};

View File

@ -0,0 +1,99 @@
import $ from 'jquery';
let queryToolActions = {
_verbose: function () {
return $('.explain-verbose').hasClass('visibility-hidden') ? 'OFF' : 'ON';
},
_costsEnabled: function () {
return $('.explain-costs').hasClass('visibility-hidden') ? 'OFF' : 'ON';
},
_buffers: function () {
return $('.explain-buffers').hasClass('visibility-hidden') ? 'OFF' : 'ON';
},
_timing: function () {
return $('.explain-timing').hasClass('visibility-hidden') ? 'OFF' : 'ON';
},
_clearMessageTab: function () {
$('.sql-editor-message').html('');
},
executeQuery: function (sqlEditorController) {
if(sqlEditorController.is_query_tool) {
this._clearMessageTab();
sqlEditorController.execute();
} else {
sqlEditorController.execute_data_query();
}
},
explainAnalyze: function (sqlEditorController) {
let costEnabled = this._costsEnabled();
let verbose = this._verbose();
let buffers = this._buffers();
let timing = this._timing();
let explainAnalyzeQuery = `EXPLAIN (FORMAT JSON, ANALYZE ON, VERBOSE ${verbose}, COSTS ${costEnabled}, BUFFERS ${buffers}, TIMING ${timing}) `;
sqlEditorController.execute(explainAnalyzeQuery);
},
explain: function (sqlEditorController) {
let costEnabled = this._costsEnabled();
let verbose = this._verbose();
let explainQuery = `EXPLAIN (FORMAT JSON, ANALYZE OFF, VERBOSE ${verbose}, COSTS ${costEnabled}, BUFFERS OFF, TIMING OFF) `;
sqlEditorController.execute(explainQuery);
},
download: function (sqlEditorController) {
let sqlQuery = sqlEditorController.gridView.query_tool_obj.getSelection();
if (!sqlQuery) {
sqlQuery = sqlEditorController.gridView.query_tool_obj.getValue();
}
if (!sqlQuery) return;
let filename = 'data-' + new Date().getTime() + '.csv';
if (!sqlEditorController.is_query_tool) {
filename = sqlEditorController.table_name + '.csv';
}
sqlEditorController.trigger_csv_download(sqlQuery, filename);
},
commentBlockCode: function (sqlEditorController) {
let codeMirrorObj = sqlEditorController.gridView.query_tool_obj;
if (!codeMirrorObj.getValue()) return;
codeMirrorObj.toggleComment(codeMirrorObj.getCursor(true), codeMirrorObj.getCursor(false));
},
commentLineCode: function (sqlEditorController) {
let codeMirrorObj = sqlEditorController.gridView.query_tool_obj;
if (!codeMirrorObj.getValue()) return;
codeMirrorObj.lineComment(codeMirrorObj.getCursor(true),
codeMirrorObj.getCursor(false),
{lineComment: '--'}
);
},
uncommentLineCode: function (sqlEditorController) {
let codeMirrorObj = sqlEditorController.gridView.query_tool_obj;
if (!codeMirrorObj.getValue()) return;
codeMirrorObj.uncomment(codeMirrorObj.getCursor(true),
codeMirrorObj.getCursor(false),
{lineComment: '--'}
);
},
};
module.exports = queryToolActions;

View File

@ -217,7 +217,7 @@ def panel(trans_id, is_query_tool, editor_title):
is_desktop_mode=app.PGADMIN_RUNTIME,
is_linux=is_linux_platform,
is_new_browser_tab=new_browser_tab,
client_plaform=user_agent.platform
client_platform=user_agent.platform
)

View File

@ -58,7 +58,7 @@
<ul class="dropdown-menu">
<li>
<a id="btn-find-menu-find" href="#">
<span> {{ _('Find') }}{% if client_plaform == 'macos' -%}
<span> {{ _('Find') }}{% if client_platform == 'macos' -%}
{{ _(' (Cmd+F)') }}
{% else %}
{{ _(' (Ctrl+F)') }}{%- endif %}</span>
@ -66,7 +66,7 @@
</li>
<li>
<a id="btn-find-menu-find-next" href="#">
<span> {{ _('Find next') }}{% if client_plaform == 'macos' -%}
<span> {{ _('Find next') }}{% if client_platform == 'macos' -%}
{{ _(' (Cmd+G)') }}
{% else %}
{{ _(' (Ctrl+G)') }}{%- endif %}</span>
@ -74,7 +74,7 @@
</li>
<li>
<a id="btn-find-menu-find-previous" href="#">
<span> {{ _('Find previous') }}{% if client_plaform == 'macos' -%}
<span> {{ _('Find previous') }}{% if client_platform == 'macos' -%}
{{ _(' (Cmd+Shift+G)') }}
{% else %}
{{ _(' (Ctrl+Shift+G)') }}{%- endif %}</span>
@ -88,7 +88,7 @@
<li class="divider"></li>
<li>
<a id="btn-find-menu-replace" href="#">
<span> {{ _('Replace') }}{% if client_plaform == 'macos' -%}
<span> {{ _('Replace') }}{% if client_platform == 'macos' -%}
{{ _(' (Cmd+Shift+F)') }}
{% else %}
{{ _(' (Ctrl+Shift+F)') }}{%- endif %}</span>
@ -139,23 +139,23 @@
<span> {{ _('Unindent Selection (Shift+Tab)') }} </span>
</a>
<a id="btn-comment-line" href="#">
<span> {{ _('Inline Comment Selection') }}{% if client_plaform == 'macos' -%}
{{ _(' (Cmd+Shift+/)') }}
{% else %}
{{ _(' (Ctrl+Shift+/)') }}{%- endif %}</span>
</a>
<a id="btn-uncomment-line" href="#">
<span> {{ _('Inline Uncomment Selection') }}{% if client_plaform == 'macos' -%}
{{ _(' (Cmd+Shift+.)') }}
{% else %}
{{ _(' (Ctrl+Shift+.)') }}{%- endif %}</span>
</a>
<a id="btn-toggle-comment-block" href="#">
<span> {{ _('Block Comment/Uncomment Selection') }}{% if client_plaform == 'macos' -%}
<span> {{ _('Inline Comment Selection') }}{% if client_platform == 'macos' -%}
{{ _(' (Cmd+/)') }}
{% else %}
{{ _(' (Ctrl+/)') }}{%- endif %}</span>
</a>
<a id="btn-uncomment-line" href="#">
<span> {{ _('Inline Uncomment Selection') }}{% if client_platform == 'macos' -%}
{{ _(' (Cmd+.)') }}
{% else %}
{{ _(' (Ctrl+.)') }}{%- endif %}</span>
</a>
<a id="btn-toggle-comment-block" href="#">
<span> {{ _('Block Comment/Uncomment Selection') }}{% if client_platform == 'macos' -%}
{{ _(' (Shift+Cmd+/)') }}
{% else %}
{{ _(' (Shift+Ctrl+/)') }}{%- endif %}</span>
</a>
</li>
</ul>
</div>

File diff suppressed because it is too large Load Diff

View File

@ -8,6 +8,7 @@
//////////////////////////////////////////////////////////////////////////
import keyboardShortcuts from 'sources/sqleditor/keyboard_shortcuts';
import {queryToolActions} from 'sources/sqleditor/query_tool_actions';
describe('the keyboard shortcuts', () => {
const F1_KEY = 112,
@ -15,11 +16,9 @@ describe('the keyboard shortcuts', () => {
F7_KEY = 118,
F8_KEY = 119,
PERIOD_KEY = 190,
FWD_SLASH_KEY = 191,
isMacSystem = window.navigator.platform.search('Mac') != -1;
FWD_SLASH_KEY = 191;
let sqlEditorControllerSpy;
let event;
let sqlEditorControllerSpy, event, queryToolActionsSpy;
beforeEach(() => {
event = {
shift: false,
@ -30,15 +29,27 @@ describe('the keyboard shortcuts', () => {
stopImmediatePropagation: jasmine.createSpy('stopImmediatePropagation'),
};
let gridView = {
query_tool_obj: {
getSelection: jasmine.createSpy('getSelection'),
getValue: jasmine.createSpy('getValue'),
},
};
sqlEditorControllerSpy = jasmine.createSpyObj('SqlEditorController', [
'isQueryRunning',
'download',
'explain',
'execute',
]);
sqlEditorControllerSpy.gridView = gridView;
queryToolActionsSpy = jasmine.createSpyObj(queryToolActions, [
'explainAnalyze',
'executeQuery',
'explain',
'download',
'commentBlockCode',
'commentLineCode',
'uncommentLineCode',
'commentBlockCode',
'executeQuery',
]);
});
@ -46,7 +57,7 @@ describe('the keyboard shortcuts', () => {
beforeEach(() => {
event.which = F1_KEY;
keyboardShortcuts.processEvent(sqlEditorControllerSpy, event);
keyboardShortcuts.processEvent(sqlEditorControllerSpy, queryToolActionsSpy, event);
});
it('should allow event to propagate', () => {
@ -58,11 +69,11 @@ describe('the keyboard shortcuts', () => {
describe('when there is no query already running', () => {
beforeEach(() => {
event.keyCode = F5_KEY;
keyboardShortcuts.processEvent(sqlEditorControllerSpy, event);
keyboardShortcuts.processEvent(sqlEditorControllerSpy, queryToolActionsSpy, event);
});
it('should execute the query', () => {
expect(sqlEditorControllerSpy.executeQuery).toHaveBeenCalled();
expect(queryToolActionsSpy.executeQuery).toHaveBeenCalledWith(sqlEditorControllerSpy);
});
it('should stop event propagation', () => {
@ -75,9 +86,9 @@ describe('the keyboard shortcuts', () => {
event.keyCode = F5_KEY;
sqlEditorControllerSpy.isQueryRunning.and.returnValue(true);
keyboardShortcuts.processEvent(sqlEditorControllerSpy, event);
keyboardShortcuts.processEvent(sqlEditorControllerSpy, queryToolActionsSpy, event);
expect(sqlEditorControllerSpy.executeQuery).not.toHaveBeenCalled();
expect(queryToolActionsSpy.executeQuery).not.toHaveBeenCalled();
});
});
});
@ -86,11 +97,11 @@ describe('the keyboard shortcuts', () => {
describe('when there is not a query already running', () => {
beforeEach(() => {
event.which = F7_KEY;
keyboardShortcuts.processEvent(sqlEditorControllerSpy, event);
keyboardShortcuts.processEvent(sqlEditorControllerSpy, queryToolActionsSpy, event);
});
it('should explain the query plan', () => {
expect(sqlEditorControllerSpy.explain).toHaveBeenCalledWith(event);
expect(queryToolActionsSpy.explain).toHaveBeenCalledWith(sqlEditorControllerSpy);
});
expectEventPropagationToStop();
@ -101,23 +112,23 @@ describe('the keyboard shortcuts', () => {
event.keyCode = F7_KEY;
sqlEditorControllerSpy.isQueryRunning.and.returnValue(true);
keyboardShortcuts.processEvent(sqlEditorControllerSpy, event);
keyboardShortcuts.processEvent(sqlEditorControllerSpy, queryToolActionsSpy, event);
expect(sqlEditorControllerSpy.explain).not.toHaveBeenCalled();
expect(queryToolActionsSpy.explain).not.toHaveBeenCalled();
});
});
});
describe('Shift+F7', () => {
describe('when therre is not a query already running', () => {
describe('when there is not a query already running', () => {
beforeEach(() => {
event.shiftKey = true;
event.which = F7_KEY;
keyboardShortcuts.processEvent(sqlEditorControllerSpy, event);
keyboardShortcuts.processEvent(sqlEditorControllerSpy, queryToolActionsSpy, event);
});
it('should analyze explain the query plan', () => {
expect(sqlEditorControllerSpy.explainAnalyze).toHaveBeenCalledWith(event);
expect(queryToolActionsSpy.explainAnalyze).toHaveBeenCalledWith(sqlEditorControllerSpy);
});
expectEventPropagationToStop();
@ -129,9 +140,9 @@ describe('the keyboard shortcuts', () => {
event.which = F7_KEY;
sqlEditorControllerSpy.isQueryRunning.and.returnValue(true);
keyboardShortcuts.processEvent(sqlEditorControllerSpy, event);
keyboardShortcuts.processEvent(sqlEditorControllerSpy, queryToolActionsSpy, event);
expect(sqlEditorControllerSpy.explainAnalyze).not.toHaveBeenCalled();
expect(queryToolActionsSpy.explainAnalyze).not.toHaveBeenCalled();
});
});
});
@ -140,11 +151,11 @@ describe('the keyboard shortcuts', () => {
describe('when there is not a query already running', () => {
beforeEach(() => {
event.which = F8_KEY;
keyboardShortcuts.processEvent(sqlEditorControllerSpy, event);
keyboardShortcuts.processEvent(sqlEditorControllerSpy, queryToolActionsSpy, event);
});
it('should download the query results as a CSV', () => {
expect(sqlEditorControllerSpy.download).toHaveBeenCalled();
expect(queryToolActionsSpy.download).toHaveBeenCalled();
});
it('should stop event propagation', () => {
@ -157,102 +168,196 @@ describe('the keyboard shortcuts', () => {
event.keyCode = F8_KEY;
sqlEditorControllerSpy.isQueryRunning.and.returnValue(true);
keyboardShortcuts.processEvent(sqlEditorControllerSpy, event);
keyboardShortcuts.processEvent(sqlEditorControllerSpy, queryToolActionsSpy, event);
expect(sqlEditorControllerSpy.download).not.toHaveBeenCalled();
expect(queryToolActionsSpy.download).not.toHaveBeenCalled();
});
});
});
describe('inlineComment', () => {
describe('when there is not a query already running', () => {
beforeEach(() => {
event.metaKey = isMacSystem;
event.shiftKey = true;
event.ctrlKey = !isMacSystem;
event.which = FWD_SLASH_KEY;
keyboardShortcuts.processEvent(sqlEditorControllerSpy, event);
describe('and the system is a Mac', () => {
beforeEach(() => {
macKeysSetup();
event.which = FWD_SLASH_KEY;
keyboardShortcuts.processEvent(sqlEditorControllerSpy, queryToolActionsSpy, event);
});
it('should comment the line', () => {
expect(queryToolActionsSpy.commentLineCode).toHaveBeenCalledWith(sqlEditorControllerSpy);
});
expectEventPropagationToStop();
});
it('should comment the line', () => {
expect(sqlEditorControllerSpy.commentLineCode).toHaveBeenCalled();
});
describe('and the system is Windows', () => {
beforeEach(() => {
windowsKeysSetup();
event.which = FWD_SLASH_KEY;
keyboardShortcuts.processEvent(sqlEditorControllerSpy, queryToolActionsSpy, event);
});
expectEventPropagationToStop();
it('should comment the line', () => {
expect(queryToolActionsSpy.commentLineCode).toHaveBeenCalledWith(sqlEditorControllerSpy);
});
expectEventPropagationToStop();
});
});
describe('when the query is already running', () => {
it('does nothing', () => {
event.shiftKey = isMacSystem;
event.ctrlKey = !isMacSystem;
event.which = FWD_SLASH_KEY;
beforeEach(() => {
sqlEditorControllerSpy.isQueryRunning.and.returnValue(true);
});
describe('and the system is a Mac', () => {
beforeEach(() => {
macKeysSetup();
event.which = FWD_SLASH_KEY;
});
keyboardShortcuts.processEvent(sqlEditorControllerSpy, event);
it('does nothing', () => {
keyboardShortcuts.processEvent(sqlEditorControllerSpy, queryToolActionsSpy, event);
expect(sqlEditorControllerSpy.commentLineCode).not.toHaveBeenCalled();
expect(queryToolActionsSpy.commentLineCode).not.toHaveBeenCalled();
});
});
describe('and the system is a Windows', () => {
beforeEach(() => {
windowsKeysSetup();
event.which = FWD_SLASH_KEY;
});
it('does nothing', () => {
keyboardShortcuts.processEvent(sqlEditorControllerSpy, queryToolActionsSpy, event);
expect(queryToolActionsSpy.commentLineCode).not.toHaveBeenCalled();
});
});
});
});
describe('inlineUncomment', () => {
describe('when there is not a query already running', () => {
beforeEach(() => {
event.metaKey = isMacSystem;
event.shiftKey = true;
event.ctrlKey = !isMacSystem;
event.which = PERIOD_KEY;
keyboardShortcuts.processEvent(sqlEditorControllerSpy, event);
});
describe('and the system is a mac', () => {
beforeEach(() => {
macKeysSetup();
event.which = PERIOD_KEY;
keyboardShortcuts.processEvent(sqlEditorControllerSpy, queryToolActionsSpy, event);
});
it('should uncomment the line', () => {
expect(sqlEditorControllerSpy.uncommentLineCode).toHaveBeenCalled();
});
it('should uncomment the line', () => {
expect(queryToolActionsSpy.uncommentLineCode).toHaveBeenCalledWith(sqlEditorControllerSpy);
});
expectEventPropagationToStop();
expectEventPropagationToStop();
});
describe('and the system is a windows', () => {
beforeEach(() => {
windowsKeysSetup();
event.which = PERIOD_KEY;
keyboardShortcuts.processEvent(sqlEditorControllerSpy, queryToolActionsSpy, event);
});
it('should uncomment the line', () => {
expect(queryToolActionsSpy.uncommentLineCode).toHaveBeenCalledWith(sqlEditorControllerSpy);
});
expectEventPropagationToStop();
});
});
describe('when the query is already running', () => {
it('does nothing', () => {
event.metaKey = isMacSystem;
event.shiftKey = true;
event.ctrlKey = !isMacSystem;
event.which = PERIOD_KEY;
beforeEach(() => {
sqlEditorControllerSpy.isQueryRunning.and.returnValue(true);
});
describe('and the system is a Mac', () => {
beforeEach(() => {
macKeysSetup();
event.which = PERIOD_KEY;
});
keyboardShortcuts.processEvent(sqlEditorControllerSpy, event);
it('does nothing', () => {
keyboardShortcuts.processEvent(sqlEditorControllerSpy, queryToolActionsSpy, event);
expect(queryToolActionsSpy.uncommentLineCode).not.toHaveBeenCalled();
});
});
describe('and the system is a Windows', () => {
beforeEach(() => {
windowsKeysSetup();
event.which = PERIOD_KEY;
});
expect(sqlEditorControllerSpy.uncommentLineCode).not.toHaveBeenCalled();
it('does nothing', () => {
keyboardShortcuts.processEvent(sqlEditorControllerSpy, queryToolActionsSpy, event);
expect(queryToolActionsSpy.uncommentLineCode).not.toHaveBeenCalled();
});
});
});
});
describe('blockComment', () => {
describe('when there is not a query already running', () => {
beforeEach(() => {
event.metaKey = isMacSystem;
event.ctrlKey = !isMacSystem;
event.which = FWD_SLASH_KEY;
keyboardShortcuts.processEvent(sqlEditorControllerSpy, event);
});
describe('and the system is a Mac', () => {
beforeEach(() => {
macKeysSetup();
event.which = FWD_SLASH_KEY;
event.shiftKey = true;
keyboardShortcuts.processEvent(sqlEditorControllerSpy, queryToolActionsSpy, event);
});
it('should comment a block of code', () => {
expect(sqlEditorControllerSpy.commentBlockCode).toHaveBeenCalled();
});
it('should comment out the block selection', () => {
expect(queryToolActionsSpy.commentBlockCode).toHaveBeenCalledWith(sqlEditorControllerSpy);
});
expectEventPropagationToStop();
expectEventPropagationToStop();
});
});
describe('when the query is already running', () => {
it('does nothing', () => {
event.metaKey = isMacSystem;
event.ctrlKey = !isMacSystem;
event.which = FWD_SLASH_KEY;
describe('when there is not a query already running', () => {
describe('and the system is a Windows', () => {
beforeEach(() => {
windowsKeysSetup();
event.which = FWD_SLASH_KEY;
event.shiftKey = true;
keyboardShortcuts.processEvent(sqlEditorControllerSpy, queryToolActionsSpy, event);
});
it('should comment out the block selection', () => {
expect(queryToolActionsSpy.commentBlockCode).toHaveBeenCalledWith(sqlEditorControllerSpy);
});
expectEventPropagationToStop();
});
});
describe('when there is a query already running', () => {
beforeEach(() => {
sqlEditorControllerSpy.isQueryRunning.and.returnValue(true);
keyboardShortcuts.processEvent(sqlEditorControllerSpy, event);
expect(sqlEditorControllerSpy.commentBlockCode).not.toHaveBeenCalled();
});
describe('and the system is a Mac', () => {
beforeEach(() => {
macKeysSetup();
event.which = FWD_SLASH_KEY;
event.shiftKey = true;
keyboardShortcuts.processEvent(sqlEditorControllerSpy, queryToolActionsSpy, event);
});
it('does nothing', () => {
expect(queryToolActionsSpy.commentBlockCode).not.toHaveBeenCalled();
});
});
describe('and the system is a Windows', () => {
beforeEach(() => {
windowsKeysSetup();
event.which = FWD_SLASH_KEY;
event.shiftKey = true;
keyboardShortcuts.processEvent(sqlEditorControllerSpy, queryToolActionsSpy, event);
});
it('does nothing', () => {
expect(queryToolActionsSpy.commentBlockCode).not.toHaveBeenCalled();
});
});
});
});
@ -274,4 +379,16 @@ describe('the keyboard shortcuts', () => {
});
});
}
function windowsKeysSetup() {
spyOn(keyboardShortcuts, 'isMac').and.returnValue(false);
event.ctrlKey = true;
event.metaKey = false;
}
function macKeysSetup() {
spyOn(keyboardShortcuts, 'isMac').and.returnValue(true);
event.ctrlKey = false;
event.metaKey = true;
}
});

View File

@ -0,0 +1,398 @@
//////////////////////////////////////////////////////////////////////////
//
// pgAdmin 4 - PostgreSQL Tools
//
// Copyright (C) 2013 - 2017, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
import queryToolActions from 'sources/sqleditor/query_tool_actions';
describe('queryToolActions', () => {
let sqlEditorController,
getSelectionSpy, getValueSpy,
selectedQueryString, entireQueryString;
describe('executeQuery', () => {
describe('when the command is being run from the query tool', () => {
beforeEach(() => {
setUpSpies('', '');
spyOn(queryToolActions, '_clearMessageTab');
});
it('clears the html in the message tab', () => {
queryToolActions.executeQuery(sqlEditorController);
expect(queryToolActions._clearMessageTab).toHaveBeenCalled();
});
it('calls the execute function on the sqlEditorController', () => {
queryToolActions.executeQuery(sqlEditorController);
expect(sqlEditorController.execute).toHaveBeenCalled();
});
});
describe('when the command is being run from the view data view', () => {
beforeEach(() => {
setUpSpies('', '');
sqlEditorController.is_query_tool = false;
});
it('it calls the execute_data_query function on the sqlEditorController', () => {
queryToolActions.executeQuery(sqlEditorController);
expect(sqlEditorController.execute_data_query).toHaveBeenCalled();
});
});
});
describe('explainAnalyze', () => {
describe('when verbose and costs are not selected and buffers and timing are not selected', () => {
beforeEach(() => {
setUpSpies('', '');
spyOn(queryToolActions, '_verbose').and.returnValue('OFF');
spyOn(queryToolActions, '_costsEnabled').and.returnValue('OFF');
spyOn(queryToolActions, '_buffers').and.returnValue('OFF');
spyOn(queryToolActions, '_timing').and.returnValue('OFF');
});
it('calls the execute function', () => {
queryToolActions.explainAnalyze(sqlEditorController);
let explainAnalyzeQuery = 'EXPLAIN (FORMAT JSON, ANALYZE ON, VERBOSE OFF, COSTS OFF, BUFFERS OFF, TIMING OFF) ';
expect(sqlEditorController.execute).toHaveBeenCalledWith(explainAnalyzeQuery);
});
});
describe('when verbose and costs and buffers and timing are all selected', () => {
beforeEach(() => {
setUpSpies('', '');
spyOn(queryToolActions, '_verbose').and.returnValue('ON');
spyOn(queryToolActions, '_costsEnabled').and.returnValue('ON');
spyOn(queryToolActions, '_buffers').and.returnValue('ON');
spyOn(queryToolActions, '_timing').and.returnValue('ON');
});
it('calls the execute function', () => {
queryToolActions.explainAnalyze(sqlEditorController);
let explainAnalyzeQuery = 'EXPLAIN (FORMAT JSON, ANALYZE ON, VERBOSE ON, COSTS ON, BUFFERS ON, TIMING ON) ';
expect(sqlEditorController.execute).toHaveBeenCalledWith(explainAnalyzeQuery);
});
});
describe('when verbose is selected and costs is not selected and buffer is selected and timing is not selected', () => {
beforeEach(() => {
setUpSpies('', '');
spyOn(queryToolActions, '_verbose').and.returnValue('ON');
spyOn(queryToolActions, '_costsEnabled').and.returnValue('OFF');
spyOn(queryToolActions, '_buffers').and.returnValue('ON');
spyOn(queryToolActions, '_timing').and.returnValue('OFF');
});
it('calls the execute function', () => {
queryToolActions.explainAnalyze(sqlEditorController);
let explainAnalyzeQuery = 'EXPLAIN (FORMAT JSON, ANALYZE ON, VERBOSE ON, COSTS OFF, BUFFERS ON, TIMING OFF) ';
expect(sqlEditorController.execute).toHaveBeenCalledWith(explainAnalyzeQuery);
});
});
describe('when verbose is not selected and costs is selected and buffer is not selected and timing is selected', () => {
beforeEach(() => {
setUpSpies('', '');
spyOn(queryToolActions, '_verbose').and.returnValue('OFF');
spyOn(queryToolActions, '_costsEnabled').and.returnValue('ON');
spyOn(queryToolActions, '_buffers').and.returnValue('OFF');
spyOn(queryToolActions, '_timing').and.returnValue('ON');
});
it('calls the execute function', () => {
queryToolActions.explainAnalyze(sqlEditorController);
let explainAnalyzeQuery = 'EXPLAIN (FORMAT JSON, ANALYZE ON, VERBOSE OFF, COSTS ON, BUFFERS OFF, TIMING ON) ';
expect(sqlEditorController.execute).toHaveBeenCalledWith(explainAnalyzeQuery);
});
});
});
describe('explain', () => {
describe('when verbose and costs are selected', () => {
beforeEach(() => {
setUpSpies('', '');
spyOn(queryToolActions, '_verbose').and.returnValue('ON');
spyOn(queryToolActions, '_costsEnabled').and.returnValue('ON');
});
it('calls the execute function', () => {
queryToolActions.explain(sqlEditorController);
let explainQuery = 'EXPLAIN (FORMAT JSON, ANALYZE OFF, VERBOSE ON, COSTS ON, BUFFERS OFF, TIMING OFF) ';
expect(sqlEditorController.execute).toHaveBeenCalledWith(explainQuery);
});
});
describe('when verbose and costs are not selected', () => {
beforeEach(() => {
setUpSpies('', '');
spyOn(queryToolActions, '_verbose').and.returnValue('OFF');
spyOn(queryToolActions, '_costsEnabled').and.returnValue('OFF');
});
it('calls the execute function', () => {
queryToolActions.explain(sqlEditorController);
let explainQuery = 'EXPLAIN (FORMAT JSON, ANALYZE OFF, VERBOSE OFF, COSTS OFF, BUFFERS OFF, TIMING OFF) ';
expect(sqlEditorController.execute).toHaveBeenCalledWith(explainQuery);
});
});
describe('when verbose is selected and costs is not selected', () => {
beforeEach(() => {
setUpSpies('', '');
spyOn(queryToolActions, '_verbose').and.returnValue('ON');
spyOn(queryToolActions, '_costsEnabled').and.returnValue('OFF');
});
it('calls the execute function', () => {
queryToolActions.explain(sqlEditorController);
let explainQuery = 'EXPLAIN (FORMAT JSON, ANALYZE OFF, VERBOSE ON, COSTS OFF, BUFFERS OFF, TIMING OFF) ';
expect(sqlEditorController.execute).toHaveBeenCalledWith(explainQuery);
});
});
});
describe('download', () => {
describe('when the query is empty', () => {
beforeEach(() => {
setUpSpies('', '');
});
it('does nothing', () => {
queryToolActions.download(sqlEditorController);
expect(sqlEditorController.trigger_csv_download).not.toHaveBeenCalled();
});
});
describe('when the table was opened through the queryTool', () => {
describe('when the query tool object has a selection', () => {
let time;
beforeEach(() => {
entireQueryString = 'include some more of that yummy string cheese;';
selectedQueryString = 'some silly string cheese';
setUpSpies(selectedQueryString, entireQueryString);
time = 'rightNow';
spyOn(window, 'Date').and.callFake(() => ({
getTime: () => {
return time;
},
}));
});
it('calls trigger_csv_download with the query and the filename', () => {
let filename = 'data-' + time + '.csv';
queryToolActions.download(sqlEditorController);
expect(sqlEditorController.trigger_csv_download).toHaveBeenCalledWith(selectedQueryString, filename);
});
});
describe('when there is no selection', () => {
let time;
beforeEach(() => {
selectedQueryString = '';
entireQueryString = 'include some more of that yummy string cheese;';
setUpSpies(selectedQueryString, entireQueryString);
time = 'rightNow';
spyOn(window, 'Date').and.callFake(() => ({
getTime: () => {
return time;
},
}));
});
it('calls trigger_csv_download with the query and the filename', () => {
let filename = 'data-' + time + '.csv';
queryToolActions.download(sqlEditorController);
expect(sqlEditorController.trigger_csv_download).toHaveBeenCalledWith(entireQueryString, filename);
});
});
});
describe('when the table was opened through tables, view all data', () => {
it('calls trigger_csv_download with the sqlQuery and the table name', () => {
let query = 'a very long query';
setUpSpies('', query);
sqlEditorController.is_query_tool = false;
queryToolActions.download(sqlEditorController);
expect(sqlEditorController.trigger_csv_download).toHaveBeenCalledWith(query, 'iAmATable' + '.csv');
});
});
});
describe('commentBlockCode', () => {
describe('when there is no query text', () => {
beforeEach(() => {
setUpSpies('', '');
});
it('does nothing', () => {
let codeMirrorObj = sqlEditorController.gridView.query_tool_obj;
queryToolActions.commentBlockCode(sqlEditorController);
expect(codeMirrorObj.toggleComment).not.toHaveBeenCalled();
});
});
describe('when there is empty selection', () => {
beforeEach(() => {
setUpSpies('', 'a string\nddd\nsss');
sqlEditorController.gridView.query_tool_obj.getCursor = (isFrom) => {
return isFrom ? 3 : 3;
};
});
it('comments the current line', () => {
let codeMirrorObj = sqlEditorController.gridView.query_tool_obj;
queryToolActions.commentBlockCode(sqlEditorController);
expect(codeMirrorObj.toggleComment).toHaveBeenCalledWith(3, 3);
});
});
describe('when some part of the query is selected', () => {
beforeEach(() => {
setUpSpies('a string\nddd', 'a string\nddd\nsss');
});
it('comments the selection', () => {
let codeMirrorObj = sqlEditorController.gridView.query_tool_obj;
queryToolActions.commentBlockCode(sqlEditorController);
expect(codeMirrorObj.toggleComment).toHaveBeenCalledWith(0, 12);
});
});
});
describe('commentLineCode', () => {
describe('when there is no query text', () => {
beforeEach(() => {
setUpSpies('', '');
});
it('does nothing', () => {
let codeMirrorObj = sqlEditorController.gridView.query_tool_obj;
queryToolActions.commentLineCode(sqlEditorController);
expect(codeMirrorObj.lineComment).not.toHaveBeenCalled();
});
});
describe('when there is empty selection', () => {
beforeEach(() => {
setUpSpies('', 'a string\nddd\nsss');
sqlEditorController.gridView.query_tool_obj.getCursor = (isFrom) => {
return isFrom ? 3 : 3;
};
});
it('comments the current line', () => {
let codeMirrorObj = sqlEditorController.gridView.query_tool_obj;
queryToolActions.commentLineCode(sqlEditorController);
expect(codeMirrorObj.lineComment).toHaveBeenCalledWith(3, 3, {lineComment: '--'});
});
});
describe('when some part of the query is selected', () => {
beforeEach(() => {
setUpSpies('tring\nddd', 'a string\nddd\nsss');
});
it('comments the selection', () => {
let codeMirrorObj = sqlEditorController.gridView.query_tool_obj;
queryToolActions.commentLineCode(sqlEditorController);
expect(codeMirrorObj.lineComment).toHaveBeenCalledWith(3, 12, {lineComment: '--'});
});
});
});
describe('uncommentLineCode', () => {
describe('when there is no query text', () => {
beforeEach(() => {
setUpSpies('', '');
});
it('does nothing', () => {
let codeMirrorObj = sqlEditorController.gridView.query_tool_obj;
queryToolActions.uncommentLineCode(sqlEditorController);
expect(codeMirrorObj.uncomment).not.toHaveBeenCalled();
});
});
describe('when there is empty selection', () => {
beforeEach(() => {
setUpSpies('', 'a string\nddd\nsss');
sqlEditorController.gridView.query_tool_obj.getCursor = (isFrom) => {
return isFrom ? 3 : 3;
};
});
it('uncomments the current line', () => {
let codeMirrorObj = sqlEditorController.gridView.query_tool_obj;
queryToolActions.uncommentLineCode(sqlEditorController);
expect(codeMirrorObj.uncomment).toHaveBeenCalledWith(3, 3, {lineComment: '--'});
});
});
describe('when some part of the query is selected', () => {
beforeEach(() => {
setUpSpies('tring\nddd', 'a string\nddd\nsss');
});
it('uncomments the selection', () => {
let codeMirrorObj = sqlEditorController.gridView.query_tool_obj;
queryToolActions.uncommentLineCode(sqlEditorController);
expect(codeMirrorObj.uncomment).toHaveBeenCalledWith(3, 12, {lineComment: '--'});
});
});
});
function setUpSpies(selectedQueryString, entireQueryString) {
getValueSpy = jasmine.createSpy('getValueSpy').and.returnValue(entireQueryString);
getSelectionSpy = jasmine.createSpy('getSelectionSpy').and.returnValue(selectedQueryString);
sqlEditorController = {
gridView: {
query_tool_obj: {
getSelection: getSelectionSpy,
getValue: getValueSpy,
toggleComment: jasmine.createSpy('toggleCommentSpy'),
lineComment: jasmine.createSpy('lineCommentSpy'),
uncomment: jasmine.createSpy('uncommentSpy'),
getCursor: (isFrom) => {
return entireQueryString.indexOf(selectedQueryString) + (isFrom ? 0 : selectedQueryString.length);
},
},
},
trigger_csv_download: jasmine.createSpy('trigger_csv_download'),
trigger: jasmine.createSpy('trigger'),
table_name: 'iAmATable',
is_query_tool: true,
execute: jasmine.createSpy('execute'),
execute_data_query: jasmine.createSpy('execute_data_query'),
};
}
});