Initial commit

This commit is contained in:
zhongjin
2020-06-13 18:34:34 +08:00
commit 52aaa9f15d
655 changed files with 96796 additions and 0 deletions
+516
View File
@@ -0,0 +1,516 @@
var _ = require('underscore');
var Backbone = require('backbone');
var AnalysisModel = require('../../../src/analysis/analysis-model.js');
var AnalysisService = require('../../../src/analysis/analysis-service.js');
var fakeCamshaftReference = {
getSourceNamesForAnalysisType: function (analysisType) {
var map = {
'analysis-type-1': ['source1', 'source2'],
'trade-area': ['source'],
'estimated-population': ['source'],
'sql-function': ['source', 'target']
};
return map[analysisType];
},
getParamNamesForAnalysisType: function (analysisType) {
var map = {
'analysis-type-1': ['attribute1', 'attribute2'],
'trade-area': ['kind', 'time'],
'estimated-population': ['columnName']
};
return map[analysisType];
}
};
var createFakeEngine = function () {
var engine = new Backbone.Model();
engine.reload = jasmine.createSpy('reload');
return engine;
};
var createFakeAnalysis = function (attrs, engine) {
return new AnalysisModel(attrs, {
engine: engine,
camshaftReference: fakeCamshaftReference
});
};
describe('src/analysis/analysis-model.js', function () {
var engineMock;
beforeEach(function () {
engineMock = createFakeEngine();
this.analysisModel = createFakeAnalysis({
type: 'analysis-type-1',
attribute1: 'value1',
attribute2: 'value2'
}, engineMock);
});
describe('.url', function () {
it('should append the api_key param if present (and not use the authToken)', function () {
this.analysisModel.set({
url: 'http://example.com',
apiKey: 'THE_API_KEY',
authToken: 'THE_AUTH_TOKEN'
});
expect(this.analysisModel.url()).toEqual('http://example.com?api_key=THE_API_KEY');
});
it('should append the auth_token param if present (and not use the authToken)', function () {
this.analysisModel.set({
url: 'http://example.com',
authToken: 'THE_AUTH_TOKEN'
});
expect(this.analysisModel.url()).toEqual('http://example.com?auth_token=THE_AUTH_TOKEN');
});
});
describe('bindings', function () {
describe('on params change', function () {
it('should reload the map', function () {
this.analysisModel.set({
attribute1: 'newValue1'
});
expect(engineMock.reload).toHaveBeenCalled();
engineMock.reload.calls.reset();
this.analysisModel.set({
attribute2: 'newValue2'
});
expect(engineMock.reload).toHaveBeenCalled();
engineMock.reload.calls.reset();
this.analysisModel.set({
attribute900: 'something'
});
expect(engineMock.reload).not.toHaveBeenCalled();
});
it('should be marked as failed if request to reload the map fails', function () {
this.analysisModel.set({
attribute1: 'newValue1',
status: AnalysisModel.STATUS.READY
});
// Request to the Maps API fails and error callback is invoked...
engineMock.reload.calls.argsFor(0)[0].error('something bad just happened');
expect(this.analysisModel.get('status')).toEqual(AnalysisModel.STATUS.FAILED);
});
});
describe('on type change', function () {
it('should unbind old params and bind new params', function () {
spyOn(this.analysisModel, '_initBinds').and.callThrough();
spyOn(this.analysisModel, 'unbind').and.callThrough();
this.analysisModel.set('type', 'new!');
expect(this.analysisModel.unbind).toHaveBeenCalled();
expect(this.analysisModel._initBinds).toHaveBeenCalled();
});
it('should reload the map', function () {
this.analysisModel.set('type', 'something');
expect(engineMock.reload).toHaveBeenCalled();
});
it('should keep listening type change again', function () {
this.analysisModel.set('type', 'something');
expect(engineMock.reload).toHaveBeenCalled();
engineMock.reload.calls.reset();
this.analysisModel.set('type', 'something else');
expect(engineMock.reload).toHaveBeenCalled();
});
});
describe('on status change', function () {
var createAnalysisModelNoStatusNoReferences = function (engine) {
var analysisModel = createFakeAnalysis({ id: 'a0' }, engine);
return analysisModel;
};
var createAnalysisModelNoStatusWithReferences = function (engine) {
var analysisModel = createFakeAnalysis({ id: 'a0' }, engine);
analysisModel.markAsSourceOf(new Backbone.Model());
return analysisModel;
};
var createAnalysisModelWithStatusNoReferences = function (engine) {
var analysisModel = createFakeAnalysis({ id: 'a0', status: 'foo' }, engine);
return analysisModel;
};
var createAnalysisModelWithStatusWithReferences = function (engine) {
var analysisModel = createFakeAnalysis({ id: 'a0', status: 'foo' }, engine);
analysisModel.markAsSourceOf(new Backbone.Model());
return analysisModel;
};
var testCases = [
{
testName: 'analysis with no previous status and no references',
createAnalysisFn: createAnalysisModelNoStatusNoReferences,
expectedVisReloadWhenStatusIn: [] // no relaod is expected
},
{
testName: 'analysis with no previous status and some references',
createAnalysisFn: createAnalysisModelNoStatusWithReferences,
expectedVisReloadWhenStatusIn: [] // no reload is expected
},
{
testName: 'analysis with previous status and no references',
createAnalysisFn: createAnalysisModelWithStatusNoReferences,
expectedVisReloadWhenStatusIn: [] // no reload is expected
},
{
testName: 'analysis with previous status and references',
createAnalysisFn: createAnalysisModelWithStatusWithReferences,
expectedVisReloadWhenStatusIn: [ AnalysisModel.STATUS.READY ]
}
];
_.forEach(testCases, function (testCase) {
var testName = testCase.testName;
var createAnalysisFn = testCase.createAnalysisFn;
var expectedVisReloadWhenStatusIn = testCase.expectedVisReloadWhenStatusIn;
var notExpectedVisReloadWhenStatusIn = [];
describe(testName, function () {
var analysisModel;
var engineMock;
beforeEach(function () {
engineMock = createFakeEngine();
analysisModel = createAnalysisFn(engineMock);
});
_.forEach(AnalysisModel.STATUS, function (status) {
if (expectedVisReloadWhenStatusIn.indexOf(status) < 0) {
notExpectedVisReloadWhenStatusIn.push(status);
}
});
_.each(expectedVisReloadWhenStatusIn, function (status) {
it("should reload the engine if analysis is now '" + status + "'", function () {
expect(engineMock.reload).not.toHaveBeenCalled();
analysisModel.set('status', status);
expect(engineMock.reload).toHaveBeenCalled();
});
}, this);
_.each(notExpectedVisReloadWhenStatusIn, function (status) {
it("should NOT reload the engine if analysis is now '" + status + "'", function () {
expect(engineMock.reload).not.toHaveBeenCalled();
analysisModel.set('status', status);
expect(engineMock.reload).not.toHaveBeenCalled();
});
}, this);
});
});
});
});
describe('.findAnalysisById', function () {
it('should find a node in the graph', function () {
var fakeCamshaftReference = {
getSourceNamesForAnalysisType: function (analysisType) {
var map = {
'analysis-type-1': ['source1', 'source2'],
'analysis-type-2': [],
'analysis-type-3': ['source3'],
'analysis-type-4': [],
'analysis-type-5': ['source4', 'source5']
};
return map[analysisType];
},
getParamNamesForAnalysisType: function (analysisType) {
var map = {
'analysis-type-1': ['a'],
'analysis-type-2': [],
'analysis-type-3': [],
'analysis-type-4': ['a4'],
'analysis-type-5': []
};
return map[analysisType];
}
};
var analysisService = new AnalysisService({
engine: engineMock,
camshaftReference: fakeCamshaftReference
});
var analysisModel = analysisService.analyse({
id: 'a1',
type: 'analysis-type-1',
params: {
a: 1,
source1: {
id: 'a2',
type: 'analysis-type-2',
params: {
a2: 2
}
},
source2: {
id: 'a3',
type: 'analysis-type-3',
params: {
source3: {
id: 'a5',
type: 'analysis-type-5',
params: {
source4: {
id: 'a4',
type: 'analysis-type-4',
params: {
a4: 4
}
}
}
}
}
}
}
});
expect(analysisModel.findAnalysisById('a1')).toEqual(analysisModel);
expect(analysisModel.findAnalysisById('a2').get('id')).toEqual('a2');
expect(analysisModel.findAnalysisById('a3').get('id')).toEqual('a3');
expect(analysisModel.findAnalysisById('a5').get('id')).toEqual('a5');
expect(analysisModel.findAnalysisById('b9')).toBeUndefined();
});
});
describe('.toJSON', function () {
it('should serialize the graph', function () {
var fakeCamshaftReference = {
getSourceNamesForAnalysisType: function (analysisType) {
var map = {
'analysis-type-1': ['source1', 'source2'],
'analysis-type-2': [],
'analysis-type-3': ['source3'],
'analysis-type-4': [],
'analysis-type-5': ['source4', 'source5']
};
return map[analysisType];
},
getParamNamesForAnalysisType: function (analysisType) {
var map = {
'analysis-type-1': ['a'],
'analysis-type-2': ['a2'],
'analysis-type-3': [],
'analysis-type-4': ['a4'],
'analysis-type-5': []
};
return map[analysisType];
},
isSourceNameOptionalForAnalysisType: function (analysisType, sourceName) {
return (analysisType === 'analysis-type-5' && sourceName === 'source5');
}
};
var analysisService = new AnalysisService({
engine: engineMock,
camshaftReference: fakeCamshaftReference
});
var analysisModel = analysisService.analyse({
id: 'a1',
type: 'analysis-type-1',
params: {
a: 1,
source1: {
id: 'a2',
type: 'analysis-type-2',
params: {
a2: 2
}
},
source2: {
id: 'a3',
type: 'analysis-type-3',
params: {
source3: {
id: 'a4',
type: 'analysis-type-4',
params: {
a4: {
id: 'a5',
type: 'analysis-type-5',
params: {
source4: {
id: 'a6',
type: 'analysis-type-2',
params: {
a2: 2
}
}
}
}
}
}
}
}
}
});
expect(analysisModel.toJSON()).toEqual({
id: 'a1',
type: 'analysis-type-1',
params: {
a: 1,
source1: {
id: 'a2',
type: 'analysis-type-2',
params: {
a2: 2
}
},
source2: {
id: 'a3',
type: 'analysis-type-3',
params: {
source3: {
id: 'a4',
type: 'analysis-type-4',
params: {
a4: {
id: 'a5',
type: 'analysis-type-5',
params: {
source4: {
id: 'a6',
type: 'analysis-type-2',
params: {
a2: 2
}
}
}
}
}
}
}
}
}
});
});
});
describe('.isDone', function () {
it('should return true if analysis has been calculated', function () {
this.analysisModel.set('status', AnalysisModel.STATUS.READY);
expect(this.analysisModel.isDone()).toEqual(true);
this.analysisModel.set('status', AnalysisModel.STATUS.FAILED);
expect(this.analysisModel.isDone()).toEqual(true);
});
it('should return false if analysis has NOT been calculated', function () {
this.analysisModel.set('status', AnalysisModel.STATUS.PENDING);
expect(this.analysisModel.isDone()).toEqual(false);
this.analysisModel.set('status', AnalysisModel.STATUS.WAITING);
expect(this.analysisModel.isDone()).toEqual(false);
this.analysisModel.set('status', AnalysisModel.STATUS.RUNNING);
expect(this.analysisModel.isDone()).toEqual(false);
});
});
describe('.setOk', function () {
it('should unset error attribute', function () {
this.analysisModel.set('error', 'error');
this.analysisModel.setOk();
expect(this.analysisModel.get('error')).toBeUndefined();
});
});
describe('.setError', function () {
it('should set error attribute', function () {
this.analysisModel.setError('wadus');
expect(this.analysisModel.get('error')).toEqual('wadus');
});
it('should set analyis as failed', function () {
this.analysisModel.setError('wadus');
expect(this.analysisModel.get('status')).toEqual(AnalysisModel.STATUS.FAILED);
});
});
describe('.getNodes', function () {
var analysisService;
beforeEach(function () {
analysisService = new AnalysisService({
engine: engineMock,
camshaftReference: fakeCamshaftReference
});
});
it('Should return a list of nodes from an analysis', function () {
var analysis = 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 actual = analysis.getNodes();
expect(actual.length).toEqual(3);
});
});
describe('references tracking', function () {
it('should allow keeping track of models that reference this object', function () {
var model1 = new Backbone.Model();
var model2 = new Backbone.Model();
expect(this.analysisModel.isSourceOfAnyModel()).toBe(false);
this.analysisModel.markAsSourceOf(model1);
expect(this.analysisModel.isSourceOfAnyModel()).toBe(true);
this.analysisModel.markAsSourceOf(model1);
expect(this.analysisModel.isSourceOfAnyModel()).toBe(true);
this.analysisModel.markAsSourceOf(model2);
expect(this.analysisModel.isSourceOfAnyModel()).toBe(true);
this.analysisModel.unmarkAsSourceOf(model1);
expect(this.analysisModel.isSourceOfAnyModel()).toBe(true);
this.analysisModel.unmarkAsSourceOf(model2);
expect(this.analysisModel.isSourceOfAnyModel()).toBe(false);
});
});
});
+105
View File
@@ -0,0 +1,105 @@
var _ = require('underscore');
var Backbone = require('backbone');
var AnalysisModel = require('../../../src/analysis/analysis-model');
var AnalysisPoller = require('../../../src/analysis/analysis-poller');
describe('src/analysis/analysis-poller', function () {
beforeEach(function () {
jasmine.clock().install();
var engineMock = new Backbone.Model();
this.reference = jasmine.createSpyObj('reference', ['getParamNamesForAnalysisType']);
this.analysisModel1 = new AnalysisModel({
id: 'a1',
url: 'http://carto.com/foo/bar'
}, { engine: engineMock, camshaftReference: this.reference });
this.analysisPoller = new AnalysisPoller();
});
afterEach(function () {
jasmine.clock().uninstall();
});
describe('.resetAnalysisNodes', function () {
_.each([AnalysisModel.STATUS.PENDING, AnalysisModel.STATUS.WAITING, AnalysisModel.STATUS.RUNNING], function (status) {
it('should start polling if status of an analysis is "' + status + '"', function () {
this.analysisModel1.set({
'status': status
});
spyOn(this.analysisModel1, 'fetch').and.callFake(function (options) {
options.success();
});
this.analysisPoller.resetAnalysisNodes([ this.analysisModel1 ]);
expect(this.analysisModel1.fetch).toHaveBeenCalled();
expect(this.analysisModel1.fetch.calls.count()).toEqual(1);
// Wait until next fetch is triggered
jasmine.clock().tick(AnalysisPoller.CONFIG.START_DELAY + 1);
expect(this.analysisModel1.fetch.calls.count()).toEqual(2);
// Wait until next fetch is triggered
jasmine.clock().tick(AnalysisPoller.CONFIG.START_DELAY * AnalysisPoller.CONFIG.DELAY_MULTIPLIER + 1);
expect(this.analysisModel1.fetch.calls.count()).toEqual(3);
});
});
_.each([AnalysisModel.STATUS.READY, AnalysisModel.STATUS.FAILED], function (newStatus) {
it('should stop polling if status of an analysis changes to "' + newStatus + '"', function () {
spyOn(this.analysisModel1, 'fetch').and.callFake(function (options) {
this.analysisModel1.set('status', newStatus, { silent: true });
options.success();
}.bind(this));
this.analysisModel1.set({
'status': 'pending'
});
this.analysisPoller.resetAnalysisNodes([ this.analysisModel1 ]);
expect(this.analysisModel1.fetch).toHaveBeenCalled();
expect(this.analysisModel1.fetch.calls.count()).toEqual(1);
// Wait until next fetch is triggered
jasmine.clock().tick(AnalysisPoller.CONFIG.START_DELAY + 1);
expect(this.analysisModel1.fetch.calls.count()).toEqual(1);
});
});
});
describe('.reset', function () {
it('should reset all pollers', function () {
this.analysisModel1.set({
'status': 'pending'
});
spyOn(this.analysisModel1, 'fetch').and.callFake(function (options) {
options.success();
});
this.analysisPoller.resetAnalysisNodes([ this.analysisModel1 ]);
expect(this.analysisModel1.fetch).toHaveBeenCalled();
expect(this.analysisModel1.fetch.calls.count()).toEqual(1);
// Wait until next fetch is triggered
jasmine.clock().tick(AnalysisPoller.CONFIG.START_DELAY + 1);
// Polling is working
expect(this.analysisModel1.fetch.calls.count()).toEqual(2);
this.analysisPoller.reset();
// Wait until next fetch is supposed to be triggered
jasmine.clock().tick(AnalysisPoller.CONFIG.START_DELAY * AnalysisPoller.CONFIG.DELAY_MULTIPLIER + 1);
// Polling has been stopped
expect(this.analysisModel1.fetch.calls.count()).toEqual(2);
});
});
});
+357
View File
@@ -0,0 +1,357 @@
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);
});
});
});
@@ -0,0 +1,19 @@
var camshaftReference = require('../../../src/analysis/camshaft-reference');
describe('src/analysis/camshaft-reference', function () {
describe('.getSourceNamesForAnalysisType', function () {
it('should return the source names for a given analyses type', function () {
expect(camshaftReference.getSourceNamesForAnalysisType('source')).toEqual([]);
expect(camshaftReference.getSourceNamesForAnalysisType('point-in-polygon')).toEqual(['points_source', 'polygons_source']);
expect(camshaftReference.getSourceNamesForAnalysisType('trade-area')).toEqual(['source']);
});
});
describe('.getParamNamesForAnalysisType', function () {
it('should return the params names for a given analyses type', function () {
expect(camshaftReference.getParamNamesForAnalysisType('source')).toEqual(['query']);
expect(camshaftReference.getParamNamesForAnalysisType('point-in-polygon')).toEqual(['points_source', 'polygons_source']);
expect(camshaftReference.getParamNamesForAnalysisType('trade-area')).toEqual([ 'source', 'kind', 'time', 'isolines', 'dissolved' ]);
});
});
});