1633 lines
48 KiB
JavaScript
1633 lines
48 KiB
JavaScript
var _ = require('underscore');
|
|
var $ = require('jquery');
|
|
var cdb = require('internal-carto.js');
|
|
var d3 = require('d3');
|
|
var WidgetHistogramChart = require('../../../../../javascripts/deep-insights/widgets/histogram/chart');
|
|
var viewportUtils = require('../../../../../javascripts/deep-insights/viewport-utils');
|
|
var formatter = require('../../../../../javascripts/deep-insights/formatter');
|
|
|
|
function flushAllD3Transitions () {
|
|
var now = Date.now;
|
|
Date.now = function () { return Infinity; };
|
|
d3.timer.flush();
|
|
Date.now = now;
|
|
}
|
|
|
|
describe('widgets/histogram/chart', function () {
|
|
var forceResizeReal;
|
|
var forceResizeSpy;
|
|
var generateHandlesSpy;
|
|
var setupBrushSpy;
|
|
var createFormatterSpy;
|
|
|
|
afterEach(function () {
|
|
$('.js-chart').remove();
|
|
});
|
|
|
|
beforeEach(function () {
|
|
d3.select('body').append('svg').attr('class', 'js-chart');
|
|
|
|
this.width = 300;
|
|
this.height = 72;
|
|
|
|
d3.select($('.js-chart')[0])
|
|
.attr('width', this.width)
|
|
.attr('height', this.height)
|
|
.append('g')
|
|
.attr('class', 'Canvas');
|
|
|
|
this.data = genHistogramData(20);
|
|
this.margin = {
|
|
top: 4,
|
|
right: 4,
|
|
bottom: 4,
|
|
left: 4
|
|
};
|
|
|
|
this.originalData = genHistogramData(20);
|
|
this.originalModel = new cdb.core.Model({
|
|
data: this.originalData,
|
|
start: this.originalData[0].start,
|
|
end: this.originalData[this.originalData.length - 1].end,
|
|
bins: 20
|
|
});
|
|
this.originalModel.getData = function () {
|
|
return this.originalData;
|
|
}.bind(this);
|
|
|
|
// override default behavior of debounce, to be able to control callback
|
|
forceResizeSpy = jasmine.createSpy('forceResize');
|
|
spyOn(_, 'debounce').and.callFake(function (cb) {
|
|
forceResizeReal = cb;
|
|
return forceResizeSpy;
|
|
});
|
|
|
|
this.widgetModel = new cdb.core.Model({
|
|
style: {
|
|
auto_style: {
|
|
definition: {
|
|
point: {
|
|
color: {
|
|
attribute: 'whatever',
|
|
range: ['#FABADA', '#F00000', '#000000']
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
this.widgetModel.getWidgetColor = function () { return ''; };
|
|
this.widgetModel.getAutoStyle = function () { return this.attributes.style.auto_style; };
|
|
this.widgetModel.isAutoStyleEnabled = function () { return true; };
|
|
this.widgetModel.isAutoStyle = function () { return false; };
|
|
|
|
spyOn(WidgetHistogramChart.prototype, '_refreshBarsColor').and.callThrough();
|
|
spyOn(WidgetHistogramChart.prototype, '_setupFillColor').and.callThrough();
|
|
|
|
this.dataviewModel = new cdb.core.Model({
|
|
aggregation: 'minute',
|
|
offset: 0
|
|
});
|
|
this.dataviewModel.getCurrentOffset = function () {
|
|
return 0;
|
|
};
|
|
this.layerModel = new cdb.core.Model();
|
|
|
|
this.view = new WidgetHistogramChart(({
|
|
el: $('.js-chart'),
|
|
type: 'histogram',
|
|
margin: this.margin,
|
|
chartBarColor: '#9DE0AD',
|
|
hasHandles: true,
|
|
height: this.height,
|
|
data: this.data,
|
|
dataviewModel: this.dataviewModel,
|
|
layerModel: this.layerModel,
|
|
originalData: this.originalModel,
|
|
displayShadowBars: true,
|
|
widgetModel: this.widgetModel,
|
|
local_timezone: false,
|
|
xAxisTickFormat: function (d, i) {
|
|
return d;
|
|
}
|
|
}));
|
|
|
|
var parentSpy = jasmine.createSpyObj('view.$el.parent()', ['width']);
|
|
parentSpy.width.and.returnValue(this.width);
|
|
spyOn(this.view.$el, 'parent');
|
|
this.view.$el.parent.and.returnValue(parentSpy);
|
|
|
|
generateHandlesSpy = spyOn(this.view, '_generateHandles');
|
|
setupBrushSpy = spyOn(this.view, '_setupBrush');
|
|
createFormatterSpy = spyOn(this.view, '_createFormatter');
|
|
spyOn(this.view, 'refresh').and.callThrough();
|
|
|
|
this.view.render();
|
|
});
|
|
|
|
it('should be hidden initially', function () {
|
|
expect(this.view.$el.attr('style')).toMatch('none');
|
|
});
|
|
|
|
it('should setup the fill color initially', function () {
|
|
expect(WidgetHistogramChart.prototype._setupFillColor).toHaveBeenCalled();
|
|
expect(this.view._autoStyleColorsScale).toBeUndefined();
|
|
});
|
|
|
|
describe('normalize', function () {
|
|
it('should normalize', function () {
|
|
spyOn(this.view, 'updateYScale');
|
|
|
|
this.view.setNormalized(true);
|
|
|
|
expect(this.view.model.get('normalized')).toEqual(true);
|
|
expect(this.view.updateYScale).toHaveBeenCalled();
|
|
expect(this.view.refresh).toHaveBeenCalled();
|
|
});
|
|
|
|
it('should denormalize', function () {
|
|
spyOn(this.view, 'updateYScale');
|
|
|
|
this.view.setNormalized(false);
|
|
|
|
expect(this.view.model.get('normalized')).toEqual(false);
|
|
expect(this.view.updateYScale).toHaveBeenCalled();
|
|
expect(this.view.refresh).toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
describe('shadow bars', function () {
|
|
it('should not show shadow bars', function () {
|
|
this.view.options.displayShadowBars = false;
|
|
this.view.model.set('show_shadow_bars', false);
|
|
|
|
expect(this.view.$('.CDB-Chart-shadowBars').length).toBe(0);
|
|
|
|
this.originalModel.trigger('change:data');
|
|
|
|
expect(this.view.$('.CDB-Chart-shadowBars').length).toBe(0);
|
|
|
|
this.view.showShadowBars();
|
|
|
|
expect(this.view.$('.CDB-Chart-shadowBars').length).toBe(0);
|
|
});
|
|
|
|
it('should remove and generate shadow bars when original data chagnes', function () {
|
|
spyOn(this.view, '_removeShadowBars');
|
|
spyOn(this.view, '_generateShadowBars');
|
|
|
|
this.originalModel.trigger('change:data');
|
|
|
|
expect(this.view._removeShadowBars).toHaveBeenCalled();
|
|
expect(this.view._generateShadowBars).toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
describe('when view is resized but set to not be shown just yet', function () {
|
|
beforeEach(function () {
|
|
expect(this.view.options.showOnWidthChange).toBe(true); // assert default value, in case it's changed
|
|
this.view.options.showOnWidthChange = false;
|
|
});
|
|
|
|
it('should not show view', function () {
|
|
expect(this.view.$el.attr('style')).toMatch('none');
|
|
});
|
|
});
|
|
|
|
describe('when view is resized', function () {
|
|
beforeEach(function () {
|
|
forceResizeReal.call(this);
|
|
expect(this.view.$el.parent).toHaveBeenCalled();
|
|
});
|
|
|
|
it('should render the view', function () {
|
|
expect(this.view.$el.attr('style')).not.toMatch('none');
|
|
});
|
|
|
|
it('should calculate the width of the bars', function () {
|
|
expect(this.view.barWidth).toBe((this.width - this.margin.left - this.margin.right) / this.data.length);
|
|
});
|
|
|
|
it('should draw the bars', function () {
|
|
expect(this.view.$('.CDB-Chart-bar').size()).toBe(this.data.length);
|
|
});
|
|
|
|
it('should draw the axis', function () {
|
|
expect(this.view.$el.find('.CDB-Chart-axis').size()).toBe(1);
|
|
});
|
|
|
|
it('should draw the handles', function () {
|
|
generateHandlesSpy.and.callThrough();
|
|
|
|
this.view._generateHandles();
|
|
|
|
expect(this.view.$el.find('.CDB-Chart-handle').size()).toBe(2);
|
|
});
|
|
|
|
it('should hide the chart', function () {
|
|
expect(this.view.$el.css('display')).toBe('inline');
|
|
|
|
this.view.hide();
|
|
|
|
expect(this.view.isHidden()).toBe(true);
|
|
expect(this.view.model.get('display')).toBe(false);
|
|
expect(this.view.$el.css('display')).toBe('none');
|
|
});
|
|
|
|
it('should show the chart', function () {
|
|
this.view.hide();
|
|
this.view.show();
|
|
expect(this.view.$el.css('display')).toBe('inline');
|
|
});
|
|
|
|
it('should set the parent width', function () {
|
|
this.view.show();
|
|
this.view._resizeToParentElement();
|
|
expect(this.view.model.get('width')).toBe(this.width);
|
|
});
|
|
|
|
it('should generate the shadow bars', function () {
|
|
expect(this.view.$el.find('.CDB-Chart-shadowBars').length).toBe(1);
|
|
});
|
|
|
|
it('should hide the shadow bars', function () {
|
|
this.view.removeShadowBars();
|
|
expect(this.view.$el.find('.CDB-Chart-shadowBars').length).toBe(0);
|
|
});
|
|
|
|
it('should maintain the visibility after calling _resizeToParentElement', function () {
|
|
this.view.show();
|
|
this.view._resizeToParentElement();
|
|
expect(this.view.$el.css('display')).toBe('inline');
|
|
expect(this.view.model.get('display')).toBe(true);
|
|
|
|
this.view.hide();
|
|
this.view._resizeToParentElement();
|
|
expect(this.view.$el.css('display')).toBe('none');
|
|
expect(this.view.model.get('display')).toBe(false);
|
|
});
|
|
|
|
it('should calculate the scales', function () {
|
|
expect(this.view.xScale(0)).toBe(0);
|
|
expect(this.view.xScale(100)).toMatch(/\d+/);
|
|
expect(this.view.xScale(100)).toEqual(this.view.chartWidth());
|
|
expect(this.view.yScale(0)).toMatch(/\d+/);
|
|
expect(this.view.yScale(0)).toEqual(this.view.chartHeight());
|
|
});
|
|
|
|
it('should refresh the data', function () {
|
|
this.view.show();
|
|
this.view.model.set({ data: updateHistogramData(20) });
|
|
expect(this.view.refresh).toHaveBeenCalled();
|
|
});
|
|
|
|
describe('animated', function () {
|
|
it('should set the parent width', function () {
|
|
var animatedWidth = 24;
|
|
spyOn(this.view.$el, 'siblings').and.returnValue($('<div>'));
|
|
spyOn($.prototype, 'width').and.returnValue(animatedWidth);
|
|
|
|
this.view.model.set('animated', true);
|
|
this.view.show();
|
|
this.view._resizeToParentElement();
|
|
|
|
expect(this.view.model.get('width')).toBe(this.width - animatedWidth);
|
|
});
|
|
});
|
|
|
|
describe('should allow to manage the y scale', function () {
|
|
beforeEach(function () {
|
|
this.originalScale = this.view.yScale;
|
|
this.view.model.set('data', genHistogramData(10));
|
|
});
|
|
|
|
it('should calculate the y scale on request', function () {
|
|
expect(this.view.yScale).toEqual(this.originalScale);
|
|
|
|
this.view.updateYScale();
|
|
expect(this.view.yScale).not.toEqual(this.originalScale);
|
|
});
|
|
|
|
it('should restore the y scale on request', function () {
|
|
this.view.resetYScale();
|
|
expect(this.view.yScale).toEqual(this.originalScale);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('_calculateDataDomain', function () {
|
|
beforeEach(function () {
|
|
this.applyNewData = function (d) {
|
|
this.view.model.attributes.data = d;
|
|
};
|
|
});
|
|
|
|
describe('without filter', function () {
|
|
beforeEach(function () {
|
|
spyOn(this.view, '_hasFilterApplied').and.returnValue(false);
|
|
});
|
|
|
|
describe('all bins with freq data', function () {
|
|
it('should return the min and max value from the first and last bins', function () {
|
|
this.applyNewData([
|
|
{
|
|
min: 0,
|
|
max: 2,
|
|
freq: 1
|
|
},
|
|
{
|
|
min: 2.1,
|
|
max: 4,
|
|
freq: 3
|
|
},
|
|
{
|
|
min: 4.1,
|
|
max: 6,
|
|
freq: 2
|
|
}
|
|
]);
|
|
|
|
expect(this.view._calculateDataDomain()).toEqual([0, 6]);
|
|
});
|
|
|
|
it('should return null when there is no data', function () {
|
|
this.applyNewData([]);
|
|
|
|
expect(this.view._calculateDataDomain()).toEqual([null, null]);
|
|
});
|
|
});
|
|
|
|
describe('not all bins with freq data', function () {
|
|
it('should return start and end values from bins with frequency (1)', function () {
|
|
this.applyNewData([
|
|
{
|
|
min: 0,
|
|
max: 2,
|
|
freq: 0
|
|
},
|
|
{
|
|
min: 2.1,
|
|
max: 4,
|
|
freq: 3
|
|
},
|
|
{
|
|
min: 4.1,
|
|
max: 6,
|
|
freq: 2
|
|
}
|
|
]);
|
|
expect(this.view._calculateDataDomain()).toEqual([2.1, 6]);
|
|
});
|
|
|
|
it('should return start and end values from bins with frequency (2)', function () {
|
|
this.applyNewData([
|
|
{
|
|
min: 1,
|
|
max: 2,
|
|
freq: 2
|
|
},
|
|
{
|
|
min: 2.1,
|
|
max: 4,
|
|
freq: 3
|
|
},
|
|
{
|
|
min: 6.1,
|
|
max: 8,
|
|
freq: 0
|
|
}
|
|
]);
|
|
expect(this.view._calculateDataDomain()).toEqual([1, 4]);
|
|
});
|
|
|
|
it('should return start and end values from bins with frequency (3)', function () {
|
|
this.applyNewData([
|
|
{
|
|
min: 0,
|
|
max: 2,
|
|
freq: 0
|
|
},
|
|
{
|
|
min: 2.1,
|
|
max: 4,
|
|
freq: 3
|
|
},
|
|
{
|
|
min: 4.1,
|
|
max: 6,
|
|
freq: 2
|
|
},
|
|
{
|
|
min: 6.1,
|
|
max: 8,
|
|
freq: 0
|
|
}
|
|
]);
|
|
|
|
expect(this.view._calculateDataDomain()).toEqual([2.1, 6]);
|
|
});
|
|
|
|
it('should return start and end values from bins with frequency (4)', function () {
|
|
this.applyNewData([
|
|
{
|
|
min: 0,
|
|
max: 2,
|
|
freq: 0
|
|
},
|
|
{
|
|
min: 2.1,
|
|
max: 4,
|
|
freq: 3
|
|
},
|
|
{
|
|
min: 4.1,
|
|
max: 6,
|
|
freq: 0
|
|
},
|
|
{
|
|
min: 6.1,
|
|
max: 8,
|
|
freq: 10
|
|
},
|
|
{
|
|
min: 8.1,
|
|
max: 12,
|
|
freq: 0
|
|
}
|
|
]);
|
|
expect(this.view._calculateDataDomain()).toEqual([2.1, 8]);
|
|
});
|
|
|
|
it('should return null when there is no data', function () {
|
|
this.applyNewData([]);
|
|
|
|
expect(this.view._calculateDataDomain()).toEqual([null, null]);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('with filter', function () {
|
|
beforeEach(function () {
|
|
spyOn(this.view, '_hasFilterApplied').and.returnValue(true);
|
|
});
|
|
|
|
describe('all bins with freq data', function () {
|
|
it('should return the min and max value from the first and last bins', function () {
|
|
spyOn(this.view, '_getLoBarIndex').and.returnValue(1);
|
|
spyOn(this.view, '_getHiBarIndex').and.returnValue(2);
|
|
|
|
this.applyNewData([
|
|
{
|
|
min: 0,
|
|
max: 2,
|
|
freq: 1
|
|
},
|
|
{
|
|
min: 2.1,
|
|
max: 4,
|
|
freq: 3
|
|
},
|
|
{
|
|
min: 4.1,
|
|
max: 6,
|
|
freq: 2
|
|
}
|
|
]);
|
|
|
|
expect(this.view._calculateDataDomain()).toEqual([2.1, 4]);
|
|
});
|
|
});
|
|
|
|
describe('not all bins with freq data', function () {
|
|
it('should return start and end values from bins with frequency (1)', function () {
|
|
spyOn(this.view, '_getLoBarIndex').and.returnValue(1);
|
|
spyOn(this.view, '_getHiBarIndex').and.returnValue(2);
|
|
|
|
this.applyNewData([
|
|
{
|
|
min: 0,
|
|
max: 2,
|
|
freq: 0
|
|
},
|
|
{
|
|
min: 2.1,
|
|
max: 4,
|
|
freq: 3
|
|
},
|
|
{
|
|
min: 4.1,
|
|
max: 6,
|
|
freq: 0
|
|
}
|
|
]);
|
|
expect(this.view._calculateDataDomain()).toEqual([2.1, 4]);
|
|
});
|
|
|
|
it('should return start and end values from bins with frequency (2)', function () {
|
|
spyOn(this.view, '_getLoBarIndex').and.returnValue(1);
|
|
spyOn(this.view, '_getHiBarIndex').and.returnValue(3);
|
|
|
|
this.applyNewData([
|
|
{
|
|
min: 1,
|
|
max: 2,
|
|
freq: 2
|
|
},
|
|
{
|
|
min: 2.1,
|
|
max: 4,
|
|
freq: 3
|
|
},
|
|
{
|
|
min: 6.1,
|
|
max: 8,
|
|
freq: 0
|
|
}
|
|
]);
|
|
expect(this.view._calculateDataDomain()).toEqual([2.1, 4]);
|
|
});
|
|
|
|
it('should return start and end values from bins with frequency (3)', function () {
|
|
spyOn(this.view, '_getLoBarIndex').and.returnValue(0);
|
|
spyOn(this.view, '_getHiBarIndex').and.returnValue(4);
|
|
|
|
this.applyNewData([
|
|
{
|
|
min: 0,
|
|
max: 2,
|
|
freq: 0
|
|
},
|
|
{
|
|
min: 2.1,
|
|
max: 4,
|
|
freq: 3
|
|
},
|
|
{
|
|
min: 4.1,
|
|
max: 6,
|
|
freq: 2
|
|
},
|
|
{
|
|
min: 6.1,
|
|
max: 8,
|
|
freq: 0
|
|
},
|
|
{
|
|
min: 8.1,
|
|
max: 10,
|
|
freq: 2
|
|
}
|
|
]);
|
|
|
|
expect(this.view._calculateDataDomain()).toEqual([2.1, 6]);
|
|
});
|
|
|
|
it('should return start and end values from bins with frequency (4)', function () {
|
|
spyOn(this.view, '_getLoBarIndex').and.returnValue(1);
|
|
spyOn(this.view, '_getHiBarIndex').and.returnValue(4);
|
|
|
|
this.applyNewData([
|
|
{
|
|
min: 0,
|
|
max: 2,
|
|
freq: 0
|
|
},
|
|
{
|
|
min: 2.1,
|
|
max: 4,
|
|
freq: 3
|
|
},
|
|
{
|
|
min: 4.1,
|
|
max: 6,
|
|
freq: 0
|
|
},
|
|
{
|
|
min: 6.1,
|
|
max: 8,
|
|
freq: 10
|
|
},
|
|
{
|
|
min: 8.1,
|
|
max: 12,
|
|
freq: 0
|
|
}
|
|
]);
|
|
expect(this.view._calculateDataDomain()).toEqual([2.1, 8]);
|
|
});
|
|
|
|
it('should return start and end values from bins with frequency (5)', function () {
|
|
spyOn(this.view, '_getLoBarIndex').and.returnValue(1);
|
|
spyOn(this.view, '_getHiBarIndex').and.returnValue(5);
|
|
|
|
this.applyNewData([
|
|
{
|
|
min: 0,
|
|
max: 2,
|
|
freq: 0
|
|
},
|
|
{
|
|
min: 2.1,
|
|
max: 4,
|
|
freq: 0
|
|
},
|
|
{
|
|
min: 4.1,
|
|
max: 6,
|
|
freq: 0
|
|
},
|
|
{
|
|
min: 6.1,
|
|
max: 8,
|
|
freq: 0
|
|
},
|
|
{
|
|
min: 8.1,
|
|
max: 12,
|
|
freq: 0
|
|
}
|
|
]);
|
|
expect(this.view._calculateDataDomain()).toEqual([2.1, 12]);
|
|
});
|
|
|
|
it('should return 0, 0 when lo and hi bar indexes are NaN', function () {
|
|
spyOn(this.view, '_getLoBarIndex').and.returnValue(NaN);
|
|
spyOn(this.view, '_getHiBarIndex').and.returnValue(NaN);
|
|
|
|
this.applyNewData([
|
|
{
|
|
min: 0,
|
|
max: 2,
|
|
freq: 0
|
|
},
|
|
{
|
|
min: 2.1,
|
|
max: 4,
|
|
freq: 0
|
|
},
|
|
{
|
|
min: 4.1,
|
|
max: 6,
|
|
freq: 0
|
|
},
|
|
{
|
|
min: 6.1,
|
|
max: 8,
|
|
freq: 0
|
|
},
|
|
{
|
|
min: 8.1,
|
|
max: 12,
|
|
freq: 0
|
|
}
|
|
]);
|
|
expect(this.view._calculateDataDomain()).toEqual([0, 0]);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('_generateFillGradients', function () {
|
|
beforeEach(function () {
|
|
this.redColor = 'rgb(255, 0, 0)';
|
|
this.yellowColor = 'rgb(255, 255, 0)';
|
|
|
|
this.getLinearGradients = function () {
|
|
var defs = d3.select(this.view.el).select('defs');
|
|
return defs.selectAll('linearGradient');
|
|
};
|
|
|
|
var definitionObj = {
|
|
definition: {
|
|
point: {
|
|
color: {
|
|
range: [this.redColor, 'blue', 'brown', this.yellowColor]
|
|
}
|
|
}
|
|
}
|
|
};
|
|
spyOn(this.view._widgetModel, 'getAutoStyle').and.returnValue(definitionObj);
|
|
|
|
var data = [
|
|
{
|
|
min: 0,
|
|
max: 2,
|
|
freq: 5
|
|
},
|
|
{
|
|
min: 2.1,
|
|
max: 4,
|
|
freq: 1
|
|
},
|
|
{
|
|
min: 4.1,
|
|
max: 6,
|
|
freq: 5
|
|
},
|
|
{
|
|
min: 6.1,
|
|
max: 8,
|
|
freq: 8
|
|
},
|
|
{
|
|
min: 8.1,
|
|
max: 12,
|
|
freq: 10
|
|
}
|
|
];
|
|
|
|
this.view.model.attributes.data = data;
|
|
this.view._removeFillGradients();
|
|
this.view.el = document.createElement('svg'); // Hack it!
|
|
});
|
|
|
|
it('should not generate any gradient if auto-style colors are not provided', function () {
|
|
this.view._widgetModel.getAutoStyle.and.returnValue({});
|
|
this.view._generateFillGradients();
|
|
expect(this.getLinearGradients().length).toBe(0);
|
|
});
|
|
|
|
it('should generate as many gradients as data we have', function () {
|
|
this.view._generateFillGradients();
|
|
|
|
var defs = d3.select(this.view.el).select('defs');
|
|
var gradients = defs.selectAll('.gradient')[0];
|
|
|
|
expect(gradients.length).toBe(5);
|
|
});
|
|
|
|
it('should generate as many hover gradients as data we have', function () {
|
|
this.view._generateFillGradients();
|
|
|
|
var defs = d3.select(this.view.el).select('defs');
|
|
var gradients = defs.selectAll('.gradient-hover')[0];
|
|
|
|
expect(gradients.length).toBe(5);
|
|
});
|
|
|
|
it('should generate 5 stops in each gradient', function () {
|
|
this.view._generateFillGradients();
|
|
|
|
this.getLinearGradients().each(function (d) {
|
|
var stops = d3.select(this).selectAll('stop');
|
|
expect(stops[0].length).toBe(5);
|
|
});
|
|
});
|
|
|
|
describe('gradient generation', function () {
|
|
describe('no colors ramp', function () {
|
|
it('should not create the proper gradient ramp if bucket is out of domain', function () {
|
|
spyOn(this.view, '_calculateDataDomain').and.returnValue([2.1, 8]);
|
|
this.view._generateFillGradients();
|
|
var self = this;
|
|
|
|
// Out of domain at the beginning
|
|
d3.select(this.getLinearGradients()[0][0]).selectAll('stop').each(function (d) {
|
|
expect(this.getAttribute('stop-color')).toBe(self.redColor);
|
|
});
|
|
|
|
// Out of domain at the end
|
|
d3.select(this.getLinearGradients()[0][4]).selectAll('stop').each(function (d) {
|
|
expect(this.getAttribute('stop-color')).toBe(self.yellowColor);
|
|
});
|
|
});
|
|
|
|
it('should not create the proper gradient ramp if bucket is empty at the beginning', function () {
|
|
var self = this;
|
|
|
|
this.view.model.attributes.data[0].freq = 0;
|
|
this.view._generateFillGradients();
|
|
|
|
// No data in the first bucket
|
|
d3.select(this.getLinearGradients()[0][0]).selectAll('stop').each(function (d) {
|
|
expect(this.getAttribute('stop-color')).toBe(self.redColor);
|
|
});
|
|
});
|
|
|
|
it('should not create the proper gradient ramp if bucket is empty at the end', function () {
|
|
this.view.model.attributes.data[4].freq = 0;
|
|
this.view._generateFillGradients();
|
|
|
|
var self = this;
|
|
|
|
// No data in the last bucket
|
|
d3.select(this.getLinearGradients()[0][4]).selectAll('stop').each(function (d) {
|
|
expect(this.getAttribute('stop-color')).toBe(self.yellowColor);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('colors ramp', function () {
|
|
it('should generate the proper ramp for each gradient', function () {
|
|
this.view._generateFillGradients();
|
|
|
|
var linearGradients = this.getLinearGradients();
|
|
var firstGradient = linearGradients[0][0];
|
|
var lastGradient = linearGradients[0][4];
|
|
var middleGradient = linearGradients[0][2];
|
|
|
|
var stopsInFirstGradient = d3.select(firstGradient).selectAll('stop');
|
|
var stopsInMiddleGradient = d3.select(middleGradient).selectAll('stop');
|
|
var stopsInLastGradient = d3.select(lastGradient).selectAll('stop');
|
|
|
|
expect(stopsInFirstGradient[0][0].getAttribute('stop-color')).toBe(this.redColor);
|
|
expect(stopsInFirstGradient[0][1].getAttribute('stop-color')).not.toBe(this.redColor);
|
|
expect(stopsInLastGradient[0][4].getAttribute('stop-color')).toBe(this.yellowColor);
|
|
expect(stopsInLastGradient[0][3].getAttribute('stop-color')).not.toBe(this.yellowColor);
|
|
|
|
// Checking middle bin gradient
|
|
expect(stopsInMiddleGradient[0][0].getAttribute('stop-color')).toBe('rgb(69, 8, 177)'); // From blue
|
|
expect(stopsInMiddleGradient[0][1].getAttribute('stop-color')).toBe('rgb(68, 11, 175)');
|
|
expect(stopsInMiddleGradient[0][2].getAttribute('stop-color')).toBe('rgb(71, 14, 168)');
|
|
expect(stopsInMiddleGradient[0][3].getAttribute('stop-color')).toBe('rgb(79, 19, 157)');
|
|
expect(stopsInMiddleGradient[0][4].getAttribute('stop-color')).toBe('rgb(90, 25, 142)'); // To purple
|
|
});
|
|
|
|
it('should create the proper gradient ramp althogh all buckets are empty', function () {
|
|
var data = this.view.model.attributes.data;
|
|
_.each(data, function (d, i) {
|
|
d.freq = 0;
|
|
});
|
|
this.view._generateFillGradients();
|
|
|
|
var linearGradients = this.getLinearGradients();
|
|
var firstGradient = linearGradients[0][0];
|
|
var lastGradient = linearGradients[0][4];
|
|
var stopsInFirstGradient = d3.select(firstGradient).selectAll('stop');
|
|
var stopsInLastGradient = d3.select(lastGradient).selectAll('stop');
|
|
|
|
// No data in the last bucket
|
|
expect(stopsInFirstGradient[0][0].getAttribute('stop-color')).toBe(this.redColor);
|
|
expect(stopsInFirstGradient[0][1].getAttribute('stop-color')).not.toBe(this.redColor);
|
|
expect(stopsInLastGradient[0][4].getAttribute('stop-color')).toBe(this.yellowColor);
|
|
expect(stopsInLastGradient[0][3].getAttribute('stop-color')).not.toBe(this.yellowColor);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('on dataview layer cartocss change', function () {
|
|
it('should generate bar gradients if they were not defined before', function () {
|
|
this.view._setupFillColor.calls.reset();
|
|
spyOn(this.view, '_areGradientsAlreadyGenerated').and.returnValue(false);
|
|
this.layerModel.set('cartocss', '#dummy {}');
|
|
expect(this.view._setupFillColor.calls.count()).toBe(1);
|
|
});
|
|
|
|
it('should not generate bar gradients if they were defined before', function () {
|
|
this.view._setupFillColor.calls.reset();
|
|
spyOn(this.view, '_areGradientsAlreadyGenerated').and.returnValue(true);
|
|
this.layerModel.set('cartocss', '#dummy {}');
|
|
expect(this.view._setupFillColor.calls.count()).toBe(0);
|
|
});
|
|
});
|
|
|
|
describe('._getDataForScales', function () {
|
|
it('should calculate (x|y)Scale depending originalData if it is provided and view is not bounded', function () {
|
|
var data = this.view._getDataForScales();
|
|
expect(data).toBe(this.originalData);
|
|
expect(data).not.toBe(this.data);
|
|
});
|
|
|
|
it('should calculate (x|y)Scale depending current data if view is bounded', function () {
|
|
this.view.model.set('bounded', true);
|
|
var data = this.view._getDataForScales();
|
|
expect(data).not.toBe(this.originalData);
|
|
expect(data).toBe(this.data);
|
|
});
|
|
|
|
it('should calculate (x|y)Scale depending current data if originalData is not defined', function () {
|
|
delete this.view._originalData;
|
|
var data = this.view._getDataForScales();
|
|
expect(data).not.toBe(this.originalData);
|
|
expect(data).toBe(this.data);
|
|
});
|
|
});
|
|
|
|
describe('autostyle changes', function () {
|
|
beforeEach(function () {
|
|
this.widgetModel.set('autoStyle', true);
|
|
});
|
|
|
|
it('should trigger a refresh of the bars fill color', function () {
|
|
expect(WidgetHistogramChart.prototype._refreshBarsColor).toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
describe('style changes', function () {
|
|
beforeEach(function () {
|
|
WidgetHistogramChart.prototype._setupFillColor.calls.reset();
|
|
WidgetHistogramChart.prototype._refreshBarsColor.calls.reset();
|
|
this.widgetModel.set('style', {});
|
|
});
|
|
|
|
it('should trigger a refresh of the bars fill color', function () {
|
|
expect(WidgetHistogramChart.prototype._refreshBarsColor.calls.count()).toEqual(1);
|
|
});
|
|
|
|
it('should setup the colors scale', function () {
|
|
expect(WidgetHistogramChart.prototype._setupFillColor.calls.count()).toEqual(1);
|
|
});
|
|
});
|
|
|
|
describe('color bar', function () {
|
|
it('should be green by default', function () {
|
|
expect(this.view.$('.CDB-Chart-bar').attr('fill')).toEqual('#9DE0AD');
|
|
});
|
|
|
|
it('should be custom if widget color is different', function () {
|
|
spyOn(this.widgetModel, 'getWidgetColor').and.returnValue('red');
|
|
this.view._refreshBarsColor();
|
|
expect(this.view.$('.CDB-Chart-bar').attr('fill')).toEqual('red');
|
|
});
|
|
|
|
it('should be colored by linear gradients when autostyle is applied', function () {
|
|
spyOn(this.widgetModel, 'isAutoStyle').and.returnValue(true);
|
|
this.widgetModel.set({
|
|
style: {
|
|
auto_style: {
|
|
definition: {
|
|
point: {
|
|
color: {
|
|
attribute: 'whatever',
|
|
range: ['red', 'blue', 'green']
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
var dataSize = this.view.model.get('data').length;
|
|
_.times(dataSize, function (i) {
|
|
expect(this.view.$('.CDB-Chart-bar:eq(' + i + ')').attr('fill')).toContain('url(#bar-');
|
|
}, this);
|
|
});
|
|
});
|
|
|
|
describe('touch interfaces fixes', function () {
|
|
beforeEach(function () {
|
|
setupBrushSpy.and.callThrough();
|
|
|
|
this.view._setupBrush();
|
|
});
|
|
|
|
afterEach(function () {
|
|
$('.Brush').remove();
|
|
});
|
|
|
|
it('should mark all brush elements with ps-prevent-touchmove', function () {
|
|
var brush = this.view.$('.Brush');
|
|
|
|
var hasProperClass = function (e) {
|
|
return e.attributes.class.value.indexOf('ps-prevent-touchmove') !== 1;
|
|
};
|
|
|
|
var checkAllChildren = function (child) {
|
|
expect(hasProperClass(child)).toBe(true);
|
|
|
|
if (child.children && child.children.length > 0) {
|
|
_.forEach(child.children, checkAllChildren);
|
|
}
|
|
};
|
|
|
|
_.forEach(brush.children(), checkAllChildren);
|
|
});
|
|
});
|
|
|
|
describe('._isTabletViewport', function () {
|
|
it('should return true if viewport is tablet', function () {
|
|
spyOn($.prototype, 'width').and.returnValue(100);
|
|
spyOn(viewportUtils, 'isTabletViewport');
|
|
|
|
this.view._isTabletViewport();
|
|
|
|
expect(viewportUtils.isTabletViewport).toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
describe('._isMobileViewport', function () {
|
|
it('should return true if viewport is mobile', function () {
|
|
spyOn($.prototype, 'width').and.returnValue(100);
|
|
spyOn(viewportUtils, 'isMobileViewport');
|
|
|
|
this.view._isMobileViewport();
|
|
|
|
expect(viewportUtils.isMobileViewport).toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
describe('._isTimeSeries', function () {
|
|
it('should return true if option type is time', function () {
|
|
expect(this.view._isTimeSeries()).toBe(false);
|
|
|
|
this.view.options.type = 'time-date';
|
|
|
|
expect(this.view._isTimeSeries()).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe('._generateChartContent', function () {
|
|
it('should generate axis, lines, bars, bottom line, handles, and setup brush', function () {
|
|
spyOn(this.view, '_generateAxis');
|
|
spyOn(this.view, '_generateLines');
|
|
spyOn(this.view, '_generateBars');
|
|
spyOn(this.view, '_generateBottomLine');
|
|
|
|
this.view._generateChartContent();
|
|
|
|
expect(this.view._generateAxis).toHaveBeenCalled();
|
|
expect(this.view._generateLines).toHaveBeenCalled();
|
|
expect(this.view._generateBars).toHaveBeenCalled();
|
|
expect(this.view._generateBottomLine).toHaveBeenCalled();
|
|
expect(this.view._generateHandles).toHaveBeenCalled();
|
|
expect(this.view._setupBrush).toHaveBeenCalled();
|
|
});
|
|
|
|
describe('time-series', function () {
|
|
beforeEach(function () {
|
|
this.view._isTimeSeries = function () {
|
|
return true;
|
|
};
|
|
});
|
|
|
|
describe('mobile', function () {
|
|
beforeEach(function () {
|
|
this.view._isMobileViewport = function () {
|
|
return true;
|
|
};
|
|
});
|
|
|
|
it('should not generate lines, bottom line', function () {
|
|
spyOn(this.view, '_generateBottomLine');
|
|
|
|
this.view._generateChartContent();
|
|
|
|
expect(this.view._generateBottomLine).not.toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
describe('tablet', function () {
|
|
beforeEach(function () {
|
|
this.view._isTabletViewport = function () {
|
|
return true;
|
|
};
|
|
});
|
|
|
|
it('should not generate lines', function () {
|
|
spyOn(this.view, '_generateLines');
|
|
|
|
this.view._generateChartContent();
|
|
|
|
expect(this.view._generateLines).not.toHaveBeenCalled();
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('._generateHandle', function () {
|
|
beforeEach(function () {
|
|
generateHandlesSpy.and.callThrough();
|
|
|
|
var generateHandleSpy = spyOn(this.view, '_generateHandle');
|
|
|
|
this.view._generateHandles();
|
|
|
|
generateHandleSpy.and.callThrough();
|
|
});
|
|
|
|
afterEach(function () {
|
|
$('.CDB-Chart-handles').remove();
|
|
});
|
|
|
|
it('should generate handle', function () {
|
|
this.view._generateHandle('left');
|
|
|
|
expect(this.view.$('.CDB-Chart-handle-left .CDB-Chart-handleRect').attr('height')).toBe('48');
|
|
});
|
|
|
|
describe('time-series', function () {
|
|
beforeEach(function () {
|
|
this.view._isTimeSeries = function () {
|
|
return true;
|
|
};
|
|
});
|
|
|
|
describe('tablet', function () {
|
|
beforeEach(function () {
|
|
this.view._isTabletViewport = function () {
|
|
return true;
|
|
};
|
|
|
|
this.view.model.set({
|
|
height: 16,
|
|
margin: _.extend({}, this.view.model.get('margin'), { top: 0 }),
|
|
showLabels: false
|
|
}, { silent: true });
|
|
});
|
|
|
|
it('should generate handle', function () {
|
|
this.view._generateHandle('left');
|
|
|
|
expect(this.view.$('.CDB-Chart-handle-left .CDB-Chart-handleRect').attr('height')).toBe('24');
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('._generateAxisTip', function () {
|
|
beforeEach(function () {
|
|
generateHandlesSpy.and.callThrough();
|
|
|
|
this.view._generateHandles();
|
|
});
|
|
|
|
afterEach(function () {
|
|
$('.CDB-Chart-handles').remove();
|
|
});
|
|
|
|
describe('left', function () {
|
|
it('should generate left axis tip', function () {
|
|
this.view._generateAxisTip('left');
|
|
|
|
var textLabel = this.view.$('.CDB-Chart-axisTipText.CDB-Chart-axisTip-left');
|
|
var rectLabel = this.view.$('.CDB-Chart-axisTipRect.CDB-Chart-axisTip-left');
|
|
var axisTip = this.view.$('.CDB-Chart-axisTip.CDB-Chart-axisTip-left');
|
|
var triangle = this.view.$('.CDB-Chart-handle-left .CDB-Chart-axisTipTriangle');
|
|
|
|
expect(textLabel.attr('opacity')).toBe('1');
|
|
expect(rectLabel.attr('opacity')).toBe('1');
|
|
expect(triangle.attr('style')).toContain('opacity: 1;');
|
|
|
|
expect(axisTip.length).toBe(1);
|
|
expect(axisTip.attr('transform')).toBe('translate(0,-26)');
|
|
expect(triangle.attr('transform')).toBe('translate(-3, -11)');
|
|
});
|
|
});
|
|
|
|
describe('right', function () {
|
|
it('should generate right axis tip', function () {
|
|
this.view._generateAxisTip('right');
|
|
|
|
var textLabel = this.view.$('.CDB-Chart-axisTipText.CDB-Chart-axisTip-right');
|
|
var rectLabel = this.view.$('.CDB-Chart-axisTipRect.CDB-Chart-axisTip-right');
|
|
var axisTip = this.view.$('.CDB-Chart-axisTip.CDB-Chart-axisTip-right');
|
|
var triangle = this.view.$('.CDB-Chart-handle-right .CDB-Chart-axisTipTriangle');
|
|
|
|
expect(textLabel.attr('opacity')).toBe('1');
|
|
expect(rectLabel.attr('opacity')).toBe('1');
|
|
expect(triangle.attr('style')).toContain('opacity: 1;');
|
|
|
|
expect(axisTip.length).toBe(1);
|
|
expect(axisTip.attr('transform')).toBe('translate(0,57)');
|
|
expect(triangle.attr('transform')).toBe('translate(-3, 59.1)');
|
|
});
|
|
});
|
|
|
|
describe('time-series', function () {
|
|
beforeEach(function () {
|
|
this.view._isTimeSeries = function () {
|
|
return true;
|
|
};
|
|
});
|
|
|
|
describe('mobile', function () {
|
|
beforeEach(function () {
|
|
this.view._isMobileViewport = function () {
|
|
return true;
|
|
};
|
|
});
|
|
|
|
describe('right', function () {
|
|
it('should generate right axis tip', function () {
|
|
this.view._generateAxisTip('right');
|
|
|
|
expect(this.view.$('.CDB-Chart-axisTip.CDB-Chart-axisTip-right').attr('transform')).toBe('translate(0,-26)');
|
|
expect(this.view.$('.CDB-Chart-handle-right .CDB-Chart-axisTipTriangle').attr('transform')).toBe('translate(-3, -11)');
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('._updateTriangle', function () {
|
|
beforeEach(function () {
|
|
generateHandlesSpy.and.callThrough();
|
|
|
|
this.view.options.hasAxisTip = true;
|
|
this.view._generateHandles();
|
|
});
|
|
|
|
it('should update triangle', function () {
|
|
var triangle = this.view.$('.CDB-Chart-handle-left .CDB-Chart-axisTipTriangle');
|
|
|
|
this.view._updateTriangle(false, triangle, 42, 60, 100);
|
|
|
|
expect(triangle.attr('transform')).toBe('translate(53,-11)rotate(0)skewX(0)scale(1,1)');
|
|
});
|
|
|
|
describe('time-series, tablet', function () {
|
|
beforeEach(function () {
|
|
this.view._isTimeSeries = function () {
|
|
return true;
|
|
};
|
|
|
|
this.view._isTabletViewport = function () {
|
|
return true;
|
|
};
|
|
|
|
this.view.model.set('right_axis_tip', 42);
|
|
});
|
|
|
|
it('should update right axis tip', function () {
|
|
var triangle = this.view.$('.CDB-Chart-handle-right .CDB-Chart-axisTipTriangle');
|
|
|
|
this.view._updateTriangle(true, triangle, 42, 60, 100);
|
|
|
|
expect(triangle.attr('transform')).toBe('translate(53,59.099998474121094)rotate(0)skewX(0)scale(1,1)');
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('._updateAxisTip', function () {
|
|
var time = 1501751014;
|
|
|
|
beforeEach(function () {
|
|
generateHandlesSpy.and.callThrough();
|
|
|
|
this.view.options.hasAxisTip = true;
|
|
this.view._generateHandles();
|
|
});
|
|
|
|
afterEach(function () {
|
|
$('.CDB-Chart-handles').remove();
|
|
});
|
|
|
|
it('should update axis tip', function () {
|
|
this.view.model.set('left_axis_tip', 42);
|
|
this.view._updateAxisTip('left');
|
|
|
|
expect(this.view.$('.CDB-Chart-axisTipText.CDB-Chart-axisTip-left').text()).toBe('42');
|
|
});
|
|
|
|
describe('left', function () {
|
|
it('should update left axis tip', function () {
|
|
this.view.model.set('left_axis_tip', 42);
|
|
this.view._updateAxisTip('left');
|
|
|
|
var axisTip = this.view.$('.CDB-Chart-axisTip.CDB-Chart-axisTip-left');
|
|
|
|
expect(axisTip.attr('transform')).toBe('translate(-2, -26)');
|
|
});
|
|
});
|
|
|
|
describe('right', function () {
|
|
it('should update right axis tip', function () {
|
|
this.view.model.set('right_axis_tip', 42);
|
|
this.view._updateAxisTip('right');
|
|
|
|
var axisTip = this.view.$('.CDB-Chart-axisTip.CDB-Chart-axisTip-right');
|
|
|
|
expect(axisTip.attr('transform')).toBe('translate(-2, 56)');
|
|
});
|
|
});
|
|
|
|
describe('datetime', function () {
|
|
beforeEach(function () {
|
|
createFormatterSpy.and.callThrough();
|
|
|
|
this.view._isDateTimeSeries = function () {
|
|
return true;
|
|
};
|
|
this.view._createFormatter();
|
|
|
|
this.view.model.set('left_axis_tip', time);
|
|
});
|
|
|
|
it('should update axis tip', function () {
|
|
this.view._updateAxisTip('left');
|
|
|
|
expect(this.view.$('.CDB-Chart-axisTipText.CDB-Chart-axisTip-left').text()).toBe('09:03 - Aug 3rd, 2017');
|
|
});
|
|
});
|
|
|
|
describe('time-series, mobile', function () {
|
|
beforeEach(function () {
|
|
this.view._isTimeSeries = function () {
|
|
return true;
|
|
};
|
|
|
|
this.view._isMobileViewport = function () {
|
|
return true;
|
|
};
|
|
|
|
this.view.model.set('right_axis_tip', 42);
|
|
});
|
|
|
|
it('should update right axis tip', function () {
|
|
this.view._updateAxisTip('right');
|
|
|
|
var axisTip = this.view.$('.CDB-Chart-axisTip.CDB-Chart-axisTip-right');
|
|
|
|
expect(axisTip.attr('transform')).toBe('translate(-2, -26)');
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('._onChangeDragging', function () {
|
|
it('should update model', function () {
|
|
this.view.model.set('dragging', true);
|
|
|
|
expect(this.view.chart.classed('is-dragging')).toBe(true);
|
|
|
|
this.view.model.set('dragging', false);
|
|
|
|
expect(this.view.chart.classed('is-dragging')).toBe(false);
|
|
});
|
|
|
|
describe('if is mobile, time-series, and is not dragging', function () {
|
|
beforeEach(function () {
|
|
this.view._isMobileViewport = function () {
|
|
return true;
|
|
};
|
|
|
|
this.view._isTimeSeries = function () {
|
|
return true;
|
|
};
|
|
|
|
this.view.model.set('dragging', true);
|
|
});
|
|
|
|
it('should hide axis tips', function () {
|
|
spyOn(this.view, '_showAxisTip');
|
|
|
|
this.view.model.set('dragging', false);
|
|
|
|
expect(this.view._showAxisTip).toHaveBeenCalledWith('right', false);
|
|
expect(this.view._showAxisTip).toHaveBeenCalledWith('left', false);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('._toggleAxisTip', function () {
|
|
beforeEach(function () {
|
|
jasmine.clock().install();
|
|
|
|
generateHandlesSpy.and.callThrough();
|
|
|
|
this.view.options.hasAxisTip = true;
|
|
this.view._generateHandles();
|
|
});
|
|
|
|
afterEach(function () {
|
|
jasmine.clock().uninstall();
|
|
|
|
$('.CDB-Chart-handles').remove();
|
|
});
|
|
|
|
it('should toggle axis tip', function () {
|
|
var textLabel = this.view.$('.CDB-Chart-axisTipText.CDB-Chart-axisTip-left');
|
|
var rectLabel = this.view.$('.CDB-Chart-axisTipRect.CDB-Chart-axisTip-left');
|
|
var triangle = this.view.$('.CDB-Chart-handle-left .CDB-Chart-axisTipTriangle');
|
|
|
|
this.view._toggleAxisTip('left', 1);
|
|
flushAllD3Transitions();
|
|
|
|
expect(textLabel.attr('opacity')).toBe('1');
|
|
expect(rectLabel.attr('opacity')).toBe('1');
|
|
expect(triangle.attr('style')).toContain('opacity: 1;');
|
|
|
|
this.view._toggleAxisTip('left', 0);
|
|
flushAllD3Transitions();
|
|
|
|
expect(textLabel.attr('opacity')).toBe('0');
|
|
expect(rectLabel.attr('opacity')).toBe('0');
|
|
expect(triangle.attr('style')).toContain('opacity: 0;');
|
|
});
|
|
});
|
|
|
|
describe('._showAxisTip', function () {
|
|
it('should show axis tip', function () {
|
|
var tip = 'left';
|
|
spyOn(this.view, '_toggleAxisTip');
|
|
|
|
this.view._showAxisTip(tip, true);
|
|
|
|
expect(this.view._toggleAxisTip).toHaveBeenCalledWith(tip, 1);
|
|
});
|
|
|
|
it('should hide axis tip', function () {
|
|
var tip = 'left';
|
|
spyOn(this.view, '_toggleAxisTip');
|
|
|
|
this.view._showAxisTip(tip, false);
|
|
|
|
expect(this.view._toggleAxisTip).toHaveBeenCalledWith(tip, 0);
|
|
});
|
|
});
|
|
|
|
describe('._setupBrush', function () {
|
|
beforeEach(function () {
|
|
setupBrushSpy.and.callThrough();
|
|
|
|
this.view._setupBrush();
|
|
});
|
|
|
|
afterEach(function () {
|
|
$('.Brush').remove();
|
|
});
|
|
|
|
it('should setup brush', function () {
|
|
expect(this.view.$('.Brush rect').attr('height')).toBe('48');
|
|
});
|
|
|
|
describe('time-series', function () {
|
|
beforeEach(function () {
|
|
this.view._isTimeSeries = function () {
|
|
return true;
|
|
};
|
|
});
|
|
|
|
it('should generate handle', function () {
|
|
expect(this.view.$('.Brush rect').attr('height')).toBe('48');
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('._generateBars', function () {
|
|
beforeEach(function () {
|
|
generateHandlesSpy.and.callThrough();
|
|
|
|
this.view._generateHandles();
|
|
});
|
|
|
|
afterEach(function () {
|
|
$('.CDB-Chart-handles').remove();
|
|
});
|
|
|
|
it('should update chart', function () {
|
|
this.view._updateChart();
|
|
flushAllD3Transitions();
|
|
|
|
expect(this.view.$('.CDB-Chart-bar').first().attr('height')).toBe('0');
|
|
expect(this.view.$('.CDB-Chart-bar').last().attr('height')).toBe('48');
|
|
|
|
expect(this.view.$('.CDB-Chart-bar').first().attr('y')).toBe('48');
|
|
expect(this.view.$('.CDB-Chart-bar').last().attr('y')).toBe('0');
|
|
});
|
|
|
|
describe('mobile, time-series', function () {
|
|
beforeEach(function () {
|
|
this.view._isMobileViewport = function () {
|
|
return true;
|
|
};
|
|
|
|
this.view._isTimeSeries = function () {
|
|
return true;
|
|
};
|
|
|
|
this.view.model.set({
|
|
height: 16,
|
|
margin: _.extend({}, this.view.model.get('margin'), { top: 0 }),
|
|
showLabels: false
|
|
}, { silent: true });
|
|
});
|
|
|
|
it('should update chart', function () {
|
|
this.view._updateChart();
|
|
flushAllD3Transitions();
|
|
|
|
expect(this.view.$('.CDB-Chart-bar').first().attr('height')).toBe('3');
|
|
expect(this.view.$('.CDB-Chart-bar').last().attr('height')).toBe('3');
|
|
|
|
expect(this.view.$('.CDB-Chart-bar').first().attr('y')).toBe('9');
|
|
expect(this.view.$('.CDB-Chart-bar').last().attr('y')).toBe('9');
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('._updateChart', function () {
|
|
beforeEach(function () {
|
|
generateHandlesSpy.and.callThrough();
|
|
|
|
this.view._generateHandles();
|
|
|
|
this.view.model.set({
|
|
data: updateHistogramData(20)
|
|
});
|
|
flushAllD3Transitions();
|
|
});
|
|
|
|
afterEach(function () {
|
|
$('.CDB-Chart-handles').remove();
|
|
});
|
|
|
|
it('should update chart', function () {
|
|
expect(this.view.$('.CDB-Chart-bar').first().attr('height')).toBe('48');
|
|
expect(this.view.$('.CDB-Chart-bar').last().attr('height')).toBe('0');
|
|
|
|
expect(this.view.$('.CDB-Chart-bar').first().attr('y')).toBe('0');
|
|
expect(this.view.$('.CDB-Chart-bar').last().attr('y')).toBe('48');
|
|
});
|
|
|
|
describe('mobile, time-series', function () {
|
|
beforeEach(function () {
|
|
this.view._isMobileViewport = function () {
|
|
return true;
|
|
};
|
|
|
|
this.view._isTimeSeries = function () {
|
|
return true;
|
|
};
|
|
|
|
this.view.model.set({
|
|
height: 16,
|
|
margin: _.extend({}, this.view.model.get('margin'), { top: 0 }),
|
|
showLabels: false
|
|
}, { silent: true });
|
|
});
|
|
|
|
it('should update chart', function () {
|
|
this.view._updateChart();
|
|
flushAllD3Transitions();
|
|
|
|
expect(this.view.$('.CDB-Chart-bar').first().attr('height')).toBe('3');
|
|
expect(this.view.$('.CDB-Chart-bar').last().attr('height')).toBe('3');
|
|
|
|
expect(this.view.$('.CDB-Chart-bar').first().attr('y')).toBe('9');
|
|
expect(this.view.$('.CDB-Chart-bar').last().attr('y')).toBe('9');
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('._createFormatter', function () {
|
|
beforeEach(function () {
|
|
createFormatterSpy.and.callThrough();
|
|
|
|
spyOn(formatter, 'timestampFactory');
|
|
spyOn(this.view, '_calculateDivisionWithByAggregation');
|
|
});
|
|
|
|
it('should setup formatter', function () {
|
|
this.view._createFormatter();
|
|
|
|
expect(formatter.timestampFactory).not.toHaveBeenCalledWith();
|
|
expect(this.view._calculateDivisionWithByAggregation).not.toHaveBeenCalledWith();
|
|
expect(this.view.formatter).toBe(formatter.formatNumber);
|
|
});
|
|
|
|
describe('datetime', function () {
|
|
it('should setup formatter', function () {
|
|
this.view._isDateTimeSeries = function () {
|
|
return true;
|
|
};
|
|
|
|
this.view._createFormatter();
|
|
|
|
expect(formatter.timestampFactory).toHaveBeenCalledWith('minute', 0);
|
|
expect(this.view._calculateDivisionWithByAggregation).toHaveBeenCalled();
|
|
expect(this.view.formatter).not.toBe(formatter.formatNumber);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
function genHistogramData (n) {
|
|
n = n || 1;
|
|
var arr = [];
|
|
_.times(n, function (i) {
|
|
var start = i;
|
|
var end = i + 1;
|
|
var obj = {
|
|
bin: i,
|
|
freq: i,
|
|
start: start,
|
|
end: end,
|
|
max: end,
|
|
min: start
|
|
};
|
|
arr.push(obj);
|
|
});
|
|
return arr;
|
|
}
|
|
|
|
function updateHistogramData (n) {
|
|
n = n || 1;
|
|
var arr = [];
|
|
_.times(n, function (i) {
|
|
var start = i;
|
|
var end = i + 1;
|
|
var obj = {
|
|
bin: i,
|
|
freq: n - end,
|
|
start: start,
|
|
end: end,
|
|
max: end,
|
|
min: start
|
|
};
|
|
arr.push(obj);
|
|
});
|
|
return arr;
|
|
}
|