338 lines
12 KiB
JavaScript
338 lines
12 KiB
JavaScript
var _ = require('underscore');
|
|
var Backbone = require('backbone');
|
|
var QueryGeometryModel = require('builder/data/query-geometry-model');
|
|
var QuerySchemaModel = require('builder/data/query-schema-model');
|
|
var QueryRowsCollection = require('builder/data/query-rows-collection');
|
|
var QueryColumnsCollection = require('builder/data/query-columns-collection');
|
|
var UserModel = require('builder/data/user-model');
|
|
var AnalysisDefinitionNodeModel = require('builder/data/analysis-definition-node-model');
|
|
var AnalysisDefinitionNodeSourceModel = require('builder/data/analysis-definition-node-source-model');
|
|
var AnalysisDefinitionNodesCollection = require('builder/data/analysis-definition-nodes-collection');
|
|
var TableView = require('builder/components/table/table-view');
|
|
var TableHeadView = require('builder/components/table/head/table-head-view');
|
|
var TableBodyView = require('builder/components/table/body/table-body-view');
|
|
var ConfigModel = require('builder/data/config-model');
|
|
var FactoryModals = require('../../factories/modals');
|
|
|
|
describe('components/table/table-view', function () {
|
|
beforeEach(function () {
|
|
spyOn(QueryGeometryModel.prototype, 'fetch');
|
|
spyOn(QueryRowsCollection.prototype, 'fetch');
|
|
spyOn(QueryColumnsCollection.prototype, 'fetch');
|
|
spyOn(QuerySchemaModel.prototype, 'fetch');
|
|
|
|
spyOn(_, 'debounce').and.callFake(function (func) {
|
|
return function () {
|
|
func.apply(this, arguments);
|
|
};
|
|
});
|
|
|
|
this.configModel = new ConfigModel({
|
|
user_name: 'pepito'
|
|
});
|
|
|
|
this.userModel = new UserModel({
|
|
name: 'pepito'
|
|
}, {
|
|
configModel: this.configModel
|
|
});
|
|
|
|
this.modals = FactoryModals.createModalService();
|
|
|
|
this.analysisDefinitionNodeModel = new AnalysisDefinitionNodeSourceModel({
|
|
query: 'select * from pepito',
|
|
table_name: 'pepito',
|
|
id: 'dummy-id',
|
|
type: 'source'
|
|
}, {
|
|
configModel: this.configModel,
|
|
userModel: this.userModel
|
|
});
|
|
|
|
this.analysisDefinitionNodesCollection = new AnalysisDefinitionNodesCollection([this.analysisDefinitionNodeModel], {
|
|
configModel: this.configModel,
|
|
userModel: this.userModel
|
|
});
|
|
|
|
this.querySchemaModel = this.analysisDefinitionNodeModel.querySchemaModel;
|
|
this.queryGeometryModel = this.analysisDefinitionNodeModel.queryGeometryModel;
|
|
|
|
this.querySchemaModel.attributes.status = 'unfetched';
|
|
|
|
this.columnsCollection = new QueryColumnsCollection([], {
|
|
configModel: this.configModel,
|
|
querySchemaModel: this.querySchemaModel
|
|
});
|
|
|
|
spyOn(TableView.prototype, '_setDisableState').and.callThrough();
|
|
spyOn(TableView.prototype, 'render').and.callThrough();
|
|
spyOn(TableHeadView.prototype, 'initialize').and.callThrough();
|
|
spyOn(TableBodyView.prototype, 'initialize').and.callThrough();
|
|
|
|
this.view = new TableView({
|
|
modals: this.modals,
|
|
columnsCollection: this.columnsCollection,
|
|
analysisDefinitionNodeModel: this.analysisDefinitionNodeModel
|
|
});
|
|
});
|
|
|
|
it('should create table-view-model', function () {
|
|
expect(this.view._tableViewModel).toBeDefined();
|
|
});
|
|
|
|
describe('fetch', function () {
|
|
it('should fetch query-schema-model if it is unfetched', function () {
|
|
expect(QuerySchemaModel.prototype.fetch).toHaveBeenCalled();
|
|
});
|
|
|
|
it('should fetch rows data if query-schema-model is already fetched', function () {
|
|
spyOn(TableView.prototype, '_fetchRowsData');
|
|
this.querySchemaModel.set('status', 'fetched');
|
|
var view = new TableView({
|
|
modals: this.modals,
|
|
columnsCollection: this.columnsCollection,
|
|
analysisDefinitionNodeModel: this.analysisDefinitionNodeModel
|
|
});
|
|
expect(TableView.prototype._fetchRowsData).toHaveBeenCalled();
|
|
expect(view).toBeDefined();
|
|
});
|
|
|
|
it('should not fetch rows data if query-schema-model query modifies the schema', function () {
|
|
spyOn(TableView.prototype, '_fetchRowsData');
|
|
this.querySchemaModel.set({
|
|
status: 'fetched',
|
|
query: 'DELETE FROM whatever WHERE perico="PACO"'
|
|
});
|
|
var view = new TableView({
|
|
modals: this.modals,
|
|
columnsCollection: this.columnsCollection,
|
|
analysisDefinitionNodeModel: this.analysisDefinitionNodeModel
|
|
});
|
|
expect(TableView.prototype._fetchRowsData).not.toHaveBeenCalled();
|
|
expect(view).toBeDefined();
|
|
});
|
|
});
|
|
|
|
describe('render', function () {
|
|
beforeEach(function () {
|
|
this.view.render();
|
|
});
|
|
|
|
it('should render head and body', function () {
|
|
expect(_.size(this.view._subviews)).toBe(2);
|
|
});
|
|
|
|
it('should add relative class if table view model has it', function () {
|
|
this.view._tableViewModel.set('relativePositionated', true);
|
|
this.view.render();
|
|
expect(this.view.$('.js-table').hasClass('Table--relative')).toBeTruthy();
|
|
});
|
|
});
|
|
|
|
describe('canHideColumns on TableBodyView/TableHeadView constructor', function () {
|
|
it('should be false if simply a source node is provided', function () {
|
|
this.view.render();
|
|
expect(TableBodyView.prototype.initialize).toHaveBeenCalledWith(jasmine.objectContaining({
|
|
canHideColumns: false
|
|
}));
|
|
|
|
expect(TableHeadView.prototype.initialize).toHaveBeenCalledWith(jasmine.objectContaining({
|
|
canHideColumns: false
|
|
}));
|
|
});
|
|
|
|
it('should be true if a trade-area analysis is somewhere in the analysis chain but no SQL analysis', function () {
|
|
const sourceNode = new AnalysisDefinitionNodeSourceModel({
|
|
query: 'select * from pepito',
|
|
table_name: 'pepito',
|
|
id: 'a0',
|
|
type: 'source'
|
|
}, {
|
|
configModel: this.configModel,
|
|
userModel: this.userModel
|
|
});
|
|
|
|
const node = new AnalysisDefinitionNodeModel({
|
|
id: 'a1',
|
|
type: 'trade-area',
|
|
source: 'a0'
|
|
}, {
|
|
configModel: this.configModel
|
|
});
|
|
|
|
new AnalysisDefinitionNodesCollection([sourceNode, node], { // eslint-disable-line no-new
|
|
configModel: this.configModel,
|
|
userModel: this.userModel
|
|
});
|
|
|
|
this.view = new TableView({
|
|
modals: this.modals,
|
|
columnsCollection: this.columnsCollection,
|
|
analysisDefinitionNodeModel: node
|
|
});
|
|
|
|
this.view.render();
|
|
expect(TableBodyView.prototype.initialize).toHaveBeenCalledWith(jasmine.objectContaining({
|
|
canHideColumns: true
|
|
}));
|
|
|
|
expect(TableHeadView.prototype.initialize).toHaveBeenCalledWith(jasmine.objectContaining({
|
|
canHideColumns: true
|
|
}));
|
|
});
|
|
|
|
it('should be false if a trade-area analysis is somewhere in the analysis chain but also a SQL analysis', function () {
|
|
const sourceNode = new AnalysisDefinitionNodeSourceModel({
|
|
query: 'select * from pepito',
|
|
table_name: 'pepito',
|
|
id: 'a0',
|
|
type: 'source'
|
|
}, {
|
|
configModel: this.configModel,
|
|
userModel: this.userModel
|
|
});
|
|
|
|
const node = new AnalysisDefinitionNodeModel({
|
|
id: 'a1',
|
|
type: 'trade-area',
|
|
source: 'a0'
|
|
}, {
|
|
configModel: this.configModel
|
|
});
|
|
|
|
const sqlNode = new AnalysisDefinitionNodeModel({
|
|
id: 'a2',
|
|
type: 'deprecated-sql-function',
|
|
source: 'a1'
|
|
}, {
|
|
configModel: this.configModel
|
|
});
|
|
|
|
new AnalysisDefinitionNodesCollection([sourceNode, node, sqlNode], { // eslint-disable-line no-new
|
|
configModel: this.configModel,
|
|
userModel: this.userModel
|
|
});
|
|
|
|
this.view = new TableView({
|
|
modals: this.modals,
|
|
columnsCollection: this.columnsCollection,
|
|
analysisDefinitionNodeModel: sqlNode
|
|
});
|
|
|
|
this.view.render();
|
|
expect(TableBodyView.prototype.initialize).toHaveBeenCalledWith(jasmine.objectContaining({
|
|
canHideColumns: false
|
|
}));
|
|
|
|
expect(TableHeadView.prototype.initialize).toHaveBeenCalledWith(jasmine.objectContaining({
|
|
canHideColumns: false
|
|
}));
|
|
});
|
|
});
|
|
|
|
describe('bind', function () {
|
|
it('should reset table view attributes when query has changed', function () {
|
|
this.view._tableViewModel.set({
|
|
page: 3,
|
|
order_by: 'description',
|
|
sort_order: 'desc'
|
|
});
|
|
this.querySchemaModel.set('query', 'SELECT * FROM new_table');
|
|
expect(this.view._tableViewModel.get('page')).toBe(0);
|
|
expect(this.view._tableViewModel.get('order_by')).toBe('');
|
|
expect(this.view._tableViewModel.get('sort_order')).toBe('');
|
|
});
|
|
|
|
it('should include sort and order if the query is custom but the change comes from table-view-model', function () {
|
|
this.querySchemaModel.set('query', 'SELECT * FROM new_table', { silent: true });
|
|
this.view._tableViewModel.set({
|
|
page: 3,
|
|
order_by: 'description',
|
|
sort_order: 'desc'
|
|
});
|
|
expect(this.view._tableViewModel.get('page')).toBe(3);
|
|
expect(this.view._tableViewModel.get('order_by')).toBe('description');
|
|
expect(this.view._tableViewModel.get('sort_order')).toBe('desc');
|
|
});
|
|
|
|
it('should check disabled state each time query schema model changes', function () {
|
|
this.querySchemaModel.set('status', 'fetched');
|
|
expect(TableView.prototype._setDisableState).toHaveBeenCalled();
|
|
TableView.prototype._setDisableState.calls.reset();
|
|
this.querySchemaModel.set('status', 'fetching');
|
|
expect(TableView.prototype._setDisableState).toHaveBeenCalled();
|
|
});
|
|
|
|
it('should fetch query-schema-model if query has changed and it is possible', function () {
|
|
this.querySchemaModel.fetch.calls.reset();
|
|
this.querySchemaModel.set({
|
|
query: 'SELECT * FROM new_table',
|
|
status: 'unfetched'
|
|
});
|
|
expect(this.querySchemaModel.fetch).toHaveBeenCalled();
|
|
|
|
this.querySchemaModel.fetch.calls.reset();
|
|
this.querySchemaModel.set({
|
|
query: '',
|
|
status: 'unfetched'
|
|
});
|
|
expect(this.querySchemaModel.fetch).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('should fetch new rows when query fetch has finished', function () {
|
|
this.querySchemaModel.set('status', 'fetched');
|
|
expect(QueryRowsCollection.prototype.fetch).toHaveBeenCalled();
|
|
});
|
|
|
|
it('should render again if synchronization is destroyed', function () {
|
|
spyOn(this.analysisDefinitionNodeModel, 'isSourceType').and.returnValue(true);
|
|
var tableModel = this.analysisDefinitionNodeModel.getTableModel();
|
|
tableModel._syncModel = new Backbone.Model({ id: 'dummy' });
|
|
tableModel._syncModel.url = 'dummy';
|
|
tableModel._syncModel.sync = function (a, b, opts) {
|
|
opts.success();
|
|
};
|
|
this.view._tableModel = tableModel;
|
|
|
|
this.view._initBinds();
|
|
tableModel._syncModel.destroy();
|
|
|
|
expect(TableView.prototype.render).toHaveBeenCalled();
|
|
});
|
|
|
|
describe('on table model view changes', function () {
|
|
beforeEach(function () {
|
|
this.querySchemaModel.set('status', 'fetched');
|
|
this.queryGeometryModel.set({
|
|
status: 'fetched'
|
|
});
|
|
});
|
|
|
|
it('should fetch new rows when table order changes', function () {
|
|
this.view._tableViewModel.set('order_by', 'cartodb_id');
|
|
expect(QueryRowsCollection.prototype.fetch).toHaveBeenCalled();
|
|
});
|
|
|
|
it('should fetch new rows when table sort changes', function () {
|
|
this.view._tableViewModel.set('sort_order', 'desc');
|
|
expect(QueryRowsCollection.prototype.fetch).toHaveBeenCalled();
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('.getColumnsCollection', function () {
|
|
it('should provide the _columnsCollection object', function () {
|
|
expect(this.view.getColumnsCollection()).toBe(this.view._columnsCollection);
|
|
});
|
|
});
|
|
|
|
it('should have no leaks', function () {
|
|
this.view.render();
|
|
expect(this.view).toHaveNoLeaks();
|
|
});
|
|
|
|
afterEach(function () {
|
|
this.view.clean();
|
|
});
|
|
});
|