mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2024-11-25 18:20:20 -06:00
640 lines
21 KiB
JavaScript
640 lines
21 KiB
JavaScript
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// pgAdmin 4 - PostgreSQL Tools
|
|
//
|
|
// Copyright (C) 2013 - 2021, 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,
|
|
replaceSelectionSpy;
|
|
|
|
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.check_data_changes_to_execute_query).toHaveBeenCalled();
|
|
});
|
|
});
|
|
describe('when the command is being run from the view data view', () => {
|
|
beforeEach(() => {
|
|
setUpSpies('', '');
|
|
sqlEditorController.is_query_tool = false;
|
|
});
|
|
|
|
it('it calls the check_data_changes_to_execute_query function on the sqlEditorController', () => {
|
|
queryToolActions.executeQuery(sqlEditorController);
|
|
|
|
expect(sqlEditorController.check_data_changes_to_execute_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(false);
|
|
spyOn(queryToolActions, '_costsEnabled').and.returnValue(false);
|
|
spyOn(queryToolActions, '_buffers').and.returnValue(false);
|
|
spyOn(queryToolActions, '_timing').and.returnValue(false);
|
|
spyOn(queryToolActions, '_summary').and.returnValue(false);
|
|
spyOn(queryToolActions, '_settings').and.returnValue(false);
|
|
});
|
|
|
|
it('calls the execute function', () => {
|
|
queryToolActions.explainAnalyze(sqlEditorController);
|
|
|
|
// let explainAnalyzeQuery = 'EXPLAIN (FORMAT JSON, ANALYZE ON, VERBOSE OFF, COSTS OFF, BUFFERS OFF, TIMING OFF) ';
|
|
const explainObject = {
|
|
format: 'json',
|
|
analyze: true,
|
|
verbose: false,
|
|
costs: false,
|
|
buffers: false,
|
|
timing: false,
|
|
summary: false,
|
|
settings: false,
|
|
};
|
|
|
|
expect(sqlEditorController.check_data_changes_to_execute_query).toHaveBeenCalledWith(explainObject);
|
|
});
|
|
});
|
|
|
|
describe('when all options are selected', () => {
|
|
beforeEach(() => {
|
|
setUpSpies('', '');
|
|
spyOn(queryToolActions, '_verbose').and.returnValue(true);
|
|
spyOn(queryToolActions, '_costsEnabled').and.returnValue(true);
|
|
spyOn(queryToolActions, '_buffers').and.returnValue(true);
|
|
spyOn(queryToolActions, '_timing').and.returnValue(true);
|
|
spyOn(queryToolActions, '_summary').and.returnValue(true);
|
|
spyOn(queryToolActions, '_settings').and.returnValue(true);
|
|
});
|
|
it('calls the execute function', () => {
|
|
queryToolActions.explainAnalyze(sqlEditorController);
|
|
const explainObject = {
|
|
format: 'json',
|
|
analyze: true,
|
|
verbose: true,
|
|
costs: true,
|
|
buffers: true,
|
|
timing: true,
|
|
summary: true,
|
|
settings: true,
|
|
};
|
|
expect(sqlEditorController.check_data_changes_to_execute_query).toHaveBeenCalledWith(explainObject);
|
|
});
|
|
});
|
|
|
|
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(true);
|
|
spyOn(queryToolActions, '_costsEnabled').and.returnValue(false);
|
|
spyOn(queryToolActions, '_buffers').and.returnValue(true);
|
|
spyOn(queryToolActions, '_timing').and.returnValue(false);
|
|
spyOn(queryToolActions, '_summary').and.returnValue(false);
|
|
spyOn(queryToolActions, '_settings').and.returnValue(false);
|
|
});
|
|
it('calls the execute function', () => {
|
|
queryToolActions.explainAnalyze(sqlEditorController);
|
|
|
|
const explainObject = {
|
|
format: 'json',
|
|
analyze: true,
|
|
verbose: true,
|
|
costs: false,
|
|
buffers: true,
|
|
timing: false,
|
|
summary: false,
|
|
settings: false,
|
|
};
|
|
|
|
expect(sqlEditorController.check_data_changes_to_execute_query).toHaveBeenCalledWith(explainObject);
|
|
});
|
|
});
|
|
|
|
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(false);
|
|
spyOn(queryToolActions, '_costsEnabled').and.returnValue(true);
|
|
spyOn(queryToolActions, '_buffers').and.returnValue(false);
|
|
spyOn(queryToolActions, '_timing').and.returnValue(true);
|
|
spyOn(queryToolActions, '_summary').and.returnValue(false);
|
|
spyOn(queryToolActions, '_settings').and.returnValue(false);
|
|
});
|
|
it('calls the execute function', () => {
|
|
queryToolActions.explainAnalyze(sqlEditorController);
|
|
|
|
const explainObject = {
|
|
format: 'json',
|
|
analyze: true,
|
|
verbose: false,
|
|
costs: true,
|
|
buffers: false,
|
|
timing: true,
|
|
summary: false,
|
|
settings: false,
|
|
};
|
|
|
|
expect(sqlEditorController.check_data_changes_to_execute_query).toHaveBeenCalledWith(explainObject);
|
|
});
|
|
});
|
|
|
|
describe('when all are not selected except summary and settings', () => {
|
|
beforeEach(() => {
|
|
setUpSpies('', '');
|
|
spyOn(queryToolActions, '_verbose').and.returnValue(false);
|
|
spyOn(queryToolActions, '_costsEnabled').and.returnValue(false);
|
|
spyOn(queryToolActions, '_buffers').and.returnValue(false);
|
|
spyOn(queryToolActions, '_timing').and.returnValue(false);
|
|
spyOn(queryToolActions, '_summary').and.returnValue(true);
|
|
spyOn(queryToolActions, '_settings').and.returnValue(true);
|
|
});
|
|
it('calls the execute function', () => {
|
|
queryToolActions.explainAnalyze(sqlEditorController);
|
|
|
|
const explainObject = {
|
|
format: 'json',
|
|
analyze: true,
|
|
verbose: false,
|
|
costs: false,
|
|
buffers: false,
|
|
timing: false,
|
|
summary: true,
|
|
settings: true,
|
|
};
|
|
|
|
expect(sqlEditorController.check_data_changes_to_execute_query).toHaveBeenCalledWith(explainObject);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('explain', () => {
|
|
describe('when verbose and costs are selected', () => {
|
|
beforeEach(() => {
|
|
setUpSpies('', '');
|
|
spyOn(queryToolActions, '_verbose').and.returnValue(true);
|
|
spyOn(queryToolActions, '_costsEnabled').and.returnValue(true);
|
|
spyOn(queryToolActions, '_summary').and.returnValue(false);
|
|
spyOn(queryToolActions, '_settings').and.returnValue(false);
|
|
spyOn(queryToolActions, '_summary').and.returnValue(false);
|
|
spyOn(queryToolActions, '_settings').and.returnValue(false);
|
|
});
|
|
|
|
it('calls the execute function', () => {
|
|
queryToolActions.explain(sqlEditorController);
|
|
const explainObject = {
|
|
format: 'json',
|
|
analyze: false,
|
|
verbose: true,
|
|
costs: true,
|
|
buffers: false,
|
|
timing: false,
|
|
summary: false,
|
|
settings: false,
|
|
};
|
|
expect(sqlEditorController.check_data_changes_to_execute_query).toHaveBeenCalledWith(explainObject);
|
|
});
|
|
});
|
|
|
|
describe('when verbose and costs are not selected', () => {
|
|
beforeEach(() => {
|
|
setUpSpies('', '');
|
|
spyOn(queryToolActions, '_verbose').and.returnValue(false);
|
|
spyOn(queryToolActions, '_costsEnabled').and.returnValue(false);
|
|
spyOn(queryToolActions, '_summary').and.returnValue(false);
|
|
spyOn(queryToolActions, '_settings').and.returnValue(false);
|
|
});
|
|
|
|
it('calls the execute function', () => {
|
|
queryToolActions.explain(sqlEditorController);
|
|
const explainObject = {
|
|
format: 'json',
|
|
analyze: false,
|
|
verbose: false,
|
|
costs: false,
|
|
buffers: false,
|
|
timing: false,
|
|
summary: false,
|
|
settings: false,
|
|
};
|
|
|
|
expect(sqlEditorController.check_data_changes_to_execute_query).toHaveBeenCalledWith(explainObject);
|
|
});
|
|
});
|
|
|
|
describe('when verbose is selected and costs is not selected', () => {
|
|
beforeEach(() => {
|
|
setUpSpies('', '');
|
|
spyOn(queryToolActions, '_verbose').and.returnValue(true);
|
|
spyOn(queryToolActions, '_costsEnabled').and.returnValue(false);
|
|
spyOn(queryToolActions, '_summary').and.returnValue(false);
|
|
spyOn(queryToolActions, '_settings').and.returnValue(false);
|
|
});
|
|
|
|
it('calls the execute function', () => {
|
|
queryToolActions.explain(sqlEditorController);
|
|
const explainObject = {
|
|
format: 'json',
|
|
analyze: false,
|
|
verbose: true,
|
|
costs: false,
|
|
buffers: false,
|
|
timing: false,
|
|
summary: false,
|
|
settings: false,
|
|
};
|
|
expect(sqlEditorController.check_data_changes_to_execute_query).toHaveBeenCalledWith(explainObject);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('download', () => {
|
|
describe('when the query is empty', () => {
|
|
beforeEach(() => {
|
|
setUpSpies('', '');
|
|
});
|
|
it('does nothing', () => {
|
|
queryToolActions.download(sqlEditorController);
|
|
|
|
expect(sqlEditorController.trigger_csv_download).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 filename having .csv extension', () => {
|
|
let filename = 'data-' + time + '.csv';
|
|
|
|
queryToolActions.download(sqlEditorController);
|
|
|
|
expect(sqlEditorController.trigger_csv_download).toHaveBeenCalledWith(filename);
|
|
});
|
|
|
|
it('calls trigger_csv_download filename having .txt extension', () => {
|
|
sqlEditorController.preferences.csv_field_separator = ';';
|
|
let filename = 'data-' + time + '.txt';
|
|
|
|
queryToolActions.download(sqlEditorController);
|
|
|
|
expect(sqlEditorController.trigger_csv_download).toHaveBeenCalledWith(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 filename', () => {
|
|
let filename = 'data-' + time + '.csv';
|
|
|
|
queryToolActions.download(sqlEditorController);
|
|
|
|
expect(sqlEditorController.trigger_csv_download).toHaveBeenCalledWith(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('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 = () => {
|
|
return 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 = () => {
|
|
return 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 = () => {
|
|
return 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: '--'});
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('toggleCaseOfSelectedText', () => {
|
|
describe('when there is no query text', () => {
|
|
beforeEach(() => {
|
|
setUpSpies('', '');
|
|
});
|
|
it('does nothing', () => {
|
|
expect(
|
|
queryToolActions.toggleCaseOfSelectedText(sqlEditorController)
|
|
).not.toBeDefined();
|
|
});
|
|
});
|
|
|
|
describe('when there is empty selection', () => {
|
|
beforeEach(() => {
|
|
setUpSpies('', 'a string\nddd\nsss');
|
|
|
|
sqlEditorController.gridView.query_tool_obj.getCursor = () => {
|
|
return 3;
|
|
};
|
|
});
|
|
|
|
it('does nothing', () => {
|
|
expect(
|
|
queryToolActions.toggleCaseOfSelectedText(sqlEditorController)
|
|
).not.toBeDefined();
|
|
});
|
|
});
|
|
|
|
describe('when selected query is in lower case', () => {
|
|
beforeEach(() => {
|
|
setUpSpies('string', 'a string\nddd\nsss');
|
|
});
|
|
|
|
it('toggle the selection and string should be in upper case', () => {
|
|
queryToolActions.toggleCaseOfSelectedText(sqlEditorController);
|
|
expect(replaceSelectionSpy
|
|
).toHaveBeenCalledWith('STRING');
|
|
});
|
|
|
|
it('(negative scenario toggle the selection and string should be in upper case', () => {
|
|
queryToolActions.toggleCaseOfSelectedText(sqlEditorController);
|
|
expect(replaceSelectionSpy
|
|
).not.toHaveBeenCalledWith('string');
|
|
});
|
|
});
|
|
|
|
describe('when selected query is in upper case', () => {
|
|
beforeEach(() => {
|
|
setUpSpies('STRING', 'a string\nddd\nsss');
|
|
});
|
|
|
|
it('toggle the selection and string should be in lower case', () => {
|
|
queryToolActions.toggleCaseOfSelectedText(sqlEditorController);
|
|
expect(replaceSelectionSpy
|
|
).toHaveBeenCalledWith('string');
|
|
});
|
|
|
|
it('(negative scenario toggle the selection and string should be in lower case', () => {
|
|
queryToolActions.toggleCaseOfSelectedText(sqlEditorController);
|
|
expect(replaceSelectionSpy
|
|
).not.toHaveBeenCalledWith('STRING');
|
|
});
|
|
});
|
|
|
|
describe('when selected query is in mixed case', () => {
|
|
beforeEach(() => {
|
|
setUpSpies('sTRIng', 'a string\nddd\nsss');
|
|
});
|
|
|
|
it('toggle the selection and string should be in upper case', () => {
|
|
queryToolActions.toggleCaseOfSelectedText(sqlEditorController);
|
|
expect(replaceSelectionSpy
|
|
).toHaveBeenCalledWith('STRING');
|
|
});
|
|
|
|
it('(negative scenario toggle the selection and string should be in upper case', () => {
|
|
queryToolActions.toggleCaseOfSelectedText(sqlEditorController);
|
|
expect(replaceSelectionSpy
|
|
).not.toHaveBeenCalledWith('sTRIng');
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('executeCommit', () => {
|
|
describe('when commit action is being run from the query tool', () => {
|
|
beforeEach(() => {
|
|
setUpSpies('', '');
|
|
});
|
|
|
|
it('calls the execute commit function', () => {
|
|
queryToolActions.executeCommit(sqlEditorController);
|
|
expect(sqlEditorController.special_sql).toEqual('COMMIT;');
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('executeRollback', () => {
|
|
describe('when rollback action is being run from the query tool', () => {
|
|
beforeEach(() => {
|
|
setUpSpies('', '');
|
|
});
|
|
|
|
it('calls the execute rollback function', () => {
|
|
queryToolActions.executeRollback(sqlEditorController);
|
|
expect(sqlEditorController.special_sql).toEqual('ROLLBACK;');
|
|
});
|
|
});
|
|
});
|
|
|
|
function setUpSpies(selectedQueryStringArg, entireQueryStringArg) {
|
|
getValueSpy = jasmine.createSpy('getValueSpy').and.returnValue(entireQueryStringArg);
|
|
getSelectionSpy = jasmine.createSpy('getSelectionSpy').and.returnValue(selectedQueryStringArg);
|
|
replaceSelectionSpy = jasmine.createSpy('replaceSelectionSpy');
|
|
|
|
sqlEditorController = {
|
|
gridView: {
|
|
query_tool_obj: {
|
|
getSelection: getSelectionSpy,
|
|
getValue: getValueSpy,
|
|
toggleComment: jasmine.createSpy('toggleCommentSpy'),
|
|
lineComment: jasmine.createSpy('lineCommentSpy'),
|
|
uncomment: jasmine.createSpy('uncommentSpy'),
|
|
replaceSelection: replaceSelectionSpy,
|
|
getCursor: (isFrom) => {
|
|
return entireQueryStringArg.indexOf(selectedQueryStringArg) + (isFrom ? 0 : selectedQueryStringArg.length);
|
|
},
|
|
},
|
|
},
|
|
trigger_csv_download: jasmine.createSpy('trigger_csv_download'),
|
|
trigger: jasmine.createSpy('trigger'),
|
|
table_name: 'iAmATable',
|
|
is_query_tool: true,
|
|
check_data_changes_to_execute_query: jasmine.createSpy('check_data_changes_to_execute_query'),
|
|
preferences: {
|
|
csv_field_separator: ',',
|
|
},
|
|
};
|
|
}
|
|
});
|