358 lines
12 KiB
JavaScript
358 lines
12 KiB
JavaScript
var Backbone = require('backbone');
|
|
var _ = require('underscore');
|
|
var AnalysisService = require('../../../src/analysis/analysis-service');
|
|
var CartoDBLayer = require('../../../src/geo/map/cartodb-layer');
|
|
var Dataview = require('../../../src/dataviews/dataview-model-base');
|
|
|
|
describe('src/analysis/analysis-service.js', function () {
|
|
var engineMock = new Backbone.Model();
|
|
var fakeCamshaftReference = {
|
|
getSourceNamesForAnalysisType: function (analysisType) {
|
|
var map = {
|
|
'trade-area': ['source'],
|
|
'estimated-population': ['source'],
|
|
'sql-function': ['source', 'target']
|
|
};
|
|
return map[analysisType];
|
|
},
|
|
getParamNamesForAnalysisType: function (analysisType) {
|
|
var map = {
|
|
'trade-area': ['kind', 'time'],
|
|
'estimated-population': ['columnName']
|
|
};
|
|
return map[analysisType];
|
|
}
|
|
};
|
|
beforeEach(function () {
|
|
this.analysisService = new AnalysisService({
|
|
engine: engineMock,
|
|
camshaftReference: fakeCamshaftReference
|
|
});
|
|
});
|
|
|
|
describe('.analyse', function () {
|
|
it('should generate and return a new analysis', function () {
|
|
var subwayStops = this.analysisService.analyse({
|
|
id: 'a0',
|
|
type: 'source',
|
|
query: 'SELECT * FROM subway_stops'
|
|
});
|
|
|
|
expect(subwayStops.attributes).toEqual({
|
|
id: 'a0',
|
|
type: 'source',
|
|
query: 'SELECT * FROM subway_stops'
|
|
});
|
|
});
|
|
|
|
it('should set attrs on the analysis models', function () {
|
|
var analysisService = new AnalysisService({
|
|
engine: new Backbone.Model(),
|
|
apiKey: 'THE_API_KEY',
|
|
authToken: 'THE_AUTH_TOKEN',
|
|
camshaftReference: fakeCamshaftReference
|
|
});
|
|
|
|
var analysisModel = analysisService.analyse({
|
|
id: 'a0',
|
|
type: 'source',
|
|
query: 'SELECT * FROM subway_stops'
|
|
});
|
|
|
|
expect(analysisModel.get('apiKey')).toEqual('THE_API_KEY');
|
|
expect(analysisModel.get('authToken')).toEqual('THE_AUTH_TOKEN');
|
|
});
|
|
|
|
it('should recursively build the analysis graph', function () {
|
|
var estimatedPopulation = this.analysisService.analyse(
|
|
{
|
|
id: 'a2',
|
|
type: 'estimated-population',
|
|
params: {
|
|
columnName: 'estimated_people',
|
|
source: {
|
|
id: 'a1',
|
|
type: 'trade-area',
|
|
params: {
|
|
kind: 'walk',
|
|
time: 300,
|
|
source: {
|
|
id: 'a0',
|
|
type: 'source',
|
|
params: {
|
|
query: 'SELECT * FROM subway_stops'
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
);
|
|
var tradeArea = estimatedPopulation.get('source');
|
|
var subwayStops = tradeArea.get('source');
|
|
expect(tradeArea.get('id')).toEqual('a1');
|
|
expect(subwayStops.get('id')).toEqual('a0');
|
|
});
|
|
|
|
it('analysis should be re-created after it has been removed', function () {
|
|
var subwayStops1 = this.analysisService.analyse({
|
|
id: 'a0',
|
|
type: 'source',
|
|
params: {
|
|
query: 'SELECT * FROM subway_stops'
|
|
}
|
|
});
|
|
|
|
subwayStops1.remove();
|
|
|
|
var subwayStops2 = this.analysisService.analyse({
|
|
id: 'a0',
|
|
type: 'source',
|
|
params: {
|
|
query: 'SELECT * FROM subway_stops '
|
|
}
|
|
});
|
|
|
|
expect(subwayStops1.cid).not.toEqual(subwayStops2.cid);
|
|
});
|
|
});
|
|
|
|
describe('.findNodeById', function () {
|
|
it('should traverse the analysis and return an existing node', function () {
|
|
var analysisA = this.analysisService.analyse(
|
|
{
|
|
id: 'a2',
|
|
type: 'estimated-population',
|
|
params: {
|
|
columnName: 'estimated_people',
|
|
source: {
|
|
id: 'a1',
|
|
type: 'trade-area',
|
|
params: {
|
|
kind: 'walk',
|
|
time: 300,
|
|
source: {
|
|
id: 'a0',
|
|
type: 'source',
|
|
params: {
|
|
query: 'SELECT * FROM subway_stops'
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
);
|
|
var analysisANodes = analysisA.getNodesCollection();
|
|
|
|
var analysisB = this.analysisService.analyse(
|
|
{
|
|
id: 'b0',
|
|
type: 'source',
|
|
params: {
|
|
query: 'SELECT * FROM bus_stops'
|
|
}
|
|
}
|
|
);
|
|
|
|
// This specs make easy to know what went wrong when the test fails
|
|
expect(this.analysisService.findNodeById('a2').get('id')).toBe('a2');
|
|
expect(this.analysisService.findNodeById('a1').get('id')).toBe('a1');
|
|
expect(this.analysisService.findNodeById('a0').get('id')).toBe('a0');
|
|
expect(this.analysisService.findNodeById('b0').get('id')).toBe('b0');
|
|
|
|
expect(this.analysisService.findNodeById('a2')).toBe(analysisANodes.get('a2'));
|
|
expect(this.analysisService.findNodeById('a1')).toBe(analysisANodes.get('a1'));
|
|
expect(this.analysisService.findNodeById('a0')).toBe(analysisANodes.get('a0'));
|
|
expect(this.analysisService.findNodeById('b0')).toBe(analysisB);
|
|
|
|
expect(this.analysisService.findNodeById('c0')).toBeUndefined();
|
|
});
|
|
|
|
it('should return undefined if node is not found', function () {
|
|
pending('Included in previous tests. TODO: create new test for this');
|
|
});
|
|
});
|
|
|
|
describe('._getAnalysisAttributesFromAnalysisDefinition', function () {
|
|
it('should analyse all source nodes if everyone has params', function () {
|
|
var analysisDefinition = {
|
|
type: 'trade-area',
|
|
params: {
|
|
source: 'a0'
|
|
}
|
|
};
|
|
spyOn(this.analysisService, 'analyse').and.returnValue('node');
|
|
|
|
var result = this.analysisService._getAnalysisAttributesFromAnalysisDefinition(analysisDefinition, this.analysisService.analyse.bind(this));
|
|
|
|
expect(this.analysisService.analyse.calls.count()).toEqual(1);
|
|
expect(this.analysisService.analyse).toHaveBeenCalledWith('a0');
|
|
expect(result).toEqual({
|
|
type: 'trade-area',
|
|
source: 'node'
|
|
});
|
|
});
|
|
|
|
it('should analyse only source nodes that has params', function () {
|
|
var analysisDefinition = {
|
|
type: 'sql-function',
|
|
params: {
|
|
source: 'a0'
|
|
}
|
|
};
|
|
spyOn(this.analysisService, 'analyse').and.returnValue('node');
|
|
|
|
var result = this.analysisService._getAnalysisAttributesFromAnalysisDefinition(analysisDefinition, this.analysisService.analyse.bind(this));
|
|
|
|
expect(this.analysisService.analyse.calls.count()).toEqual(1);
|
|
expect(this.analysisService.analyse).toHaveBeenCalledWith('a0');
|
|
expect(result).toEqual({
|
|
type: 'sql-function',
|
|
source: 'node'
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('.getUniqueAnalysisNodes', function () {
|
|
it('should return the analysis nodes: (single analysis node in a single layer)', function () {
|
|
var analysis = this.analysisService.analyse({
|
|
id: 'a0',
|
|
type: 'source',
|
|
query: 'SELECT * FROM subway_stops'
|
|
});
|
|
var layer = new CartoDBLayer({ source: analysis }, { engine: engineMock });
|
|
var layersCollection = new Backbone.Collection([layer]);
|
|
var dataviewsCollection = new Backbone.Collection();
|
|
|
|
var expected = analysis;
|
|
var actual = AnalysisService.getUniqueAnalysisNodes(layersCollection, dataviewsCollection);
|
|
|
|
expect(actual[0]).toEqual(expected);
|
|
});
|
|
|
|
it('should return the analysis nodes: (2 analysis nodes, 1 dataview, 1 layer)', function () {
|
|
var analysis0 = this.analysisService.analyse({
|
|
id: 'a0',
|
|
type: 'source',
|
|
query: 'SELECT * FROM subway_stops'
|
|
});
|
|
|
|
var analysis1 = this.analysisService.analyse({
|
|
id: 'a1',
|
|
type: 'source',
|
|
query: 'SELECT * FROM bus_stops'
|
|
});
|
|
|
|
var layer = new CartoDBLayer({ source: analysis0 }, { engine: engineMock });
|
|
var dataview = new Dataview({ id: 'dataview1', source: analysis1 }, { map: {}, engine: engineMock });
|
|
|
|
var layersCollection = new Backbone.Collection([layer]);
|
|
var dataviewsCollection = new Backbone.Collection([dataview]);
|
|
|
|
var expected = [analysis0, analysis1];
|
|
var actual = AnalysisService.getUniqueAnalysisNodes(layersCollection, dataviewsCollection);
|
|
|
|
expect(actual.length).toEqual(expected.length);
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
|
|
it('should return the analysis nodes: (2 analysis nodes, 1 dataview, 1 layer)', function () {
|
|
var analysis0 = this.analysisService.analyse({
|
|
id: 'a0',
|
|
type: 'source',
|
|
query: 'SELECT * FROM subway_stops'
|
|
});
|
|
|
|
var analysis1 = this.analysisService.analyse({
|
|
id: 'a1',
|
|
type: 'source',
|
|
query: 'SELECT * FROM bus_stops'
|
|
});
|
|
|
|
var layer = new CartoDBLayer({ source: analysis0 }, { engine: engineMock });
|
|
var dataview = new Dataview({ id: 'dataview1', source: analysis1 }, { map: {}, engine: engineMock });
|
|
|
|
var layersCollection = new Backbone.Collection([layer]);
|
|
var dataviewsCollection = new Backbone.Collection([dataview]);
|
|
|
|
var expected = [analysis0, analysis1];
|
|
var actual = AnalysisService.getUniqueAnalysisNodes(layersCollection, dataviewsCollection);
|
|
|
|
expect(actual.length).toEqual(expected.length);
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
|
|
it('Should return the analysis nodes: (3 analysis nodes, 1 dataview, 2 layers)', function () {
|
|
var analysisA = this.analysisService.analyse(
|
|
{
|
|
id: 'a2',
|
|
type: 'estimated-population',
|
|
params: {
|
|
columnName: 'estimated_people',
|
|
source: {
|
|
id: 'a1',
|
|
type: 'trade-area',
|
|
params: {
|
|
kind: 'walk',
|
|
time: 300,
|
|
source: {
|
|
id: 'a0',
|
|
type: 'source',
|
|
params: {
|
|
query: 'SELECT * FROM subway_stops'
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
);
|
|
var analysisNodes = analysisA.getNodesCollection();
|
|
|
|
var analysis0 = analysisNodes.get('a0');
|
|
var analysis1 = analysisNodes.get('a1');
|
|
var analysis2 = analysisNodes.get('a2');
|
|
|
|
var layer0 = new CartoDBLayer({ source: analysis0 }, { engine: engineMock });
|
|
var layer1 = new CartoDBLayer({ source: analysis2 }, { engine: engineMock });
|
|
var dataview = new Dataview({ id: 'dataview1', source: analysis1 }, { map: {}, engine: engineMock });
|
|
|
|
var layersCollection = new Backbone.Collection([layer0, layer1]);
|
|
var dataviewsCollection = new Backbone.Collection([dataview]);
|
|
|
|
var expected = [analysis0, analysis2, analysis1];
|
|
var actual = AnalysisService.getUniqueAnalysisNodes(layersCollection, dataviewsCollection);
|
|
|
|
// This specs make easy to know what went wrong when the test fails.
|
|
expect(actual.length).toEqual(expected.length);
|
|
expect(actual[0].id).toEqual(expected[0].id);
|
|
expect(actual[1].id).toEqual(expected[1].id);
|
|
expect(actual[2].id).toEqual(expected[2].id);
|
|
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
|
|
it('should compact layers and dataviews if they do not have sources. It happens in named maps.', function () {
|
|
var analysis = this.analysisService.analyse({
|
|
id: 'a0',
|
|
type: 'source',
|
|
params: {
|
|
query: 'SELECT * FROM subway_stops'
|
|
}
|
|
});
|
|
var layer = new CartoDBLayer({ source: analysis }, { engine: engineMock });
|
|
var dataview = new Dataview({ id: 'dataview1', source: analysis }, { map: {}, engine: engineMock });
|
|
layer.set('source', undefined, { silent: true });
|
|
dataview.set('source', undefined, { silent: true });
|
|
var layersCollection = new Backbone.Collection([layer]);
|
|
var dataviewsCollection = new Backbone.Collection([dataview]);
|
|
|
|
var nodes = AnalysisService.getUniqueAnalysisNodes(layersCollection, dataviewsCollection);
|
|
|
|
expect(_.isArray(nodes)).toBe(true);
|
|
expect(nodes.length).toBe(0);
|
|
});
|
|
});
|
|
});
|