Initial commit

This commit is contained in:
zhongjin
2020-06-15 10:58:47 +08:00
commit 4f1dfe7564
8590 changed files with 1516878 additions and 0 deletions
@@ -0,0 +1,111 @@
var Backbone = require('backbone');
var FactoryModals = require('../../../factories/modals');
var EditorHelpers = require('builder/components/form-components/helpers/editor');
function dispatchDocumentEvent (type, opts) {
var e = document.createEvent('HTMLEvents');
e.initEvent(type, false, true);
if (opts.which) {
e.which = opts.which;
}
document.dispatchEvent(e, opts);
}
describe('components/form-components/editors/base', function () {
var view;
beforeEach(function () {
view = new Backbone.Form.editors.Base();
view.options = {
validators: ['required']
};
document.body.appendChild(view.el);
});
afterEach(function () {
var parent = view.el.parentNode;
parent && parent.removeChild(view.el);
view.remove();
});
it('should take default validation', function () {
EditorHelpers.setOptions(view, {
schema: {
min: 0,
max: 10,
step: 1,
showSlider: true
}
});
expect(view.options.validators.length).toBe(1);
expect(view.options.validators[0]).toBe('required');
});
it('should take opts validation plus the default one', function () {
EditorHelpers.setOptions(view, {
schema: {
validators: [{
type: 'regexp',
regexp: /^[0-9]*\.?[0-9]*$/,
message: 'Must be valid'
}]
}
});
expect(view.options.validators.length).toBe(2);
expect(view.options.validators[0].type).toBe('regexp');
expect(view.options.validators[1]).toBe('required');
});
describe('document click and escape binding', function () {
beforeEach(function () {
this.modals = FactoryModals.createModalService();
});
it('without modals set', function () {
var cb = jasmine.createSpy('cb');
view.applyClickOutsideBind(cb);
dispatchDocumentEvent('click', { target: 'body' });
expect(cb).toHaveBeenCalled();
});
it('with some modal open', function () {
var clickCB = jasmine.createSpy('clickCB');
var escCB = jasmine.createSpy('escCB');
EditorHelpers.setOptions(view, {
modals: this.modals
});
view.applyClickOutsideBind(clickCB);
view.applyESCBind(escCB);
this.modals.set('open', true);
dispatchDocumentEvent('click', { target: 'body' });
expect(clickCB).not.toHaveBeenCalled();
dispatchDocumentEvent('keydown', { which: 27 });
expect(escCB).not.toHaveBeenCalled();
});
it('without any modal open', function () {
var clickCB = jasmine.createSpy('clickCB');
var escCB = jasmine.createSpy('escCB');
EditorHelpers.setOptions(view, {
modals: this.modals
});
view.applyClickOutsideBind(clickCB);
view.applyESCBind(escCB);
this.modals.set('open', false);
dispatchDocumentEvent('click', { target: 'body' });
expect(clickCB).toHaveBeenCalled();
dispatchDocumentEvent('keydown', { which: 27 });
expect(escCB).toHaveBeenCalled();
});
});
});
@@ -0,0 +1,209 @@
var Backbone = require('backbone');
var _ = require('underscore');
var AnalysisDefinitionNodeModel = require('builder/data/analysis-definition-node-model');
var MeasurementModel = require('builder/data/data-observatory/measurement-model');
describe('components/form-components/editors/data-observatory-measurements/data-observatory-measurements-view', function () {
var createViewFn = function (options) {
var configModel = new Backbone.Model({
base_url: '/u/foo',
user_name: 'foo',
sql_api_template: 'foo',
api_key: 'foo'
});
this.nodeDefModel = new AnalysisDefinitionNodeModel({
id: 'a1',
type: 'data-observatory-multiple-measures',
final_column: 'foo',
source: 'a0'
}, {
configModel: configModel,
collection: new Backbone.Collection()
});
this.querySchemaModel = new Backbone.Model({
query: 'select * from wadus'
});
this.nodeDefModel.querySchemaModel = this.querySchemaModel;
this.model = new Backbone.Model({
measurements: 'us.census.acs.B01001002'
});
this.measurementModel = new MeasurementModel({}, {
configModel: configModel,
nodeDefModel: this.nodeDefModel
});
var defaultOptions = {
key: 'measurements',
model: this.model,
configModel: configModel,
nodeDefModel: this.nodeDefModel,
measurementModel: this.measurementModel,
region: 'wadus'
};
this.view = new Backbone.Form.editors.DataObservatoryDropdown(_.extend(defaultOptions, options));
this.view.render();
this.dialog = this.view._dialogView;
spyOn(this.view.filtersCollection.SQL, 'execute').and.callFake(function (query, vars, params) {
var payload = {
rows: [
{
subsection_id: 'subsection/tags.age_gender',
subsection_name: 'Age and Gender'
},
{
subsection_id: 'subsection/us.census.acs.segments',
subsection_name: 'US Population Segments'
},
{
subsection_id: 'subsection/tags.housing',
subsection_name: 'Housing'
},
{
subsection_id: 'subsection/us.zillow.indexes',
subsection_name: 'Zillow Home Value and Rental Indexes'
}
]
};
params && params.success(payload);
});
spyOn(this.view.measurementsCollection.SQL, 'execute').and.callFake(function (query, vars, params) {
var payload = {
rows: [
{
numer_id: 'us.zillow.AllHomes_Zhvi',
numer_name: 'Zillow Home Value Index for All homes',
numer_tags: '{"subsection/tags.housing": "Housing", "license/us.zillow.zillow-license": "Zillow Terms of Use for Aggregate Data"}'
},
{
numer_id: 'us.census.acs.B19083001',
numer_name: 'Gini Index',
numer_tags: '{"subsection/tags.age_gender": "Age and Gender", "license/tags.no-restrictions": "Unrestricted"}'
},
{
numer_id: 'us.census.acs.B01001002',
numer_name: 'Male Population',
numer_tags: '{"subsection/tags.age_gender": "Age and Gender", "license/tags.no-restrictions": "Unrestricted"}'
}
]
};
params && params.success(payload);
});
};
beforeEach(function () {
this.createView = createViewFn.bind(this);
});
it('should genereate an measurements and filters collections', function () {
this.createView();
expect(this.view.measurementsCollection).toBeDefined();
expect(this.view.filtersCollection).toBeDefined();
});
describe('render', function () {
it('should render properly', function () {
this.createView();
this.view.measurementsCollection.fetch();
this.view.measurementsCollection.getItem('us.census.acs.B01001002').set({ selected: true });
expect(this.view.$('.js-button').length).toBe(1);
expect(this.view.$('.js-button').text()).toContain('Male Population');
expect(this.view.$('.js-button').attr('title')).toBe('Male Population');
this.view.measurementsCollection.getItem('us.census.acs.B19083001').set({ selected: true });
expect(this.view.$('.js-button').text()).toContain('Gini Index');
expect(this.view.$('.js-button').attr('title')).toBe('Gini Index');
});
it('should render custom placeholder if provided and no selected', function () {
this.createView({
placeholder: 'wadus'
});
this.model.set('measurements', '');
this.view.render();
expect(this.view.$('.js-button').length).toBe(1);
expect(this.view.$('.js-button').text()).toContain('wadus');
});
it('should disable the component if option is true', function () {
this.createView();
this.view.options.disabled = true;
this.view.render();
expect(this.view.$('.js-button').hasClass('is-disabled')).toBeTruthy();
});
it('should add is-empty class if there is no value selected', function () {
this.createView();
this.view.render();
expect(this.view.$('.js-button').hasClass('is-empty')).toBeTruthy();
});
});
describe('getValue', function () {
it('should return item selected if any', function () {
this.createView();
this.view.measurementsCollection.fetch();
this.view.measurementsCollection.getItem('us.zillow.AllHomes_Zhvi').set({ selected: true });
var value = this.view.getValue();
expect(value).toBe('us.zillow.AllHomes_Zhvi');
});
it('should return value if no item selected', function () {
this.createView();
this.measurementModel.set({
val: 'us.census.acs.B01001002'
});
var value = this.view.getValue();
expect(value).toBe('us.census.acs.B01001002');
});
});
it('should change button value and hide dialog when a new item is selected', function () {
this.createView();
spyOn(this.dialog, 'hide');
this.view.measurementsCollection.fetch();
this.view.measurementsCollection.getItem('us.zillow.AllHomes_Zhvi').set({ selected: true });
expect(this.view.$('.js-button').text()).toContain('Zillow Home Value Index for All homes');
expect(this.view.$('.js-button').hasClass('is-empty')).toBeFalsy();
expect(this.dialog.hide).toHaveBeenCalled();
});
it('should open dialog if "button" is clicked', function () {
this.createView();
spyOn(this.dialog, 'toggle');
this.view.$('.js-button').trigger('click');
expect(this.dialog.toggle).toHaveBeenCalled();
});
it('should destroy dialog when element is removed', function () {
this.createView();
spyOn(this.dialog, 'clean');
this.view.remove();
expect(this.dialog.clean).toHaveBeenCalled();
});
afterEach(function () {
this.view.remove();
});
});
@@ -0,0 +1,48 @@
var Backbone = require('backbone');
var DataObservatoryCountView = require('builder/components/form-components/editors/data-observatory-measurements//measurements-count-view');
describe('components/form-components/editors/data-observatory-measurements/measurements-count-view', function () {
beforeEach(function () {
this.model = new Backbone.Model({
query: null,
items: 50,
filtering: false
});
this.view = new DataObservatoryCountView({
model: this.model
});
});
it('should render top results if query is empty', function () {
this.model.set({
query: '',
items: 0
});
expect(this.view.$el.html()).toContain('analyses.data-observatory-measure.count.suggested');
});
it('should render number of results if query is not empty', function () {
this.view.model.set({
query: 'foo',
items: 35
});
expect(this.view.$el.html()).toContain('analyses.data-observatory-measure.count.search');
});
it('should render number of results if query is not empty', function () {
this.view.model.set({
query: 'foo',
items: 15,
filtering: true
});
expect(this.view.$el.html()).toContain('analyses.data-observatory-measure.count.search');
});
it('should not have any leaks', function () {
expect(this.view).toHaveNoLeaks();
});
});
@@ -0,0 +1,183 @@
var Backbone = require('backbone');
var MeasurementsCollection = require('builder/data/data-observatory/measurements-collection');
var FiltersCollection = require('builder/data/data-observatory/filters-collection');
var AnalysisDefinitionNodeModel = require('builder/data/analysis-definition-node-model');
var DataObservatoryListView = require('builder/components/form-components/editors/data-observatory-measurements/measurements-list-view');
var MeasurementModel = require('builder/data/data-observatory/measurement-model');
describe('components/form-components/editors/data-observatory-measurements/measurements-list-view', function () {
beforeEach(function () {
var configModel = new Backbone.Model({
base_url: '/u/foo',
user_name: 'foo',
sql_api_template: 'foo',
api_key: 'foo'
});
this.nodeDefModel = new AnalysisDefinitionNodeModel({
id: 'a1',
type: 'data-observatory-multiple-measures',
final_column: 'foo',
source: 'a0'
}, {
configModel: configModel,
collection: new Backbone.Collection()
});
this.querySchemaModel = new Backbone.Model({
query: 'select * from wadus'
});
this.nodeDefModel.querySchemaModel = this.querySchemaModel;
this.measurementsCollection = new MeasurementsCollection([], {
configModel: configModel,
nodeDefModel: this.nodeDefModel
});
spyOn(this.measurementsCollection.SQL, 'execute').and.callFake(function (query, vars, params) {
var payload = {
rows: [
{
numer_id: 'us.zillow.AllHomes_Zhvi',
numer_name: 'Zillow Home Value Index for All homes',
numer_tags: '{"subsection/tags.housing": "Housing", "license/us.zillow.zillow-license": "Zillow Terms of Use for Aggregate Data"}'
},
{
numer_id: 'us.census.acs.B19083001',
numer_name: 'Gini Index',
numer_tags: '{"subsection/tags.age_gender": "Age and Gender", "license/tags.no-restrictions": "Unrestricted"}'
},
{
numer_id: 'us.census.acs.B01001002',
numer_name: 'Male Population',
numer_tags: '{"subsection/tags.age_gender": "Age and Gender", "license/tags.no-restrictions": "Unrestricted"}'
}
]
};
params && params.success(payload);
});
this.filtersCollection = new FiltersCollection([], {
configModel: configModel,
nodeDefModel: this.nodeDefModel
});
spyOn(this.filtersCollection.SQL, 'execute').and.callFake(function (query, vars, params) {
var payload = {
rows: [
{
subsection_id: 'subsection/tags.age_gender',
subsection_name: 'Age and Gender'
},
{
subsection_id: 'subsection/us.census.acs.segments',
subsection_name: 'US Population Segments'
},
{
subsection_id: 'subsection/tags.housing',
subsection_name: 'Housing'
},
{
subsection_id: 'subsection/us.zillow.indexes',
subsection_name: 'Zillow Home Value and Rental Indexes'
}
]
};
params && params.success(payload);
});
this.measurementsCollection.fetch();
this.filtersCollection.fetch();
this.searchMeasurements = jasmine.createSpy('searchMeasurements');
this.measurementModel = new MeasurementModel({}, {
configModel: configModel,
nodeDefModel: this.nodeDefModel
});
this.view = new DataObservatoryListView({
measurementsCollection: this.measurementsCollection,
filtersCollection: this.filtersCollection,
searchMeasurements: this.searchMeasurements,
measurementModel: this.measurementModel
});
spyOn(this.view, '_createListView').and.callThrough();
spyOn(this.view, '_createSearchView').and.callThrough();
spyOn(this.view, '_createCountView').and.callThrough();
this.view.render();
});
it('should genereate an measurements and filters collections', function () {
expect(this.view._measurementsCollection).toBeDefined();
expect(this.view._filtersCollection).toBeDefined();
expect(this.view._measurementsCollection.size()).toBe(3);
expect(this.view._filtersCollection.size()).toBe(4);
});
it('should render properly', function () {
expect(this.view._listView).toBeDefined();
expect(this.view._createListView).toHaveBeenCalled();
expect(this.view._createSearchView).toHaveBeenCalled();
expect(this.view._createCountView).toHaveBeenCalled();
});
it('should filter search queries', function () {
this.view.model.set('query', 'pop');
expect(this.searchMeasurements).toHaveBeenCalled();
});
it('should render filtered measurements', function () {
this.measurementsCollection.SQL.execute = function (query, vars, params) {
var payload = {
rows: [
{
numer_id: 'us.census.acs.B19083001',
numer_name: 'Gini Index',
numer_tags: '{"subsection/tags.age_gender": "Age and Gender", "license/tags.no-restrictions": "Unrestricted"}'
},
{
numer_id: 'us.census.acs.B01001002',
numer_name: 'Male Population',
numer_tags: '{"subsection/tags.age_gender": "Age and Gender", "license/tags.no-restrictions": "Unrestricted"}'
}
]
};
params && params.success(payload);
};
this.filtersCollection.setSelected('subsection/tags.age_gender');
this.measurementsCollection.fetch();
this.view = new DataObservatoryListView({
measurementsCollection: this.measurementsCollection,
filtersCollection: this.filtersCollection,
searchMeasurements: this.searchMeasurements,
measurementModel: this.measurementModel
});
this.view.render();
expect(this.view.$('.js-listItem').length).toBe(2);
expect(this.view.$('.js-listItem').eq(0).text()).toContain('Gini Index');
expect(this.view.$('.js-listItem').eq(1).text()).toContain('Male Population');
});
it('should trigger filter event', function () {
spyOn(this.view, 'trigger');
this.view.$('.js-filters').click();
expect(this.view.trigger).toHaveBeenCalledWith('filters');
});
it('should not have any leaks', function () {
expect(this.view).toHaveNoLeaks();
});
});
@@ -0,0 +1,96 @@
var Backbone = require('backbone');
var DataObservatorySearchView = require('builder/components/form-components/editors/data-observatory-measurements/measurements-search-view');
var FiltersCollection = require('builder/data/data-observatory/filters-collection');
var AnalysisDefinitionNodeModel = require('builder/data/analysis-definition-node-model');
describe('components/form-components/editors/data-observatory-measurements/measurements-search-view', function () {
beforeEach(function () {
var configModel = new Backbone.Model({
base_url: '/u/foo',
user_name: 'foo',
sql_api_template: 'foo',
api_key: 'foo'
});
this.nodeDefModel = new AnalysisDefinitionNodeModel({
id: 'a1',
type: 'data-observatory-multiple-measures',
final_column: 'foo',
source: 'a0'
}, {
configModel: configModel,
collection: new Backbone.Collection()
});
this.querySchemaModel = new Backbone.Model({
query: 'select * from wadus'
});
this.nodeDefModel.querySchemaModel = this.querySchemaModel;
this.filtersCollection = new FiltersCollection([
{
subsection_id: 'subsection/tags.age_gender',
subsection_name: 'Age and Gender'
},
{
subsection_id: 'subsection/us.census.acs.segments',
subsection_name: 'US Population Segments'
},
{
subsection_id: 'subsection/tags.housing',
subsection_name: 'Housing'
},
{
subsection_id: 'subsection/us.zillow.indexes',
subsection_name: 'Zillow Home Value and Rental Indexes'
}
], {
configModel: configModel,
nodeDefModel: this.nodeDefModel
});
this.model = new Backbone.Model({
query: '',
items: 50,
fetching: false
});
this.view = new DataObservatorySearchView({
model: this.model,
filtersCollection: this.filtersCollection
});
});
it('should sanitize input', function () {
this.view.$('.js-input-search').val('<script>');
expect(this.model.get('query')).toBe('');
});
describe('render', function () {
it('label with no filter selected', function () {
this.view.render();
expect(this.view.$('.js-filters').text()).toContain('analyses.data-observatory-measure.filters.label');
});
it('label with 1 filter selected', function () {
this.filtersCollection.at(0).set({selected: true});
this.view.render();
expect(this.view.$('.js-filters').text()).toContain('analyses.data-observatory-measure.filters.applied.single');
});
it('label with more than one filter selected', function () {
this.filtersCollection.at(0).set({selected: true});
this.filtersCollection.at(2).set({selected: true});
this.view.render();
expect(this.view.$('.js-filters').text()).toContain('analyses.data-observatory-measure.filters.applied.multiple');
});
});
it('should not have any leaks', function () {
expect(this.view).toHaveNoLeaks();
});
});
@@ -0,0 +1,60 @@
var Backbone = require('backbone');
describe('components/form-components/editors/datetime', function () {
beforeEach(function () {
this.model = new Backbone.Model({
dateee: '2016-12-01T12:00:00+00:00'
});
this.view = new Backbone.Form.editors.DateTime({
schema: {},
key: 'dateee',
model: this.model
});
});
describe('when date time is provided', function () {
it('should render properly', function () {
expect(this.view.$('.js-input').length).toBe(1);
expect(this.view.$('.js-input').html()).toBe('2016-12-01T12:00:00Z');
expect(this.view.$('.js-datetimePicker').length).toBe(0);
});
it('should open time picker when click over input and not change the time', function () {
expect(this.view.$('.js-input').html()).toBe('2016-12-01T12:00:00Z');
this.view.$('.js-input').click();
expect(this.view.$('.js-datetimePicker').length).toBe(1);
expect(this.view.$('.js-input').html()).toBe('2016-12-01T12:00:00Z');
});
});
describe('when date time is NOT provided', function () {
beforeEach(function () {
this.view.value = '';
this.model.set('dateee', '');
this.view.render();
});
it('should return null as value when datetime is not selected', function () {
expect(this.view.getValue()).toBe(null);
});
it('should render null when datetime is not selected', function () {
expect(this.view.$('.js-input').length).toBe(1);
expect(this.view.$('.js-input').html()).toBe('null');
expect(this.view.$('.js-input').hasClass('is-empty')).toBeTruthy();
});
it('should change input when it is clicked for showing time picker', function () {
expect(this.view.$('.js-input').html()).toBe('null');
this.view.$('.js-input').click();
expect(this.view.$('.js-datetimePicker').length).toBe(1);
expect(this.view.$('.js-input').html()).not.toBe('null');
expect(this.view.$('.js-input').hasClass('is-empty')).toBeFalsy();
});
});
afterEach(function () {
this.view.remove();
});
});
@@ -0,0 +1,85 @@
var Backbone = require('backbone');
describe('components/form-components/editors/enabler-editor', function () {
beforeEach(function () {
this.model = new Backbone.Model({
key: ''
});
this.view = new Backbone.Form.editors.EnablerEditor({
key: 'key',
model: this.model,
label: 'hello',
trackingClass: 'wadus',
editor: {
type: 'Select',
options: ['hello', 'world']
}
});
this.view.render();
});
it('should render properly', function () {
expect(this.view.$('.js-check').length).toBe(1);
expect(this.view.$('.js-editor').length).toBe(1);
expect(this.view.$('.js-check').is(':checked')).toBeFalsy();
});
it('should render as checked when value is not empty', function () {
this.view._checkModel.set('enabled', true);
this.view.render();
expect(this.view.$('.js-check').is(':checked')).toBeTruthy();
});
it('should render help tooltip', function () {
this.view.options.help = 'HELP!';
this.view.render();
expect(this.view._helpTooltip).toBeDefined();
expect(this.view.$('.js-help').length).toBe(1);
});
it('should change model value when editor component changes', function () {
this.view._editorComponent.setValue('hello');
this.view._editorComponent.trigger('change', this.view._editorComponent);
expect(this.view.value).toBe('hello');
});
it('should change model with empty value when check is disabled', function () {
this.view._checkModel.set('enabled', true);
this.view._editorComponent.setValue('hello');
this.view._editorComponent.trigger('change', 'hello', this.view._editorComponent);
expect(this.view._checkModel.get('enabled')).toBeTruthy();
expect(this.view.value).toBe('hello');
this.view._checkModel.set('enabled', false);
expect(this.view._checkModel.get('enabled')).toBeFalsy();
expect(this.view.$('.js-check').is(':checked')).toBeFalsy();
expect(this.view.value).toBe('');
});
it('should change model with default value when check is enabled', function () {
this.view.options.defaultValue = 'world';
this.view._checkModel.set('enabled', true);
expect(this.view._editorComponent.getValue()).toBe('world');
expect(this.view.value).toBe('world');
});
it('should change model with empty value when default value is passed and check is disabled', function () {
this.view.options.defaultValue = 'world';
this.view._checkModel.set('enabled', true);
this.view._checkModel.set('enabled', false);
expect(this.view.value).toBe('');
});
it('should accept disabled option', function () {
this.view.options.isDisabled = true;
this.view.render();
expect(this.view.$('.js-check').is(':disabled')).toBeTruthy();
});
it('should add the track class', function () {
expect(this.view.$('.track-keySelect').length).toBe(1);
});
afterEach(function () {
this.view.remove();
});
});
@@ -0,0 +1,84 @@
var Backbone = require('backbone');
describe('components/form-components/editors/enabler', function () {
beforeEach(function () {
this.model = new Backbone.Model({
enabler: false
});
this.view = new Backbone.Form.editors.Enabler({
model: this.model,
title: 'hello',
key: 'enabler'
});
});
describe('render', function () {
beforeEach(function () {
this.view.render();
this.$input = function () {
return this.view.$('.js-input');
};
});
it('should create the checkbox properly', function () {
expect(this.$input().length).toBe(1);
expect(this.$input().is(':checked')).toBeFalsy();
});
it('should start checked from the beginning if key is true', function () {
this.model.attributes.enabler = true;
var view = new Backbone.Form.editors.Enabler({
model: this.model,
title: 'hello',
key: 'enabler'
});
expect(view.$('.js-input').is(':checked')).toBeTruthy();
view.remove();
});
it('should disable checkbox if option is false', function () {
this.view.options.disabled = true;
this.view._initViews();
expect(this.$input().is(':checked')).toBeFalsy();
expect(this.$input().is(':disabled')).toBeTruthy();
});
it('should add help and help tooltip', function () {
this.view.options.help = 'help!';
this.view._initViews();
expect(this.view.$('.js-help').length).toBe(1);
expect(this.view._helpTooltip).toBeDefined();
});
});
it('should trigger event when input changes', function () {
var bindSpy = jasmine.createSpy('callback');
expect(this.model.get('enabler')).toBeFalsy();
this.view.bind('change', bindSpy);
this.view.$('.js-input').attr('checked', '').trigger('change');
expect(this.model.get('enabler')).toBeTruthy();
expect(bindSpy).toHaveBeenCalled();
});
it('should set value properly', function () {
this.view.setValue(true);
expect(this.model.get('enabler')).toBeTruthy();
expect(this.view.$('.js-input').is(':checked')).toBeTruthy();
this.view.setValue(false);
expect(this.model.get('enabler')).toBeFalsy();
expect(this.view.$('.js-input').is(':checked')).toBeFalsy();
});
it('should remove help tooltip if it is defined', function () {
this.view.options.help = 'hello';
this.view._initViews();
spyOn(this.view, '_removeTooltip');
this.view.remove();
expect(this.view._removeTooltip).toHaveBeenCalled();
});
afterEach(function () {
this.view.remove();
});
});
@@ -0,0 +1,53 @@
var Backbone = require('backbone');
var FillColorByValueView = require('builder/components/form-components/editors/fill-color/fill-color-by-value-view');
var FactoryModals = require('../../../../factories/modals');
var getConfigModelFixture = require('fixtures/builder/config-model.fixture.js');
var getUserModelFixture = require('fixtures/builder/user-model.fixture.js');
var DialogConstants = require('builder/components/form-components/_constants/_dialogs');
describe('components/form-components/editors/fill-color/fill-color-by-value-view', function () {
var view;
var CARTODB_ID = { val: 'cartodb_id', label: 'cartodb_id', type: 'number' };
var A_NUMBER_COLUMN = { val: 'a_number', label: 'a_number', type: 'number' };
var A_TEXT_COLUMN = { val: 'category', label: 'category', type: 'string' };
var ALL_COLUMNS = [CARTODB_ID, A_NUMBER_COLUMN, A_TEXT_COLUMN];
function createView (options) {
options = options || {
model: new Backbone.Model({}),
columns: ALL_COLUMNS,
query: 'SELECT * from table',
configModel: getConfigModelFixture(),
userModel: getUserModelFixture(),
editorAttrs: { help: '' },
modals: FactoryModals.createModalService(),
dialogMode: DialogConstants.Mode.FLOAT,
valueColorInputModel: new Backbone.Model({}),
popupConfig: {}
};
return new FillColorByValueView(options);
}
describe('render', function () {
it('should have no leaks', function () {
view = createView();
expect(view).toHaveNoLeaks();
});
it('calls to _initViews', function () {
view = createView();
spyOn(view, '_initFillDialog');
spyOn(view, '_initColorByValueInput');
view.render();
expect(view._initFillDialog).toHaveBeenCalled();
expect(view._initColorByValueInput).toHaveBeenCalled();
});
});
});
@@ -0,0 +1,47 @@
var Backbone = require('backbone');
var FillColorFixedView = require('builder/components/form-components/editors/fill-color/fill-color-fixed-view');
var DialogConstants = require('builder/components/form-components/_constants/_dialogs');
describe('components/form-components/editors/fill-color/fill-color-fixed-view', function () {
var view;
var CARTODB_ID = { val: 'cartodb_id', label: 'cartodb_id', type: 'number' };
var A_NUMBER_COLUMN = { val: 'a_number', label: 'a_number', type: 'number' };
var A_TEXT_COLUMN = { val: 'category', label: 'category', type: 'string' };
var ALL_COLUMNS = [CARTODB_ID, A_NUMBER_COLUMN, A_TEXT_COLUMN];
function createView () {
var fillColorFixedView = new FillColorFixedView({
model: new Backbone.Model({
fixed: 'red',
opacity: 0.8
}),
columns: ALL_COLUMNS,
editorAttrs: { help: '' },
dialogMode: DialogConstants.Mode.FLOAT,
popupConfig: {},
fixedColorInputModel: new Backbone.Model({}),
imageInputModel: new Backbone.Model({})
});
return fillColorFixedView;
}
describe('render', function () {
it('should have no leaks', function () {
view = createView();
expect(view).toHaveNoLeaks();
});
it('calls to _initViews', function () {
view = createView();
spyOn(view, '_initFillColorInput');
spyOn(view, '_initFillImageInput');
view.render();
expect(view._initFillColorInput).toHaveBeenCalled();
expect(view._initFillImageInput).toHaveBeenCalled();
});
});
});
@@ -0,0 +1,106 @@
var Backbone = require('backbone');
var FactoryModals = require('../../../../factories/modals');
var getConfigModelFixture = require('fixtures/builder/config-model.fixture.js');
var getUserModelFixture = require('fixtures/builder/user-model.fixture.js');
var DialogConstants = require('builder/components/form-components/_constants/_dialogs');
var ColorByValueView = require('builder/components/form-components/editors/fill-color/fill-color-by-value-view');
describe('components/form-components/editors/fill-color/fill-color', function () {
var color;
var CARTODB_ID = { val: 'cartodb_id', label: 'cartodb_id', type: 'number' };
var A_NUMBER_COLUMN = { val: 'a_number', label: 'a_number', type: 'number' };
var A_TEXT_COLUMN = { val: 'category', label: 'category', type: 'string' };
var ALL_COLUMNS = [CARTODB_ID, A_NUMBER_COLUMN, A_TEXT_COLUMN];
function createFillColor (opts) {
opts = opts || {};
var modelOptions = {};
if (opts.fillColor) {
modelOptions.fillColor = opts.fillColor;
}
var options = {
model: new Backbone.Model(modelOptions),
key: 'fillColor',
options: ALL_COLUMNS,
query: 'SELECT * from table',
configModel: getConfigModelFixture(),
userModel: getUserModelFixture(),
editorAttrs: {
geometryName: 'point',
help: '',
hidePanes: []
},
modals: FactoryModals.createModalService(),
dialogMode: DialogConstants.Mode.FLOAT,
valueColorInputModel: new Backbone.Model({}),
popupConfig: {}
};
if (opts.hidePanes) {
options.editorAttrs.hidePanes = opts.hidePanes;
}
if (opts.columns) {
options.options = opts.columns;
}
return new Backbone.Form.editors.FillColor(options);
}
describe('render', function () {
it('both fixed and by value if no options passed about it', function () {
color = createFillColor();
color.render();
expect(color.$('.js-menu').children().length).toBe(2);
var labels = color.$('.js-menu > li label');
expect(labels.length).toBe(2);
expect(labels[0].textContent.trim()).toContain('form-components.editors.fill.input-number.solid');
expect(labels[1].textContent.trim()).toContain('form-components.editors.fill.input-number.by-value');
});
it('only fixed if hidePanes set with `value`', function () {
color = createFillColor({
hidePanes: ['value'],
fillColor: {
fixed: '#FF0000',
opacity: 0.9
}
});
color.render();
// Menu
expect(color.$('.js-menu').children().length).toBe(1);
var labels = color.$('.js-menu > li label');
expect(labels.length).toBe(1);
expect(labels[0].textContent.trim()).toContain('form-components.editors.fill.input-number.solid');
// Form content
expect(color.$('.js-content .ColorBarContainer').length).toBe(1);
expect(color.$('.js-content li.ColorBar')[0].style.backgroundColor).toContain('rgba(255, 0, 0, 0.9');
});
it('only by value if hidePanes set with `fixed`', function () {
spyOn(ColorByValueView.prototype, 'initialize');
spyOn(ColorByValueView.prototype, 'render').and.returnValue('<div class="fake-by-value"></div>');
color = createFillColor({
hidePanes: ['fixed']
});
color.render();
// Menu
expect(color.$('.js-menu').children().length).toBe(1);
var labels = color.$('.js-menu > li label');
expect(labels.length).toBe(1);
expect(labels[0].textContent.trim()).toContain('form-components.editors.fill.input-number.by-value');
expect(ColorByValueView.prototype.render).toHaveBeenCalled();
});
afterEach(function () {
color.remove();
});
});
});
@@ -0,0 +1,92 @@
var Backbone = require('backbone');
var InputColorByValueView = require('builder/components/form-components/editors/fill-color/inputs/input-color-by-value');
var FactoryModals = require('../../../../../factories/modals');
var getConfigModelFixture = require('fixtures/builder/config-model.fixture.js');
var getUserModelFixture = require('fixtures/builder/user-model.fixture.js');
describe('components/form-components/editors/fill-color/inputs/input-color-by-value', function () {
var view;
var CARTODB_ID = { val: 'cartodb_id', label: 'cartodb_id', type: 'number' };
var A_NUMBER_COLUMN = { val: 'a_number', label: 'a_number', type: 'number' };
var A_TEXT_COLUMN = { val: 'category', label: 'category', type: 'string' };
var ALL_COLUMNS = [CARTODB_ID, A_NUMBER_COLUMN, A_TEXT_COLUMN];
function createView (options) {
options = options || {
model: new Backbone.Model({
range: []
}),
columns: ALL_COLUMNS,
configModel: getConfigModelFixture(),
userModel: getUserModelFixture(),
modals: FactoryModals.createModalService(),
query: 'SELECT * from a',
editorAttrs: { help: '' }
};
return new InputColorByValueView(options);
}
describe('initialize', function () {
it('model can be set without colors (first use)', function () {
view = createView();
expect(view._getValue()).toBe(null);
expect(view.model.get('range')).toEqual([]);
});
it('model can be set with colors range & string field', function () {
view = createView();
view.model.set('range', ['#5F4690', '#1D6996']);
view.model.set('attribute', 'category');
view.model.set('attribute_type', 'string');
expect(view._getValue()).not.toBe(null);
expect(view._getColumn()).toBe(A_TEXT_COLUMN);
});
});
describe('render', function () {
it('renders a `select by column` if no attribute is set', function () {
view = createView();
view.render();
var htmlContent = view.$el.html();
expect(htmlContent).toContain('form-components.editors.style.select-by-column');
});
it('renders the name of the field & a colorbar if attribute and colors are set', function () {
view = createView();
view.model.set('range', ['#FF0000', '#0000FF']);
view.model.set('attribute', 'category');
view.model.set('attribute_type', 'string');
view.render();
var columnName = view.$el.find('.Editor-fillContainer--Column');
expect(columnName.html()).toContain('category');
var colorbar = view.$el.find('.Editor-fillContainer--ColorBarContainer');
expect(colorbar.html()).toContain('rgba(255, 0, 0, 1)');
expect(colorbar.html()).toContain('rgba(0, 0, 255, 1)');
});
it('creates an input-color-value-content-view', function () {
view = createView();
view._createContentView();
expect(view._inputColorValueContentView).toBeDefined();
});
});
describe('events', function () {
it('should hookup selectors with functions', function () {
view = createView();
expect(view.events['click']).toEqual('_onClick');
});
});
});
@@ -0,0 +1,37 @@
var Backbone = require('backbone');
var InputColorFixedView = require('builder/components/form-components/editors/fill-color/inputs/input-color-fixed');
describe('components/form-components/editors/fill-color/inputs/input-color-fixed', function () {
var inputColor;
function createView () {
inputColor = new InputColorFixedView({
model: new Backbone.Model({
type: 'color',
fixed: '#FF0000',
opacity: 0.90
}),
columns: {},
editorAttrs: { help: '' }
});
}
beforeEach(function () {
createView();
});
it('renders a colorbar', function () {
inputColor.render();
expect(inputColor._getValue()).toContain('rgba(255, 0, 0, 0.9');
expect(inputColor._getOpacity()).toBe(0.9);
var colorBarBackground = inputColor.$el.find('.ColorBar')[0].style.backgroundColor;
expect(colorBarBackground).toContain('rgba(255, 0, 0, 0.9');
});
it('can create a color picker to choose one', function () {
inputColor._createContentView();
expect(inputColor._colorPickerView).not.toBeNull();
});
});
@@ -0,0 +1,66 @@
var _ = require('underscore');
var Backbone = require('backbone');
var InputImageView = require('builder/components/form-components/editors/fill-color/inputs/input-image');
var ImageLoaderView = require('builder/components/img-loader-view');
var ConfigModel = require('builder/data/config-model');
var FactoryModals = require('../../../../../factories/modals');
describe('components/form-components/editors/fill-color/inputs/input-image', function () {
var NO_IMAGE_TEXT = 'form-components.editors.fill.input-color.img';
var SQUARE_ICON_URL = 'https://s3.amazonaws.com/com.cartodb.users-assets.production/maki-icons/square-18.svg';
var inputImageView;
var spyOnSvgRequest;
function createView () {
inputImageView = new InputImageView({
model: new Backbone.Model({
type: 'image',
image: null,
kind: null
}),
userModel: { featureEnabled: function () { return true; } },
configModel: new ConfigModel({ base_url: '/u/pepe' }),
modals: FactoryModals.createModalService(),
editorAttrs: { help: '' }
});
}
beforeEach(function () {
spyOnSvgRequest = spyOn(ImageLoaderView.prototype, '_loadSVG');
createView();
});
it('renders without an image', function () {
inputImageView.render();
expect(inputImageView._getImageURL()).toBe('');
var htmlContent = inputImageView.$('.Editor-fillImage').html();
expect(htmlContent).toContain(NO_IMAGE_TEXT);
var imgDiv = inputImageView.$('.js-image-container');
expect(_.size(imgDiv)).toBe(0);
});
it('renders an image if specified', function () {
inputImageView.model.set('image', SQUARE_ICON_URL);
inputImageView.render();
expect(inputImageView._getImageURL()).toBe(SQUARE_ICON_URL);
var htmlContent = inputImageView.$('.Editor-fillImage').html();
expect(htmlContent).not.toContain(NO_IMAGE_TEXT);
var imgDiv = inputImageView.$('.js-image-container');
expect(_.size(imgDiv)).toBe(1);
expect(spyOnSvgRequest).toHaveBeenCalled();
});
it('can create a color file view to select assets', function () {
inputImageView._createContentView();
expect(inputImageView._inputColorFileView).not.toBeNull();
});
});
@@ -0,0 +1,287 @@
var Backbone = require('backbone');
var FactoryModals = require('../../../factories/modals');
describe('components/form-components/editors/fill', function () {
beforeEach(function () {
this.model = new Backbone.Model({
names: 'pepe',
stroke: {
size: {
range: [1, 30],
attribute: 'the_geom',
quantification: 'Quantile'
},
color: {
bins: 5,
range: ['#FFFFFF', '#FABADA', '#00FF00', '#000000', '#999999'],
attribute: 'column1',
quantification: 'Jenks',
opacity: 0.5
}
},
fill: {
color: {
bins: 5,
range: ['#FFFFFF', '#FABADA', '#00FF00', '#000000', '#999999'],
attribute: 'column1',
quantification: 'Jenks',
opacity: 0.5
},
size: {
range: [1, 30],
attribute: 'the_geom',
quantification: 'Quantile'
}
}
});
this._userModel = {
featureEnabled: function () { return true; }
};
this._schema = {
configModel: {},
query: 'SELECT * from table',
options: [
{ label: 'column1', type: 'number' },
{ label: 'column2', type: 'number' },
{ label: 'column3', type: 'number' }
]
};
this.modals = FactoryModals.createModalService();
this.view = new Backbone.Form.editors.Fill({
key: 'stroke',
userModel: this._userModel,
modals: this.modals,
schema: this._schema,
model: this.model
});
this.view.render();
});
it('should render properly', function () {
expect(this.view.$('.CDB-OptionInput-item').length).toBe(2);
expect(this.view.$el.text()).toContain('1..30');
});
it('should render the input fields', function () {
expect(this.view.$('.CDB-OptionInput-item').length).toBe(2);
});
it('should show the input fields correctly sorted', function () {
expect(this.view.$('.CDB-OptionInput-item:first-child').text()).toContain('1..30');
expect(this.view.$('.CDB-OptionInput-item:last-child').html()).toContain('rgba(255, 255, 255, 0.5),rgba(250, 186, 218, 0.5),rgba(0, 255, 0, 0.5),rgba(0, 0, 0, 0.5),rgba(153, 153, 153, 0.5)');
});
it('should open a fill dialog on click', function () {
expect(this.view.$('.Editor-boxModal').length).toBe(0);
this.view.$('.CDB-OptionInput-item:first-child').click();
expect(this.view.$('.Editor-boxModal').length).toBe(1);
});
it('should render the size dialog component ', function () {
this.view.$('.CDB-OptionInput-item:first-child').click();
expect(this.view.$('.CDB-NavMenu-item').length).toEqual(2);
expect(this.view.$('.Editor-boxModal').text()).toContain('form-components.editors.fill.input-number.fixed');
expect(this.view.$('.Editor-boxModal').text()).toContain('form-components.editors.fill.input-number.by-value');
expect(this.view.$('.Editor-boxModal').text()).toContain('form-components.editors.fill.quantification.methods.quantiles');
expect(this.view.$('.Editor-boxModal').text()).toContain('the_geom');
});
it('should render the color dialog component ', function () {
this.view.$('.CDB-OptionInput-item:last-child').click();
expect(this.view.$('.CDB-NavMenu-item').length).toEqual(2);
expect(this.view.$('.Editor-boxModal').text()).toContain('form-components.editors.fill.input-color.solid');
expect(this.view.$('.Editor-boxModal').text()).toContain('form-components.editors.fill.input-color.value');
expect(this.view.$('.Editor-boxModal').text()).toContain('5 form-components.editors.fill.input-ramp.buckets');
expect(this.view.$('.Editor-boxModal').text()).toContain('column1');
expect(this.view.$('.Editor-boxModal').text()).toContain('form-components.editors.fill.quantification.methods.jenks');
});
describe('hide panes', function () {
beforeEach(function () {
this.view = new Backbone.Form.editors.Fill({
key: 'fill',
schema: {
configModel: {},
userModel: {
featureEnabled: function () { return true; }
},
modals: this.modals,
query: 'SELECT * FROM table',
options: [
{ label: 'column1', type: 'number' },
{ label: 'column2', type: 'number' },
{ label: 'column3', type: 'number' }
],
editorAttrs: {
size: {
hidePanes: ['fixed']
},
color: {
hidePanes: ['fixed']
}
}
},
model: this.model
});
this.view.render();
});
it('should render the size dialog component ', function () {
this.view.$('.CDB-OptionInput-item:first-child').click();
expect(this.view.$('.CDB-NavMenu-item').length).toEqual(1);
expect(this.view.$('.Editor-boxModal').text()).not.toContain('form-components.editors.fill.input-number.fixed');
expect(this.view.$('.Editor-boxModal').text()).toContain('form-components.editors.fill.input-number.by-value');
expect(this.view.$('.Editor-boxModal').text()).toContain('form-components.editors.fill.quantification.methods.quantiles');
expect(this.view.$('.Editor-boxModal').text()).toContain('the_geom');
});
it('should render the color dialog component', function () {
this.view.$('.CDB-OptionInput-item:last-child').click();
expect(this.view.$('.CDB-NavMenu-item').length).toEqual(1);
expect(this.view.$('.Editor-boxModal').text()).not.toContain('form-components.editors.fill.input-color.solid');
expect(this.view.$('.Editor-boxModal').text()).toContain('form-components.editors.fill.input-color.value');
expect(this.view.$('.Editor-boxModal').text()).toContain('5 form-components.editors.fill.input-ramp.buckets');
expect(this.view.$('.Editor-boxModal').text()).toContain('column1');
expect(this.view.$('.Editor-boxModal').text()).toContain('form-components.editors.fill.quantification.methods.jenks');
});
describe('setting an image', function () {
beforeEach(function () {
this.model = new Backbone.Model({
stroke: {
size: {
range: [1, 30],
attribute: 'the_geom',
quantification: 'Quantile'
},
color: {
bins: 5,
range: ['#FFFFFF', '#FABADA', '#00FF00', '#000000', '#999999'],
attribute: 'column1',
quantification: 'Jenks',
opacity: 0.5
}
},
fill: {
color: {
fixed: '#f1f1f1',
opacity: 0.5
},
size: {
fixed: 10
}
}
});
this.view = new Backbone.Form.editors.Fill({
key: 'fill',
userModel: this._userModel,
modals: this.modals,
schema: this._schema,
model: this.model
});
this.color = this.view._inputCollection.findWhere({ type: 'color' });
this.size = this.view._inputCollection.findWhere({ type: 'size' });
});
it('should adjust the min image size if it\'s too small', function () {
this.color.set('image', 'test.png');
expect(this.size.get('fixed')).toBe(20);
});
it('shouldn\'t adjust the image size if its big enough', function () {
this.size.set({ fixed: 30 }, { silent: true });
this.color.set('image', 'dog.png');
expect(this.size.get('fixed')).toBe(30);
});
it('shouldn\'t adjust the image size if there was already an image set', function () {
this.size.set({ fixed: 1 }, { silent: true });
this.color.set({ image: 'duck.png' }, { silent: true });
this.color.set('image', 'cat.png');
expect(this.size.get('fixed')).toBe(1);
});
});
describe('setting images', function () {
beforeEach(function () {
this.model = new Backbone.Model({
stroke: {
size: {
range: [1, 30],
attribute: 'the_geom',
quantification: 'Quantile'
},
color: {
bins: 5,
range: ['#FFFFFF', '#FABADA', '#00FF00', '#000000', '#999999'],
attribute: 'column1',
quantification: 'Jenks',
opacity: 0.5
}
},
fill: {
color: {
fixed: '#f1f1f1',
opacity: 0.5
},
size: {
fixed: 10
}
}
});
this.view = new Backbone.Form.editors.Fill({
key: 'fill',
userModel: this._userModel,
modals: this.modals,
schema: this._schema,
model: this.model
});
this.color = this.view._inputCollection.findWhere({ type: 'color' });
this.size = this.view._inputCollection.findWhere({ type: 'size' });
});
it('should adjust the min image size if it\'s too small', function () {
this.color.set('images', ['test.png']);
expect(this.size.get('fixed')).toBe(20);
});
it('shouldn\'t adjust the image size if its big enough', function () {
this.size.set({ fixed: 30 }, { silent: true });
this.color.set('images', ['test.png']);
expect(this.size.get('fixed')).toBe(30);
});
it('shouldn\'t adjust the image size if there was already an image set', function () {
this.size.set({ fixed: 1 }, { silent: true });
this.color.set({ images: ['duck.png', 'ping.jpg'] }, { silent: true });
this.color.set('images', ['duck.png', 'ping.jpg', 'cat.gif']);
expect(this.size.get('fixed')).toBe(1);
});
it('shouldn\'t adjust the image size when no image is set', function () {
this.size.set({ fixed: 1 }, { silent: true });
this.color.set('images', ['']);
expect(this.size.get('fixed')).toBe(1);
});
});
});
afterEach(function () {
this.view.remove();
});
});
@@ -0,0 +1,127 @@
var $ = require('jquery');
var ColorPicker = require('builder/components/color-picker/color-picker');
var ESCAPE_KEY_CODE = 27;
var simulateEscapeKeyPress = function () {
var e = $.Event('keydown');
e.keyCode = e.which = ESCAPE_KEY_CODE;
$(document).trigger(e);
};
describe('components/form-components/editors/fill/color-picker/color-picker', function () {
describe('ESC key press', function () {
beforeEach(function () {
spyOn(ColorPicker.prototype, '_onEscapePressed');
this.view = new ColorPicker({
value: '#A6CEE3',
opacity: 0.5
});
this.view.render();
});
it('should close', function () {
simulateEscapeKeyPress();
expect(ColorPicker.prototype._onEscapePressed).toHaveBeenCalled();
});
afterEach(function () {
this.view.remove();
});
});
describe('with opacity', function () {
beforeEach(function () {
this.view = new ColorPicker({
value: '#A6CEE3',
opacity: 0.5
});
this.view.render();
});
it('should get render', function () {
expect(this.view.$('.js-hex').val()).toBe('#A6CEE3');
expect(this.view.$('.js-r').val()).toBe('166');
expect(this.view.$('.js-g').val()).toBe('206');
expect(this.view.$('.js-b').val()).toBe('227');
expect(this.view.$('.js-a').val()).toBe('0.5');
});
it('should not have leaks', function () {
expect(this.view).toHaveNoLeaks();
});
afterEach(function () {
this.view.remove();
});
});
describe('withouth opacity', function () {
beforeEach(function () {
this.view = new ColorPicker({
value: '#A6CEE3',
opacity: 0.5,
disableOpacity: true
});
this.view.render();
});
it('should disable the opacity selector', function () {
expect(this.view.$('.js-a').val()).toBe('0.5');
expect(this.view.$('.js-a').hasClass('is-disabled')).toBe(true);
expect(this.view.$('.js-colorPicker .js-alpha').hasClass('is-hidden')).toBe(true);
});
it('should change the hex color directly', function () {
this.view.$('.js-hex').val('#CCC');
var e = $.Event('blur');
e.which = 37;
this.view.$('.js-hex').trigger(e);
expect(this.view.model.get('hex')).toBe('#cccccc');
});
it('should change each color individually', function () {
this.view.$('.js-r').val('10');
this.view.$('.js-g').val('20');
this.view.$('.js-b').val('30');
var e = $.Event('blur');
e.which = 37;
this.view.$('.js-r').trigger(e);
expect(this.view.model.get('hex')).toBe('#0a141e');
});
it('should change each the alpha', function () {
this.view.$('.js-a').val('0.7');
var e = $.Event('blur');
e.which = 37;
this.view.$('.js-a').trigger(e);
expect(this.view.model.get('opacity')).toBe(0.7);
});
it('should show the errors', function () {
this.view.$('.js-r').val('10');
this.view.$('.js-g').val('20');
this.view.$('.js-b').val('what?');
var e = $.Event('blur');
e.which = 37;
this.view.$('.js-b').trigger(e);
expect(this.view.model.get('hex')).toBe('#A6CEE3');
expect(this.view.$('.js-b').hasClass('has-error')).toBeTruthy();
});
it('should not have leaks', function () {
expect(this.view).toHaveNoLeaks();
});
afterEach(function () {
this.view.remove();
});
});
});
@@ -0,0 +1,43 @@
var _ = require('underscore');
var DialogModel = require('builder/components/dialog/dialog-model');
var DialogView = require('builder/components/dialog/dialog-view');
describe('components/fill-dialog', function () {
var view, model;
var createViewFn = function () {
model = new DialogModel({});
var view = new DialogView(({
model: model
}));
return view;
};
beforeEach(function () {
view = createViewFn();
});
afterEach(function () {
view.clean();
});
xit('should get rendered', function () {
// TODO
});
it('should not have leaks', function () {
view.render();
expect(view).toHaveNoLeaks();
});
afterEach(function () {
view.remove();
});
it('should render properly', function () {
view.render();
expect(_.size(view._subviews)).toBe(2);
});
});
@@ -0,0 +1,342 @@
var _ = require('underscore');
var Backbone = require('backbone');
var InputColor = require('builder/components/input-color/input-color');
var rampList = require('builder/components/input-color/input-quantitative-ramps/ramps');
var ConfigModel = require('builder/data/config-model');
var UserModel = require('builder/data/user-model');
var FactoryModals = require('../../../../factories/modals');
describe('components/form-components/editors/fill/input-color', function () {
var svgResponse = {
status: 200,
contentType: 'image/svg+xml',
responseText: '<svg xmlns:a="genius.com" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"><path></path></svg>'
};
var imgUrl = 'http://www.image.com/image.svg';
var fixed = '#c0ffee';
beforeEach(function () {
this.configModel = new ConfigModel({
base_url: '/u/pepe'
});
this.userModel = new UserModel({}, {
configModel: this.configModel
});
this.modals = FactoryModals.createModalService();
this.model = new Backbone.Model({
bins: 5,
range: ['#FFF', '#FABADA', '#00FF00', '#000', '#999999'],
attribute: 'column1',
quantification: 'jenks',
opacity: 0.5
});
this.view = new InputColor(({
model: this.model,
userModel: this.userModel,
configModel: this.configModel,
query: 'SELECT * from table',
columns: [
{ label: 'column1', type: 'number' },
{ label: 'column2', type: 'number' },
{ label: 'column3', type: 'number' }
]
}));
this.view.render();
});
afterEach(function () {
this.view.remove();
});
it('should render properly', function () {
expect(_.size(this.view._subviews)).toBe(1);
});
it('should get selected', function () {
this.model.set('selected', true);
expect(this.view.$el.hasClass('is-active')).toBeTruthy();
});
it('should create a content view', function () {
expect(this.view.model.get('createContentView')).toBeDefined();
});
it('should trigger a click event when clicked', function () {
var clickEvent = false;
this.view.bind('click', function () {
clickEvent = true;
});
this.view.$el.click();
expect(clickEvent).toBeTruthy();
});
describe('range', function () {
beforeEach(function () {
this.model = new Backbone.Model({
bins: 5,
range: ['#FFFFFF', '#FABADA', '#00FF00', '#000000', '#999999'],
attribute: 'column1',
quantification: 'Jenks',
opacity: 0.50
});
this.view = new InputColor(({
model: this.model,
userModel: this.userModel,
configModel: this.configModel,
query: 'SELECT * from table',
columns: [
{ label: 'column1', type: 'number' },
{ label: 'column2', type: 'number' },
{ label: 'column3', type: 'number' }
]
}));
this.view.render();
});
it('should render properly', function () {
expect(this.view.$('.ColorBar').length).toBe(1);
});
it('should update when the value has changed', function () {
this.model.set('range', ['#FFFFFF', '#FFFF00', '#0000FF']);
expect(this.view.$('.ColorBar').length).toBe(1);
expect(this.view.$('.ColorBar').attr('style')).toBeDefined();
expect(this.view._getValue()).toEqual(['rgba(255, 255, 255, 0.5)', 'rgba(255, 255, 0, 0.5)', 'rgba(0, 0, 255, 0.5)']);
});
it('should set opacity for each color', function () {
this.model.set({
range: ['#FABADA', '#00FFAA', '#0000FF'],
opacity: 0.99
});
expect(this.view.$('.ColorBar').length).toBe(1);
expect(this.view.$('.ColorBar').attr('style')).toBeDefined();
expect(this.view._getValue()).toEqual(['rgba(250, 186, 218, 0.99)', 'rgba(0, 255, 170, 0.99)', 'rgba(0, 0, 255, 0.99)']);
});
});
describe('image', function () {
describe('without image enabled', function () {
it('should not render the image', function () {
this.view = new InputColor(({
model: new Backbone.Model({
opacity: 0.5,
fixed: fixed,
attribute: 'column1'
}),
userModel: {
featureEnabled: function () {
return true;
}
},
modals: this.modals,
configModel: {},
query: 'SELECT * from table',
columns: [
{ label: 'column1', type: 'string' }
]
}));
this.view.render();
expect(this.view.$('.Editor-fillImage').length).toBe(0);
});
});
describe('with image enabled', function () {
describe('without image', function () {
it('should render image link if category images are present', function () {
this.view = new InputColor(({
model: new Backbone.Model({
opacity: 0.5,
fixed: fixed,
images: [imgUrl, imgUrl, imgUrl],
attribute: 'column1'
}),
userModel: {
featureEnabled: function () {
return true;
}
},
modals: this.modals,
configModel: {},
editorAttrs: {
imageEnabled: true
},
query: 'SELECT * from table',
columns: [
{ label: 'column1', type: 'string' }
]
}));
this.view.render();
expect(this.view.$('.Editor-fillImage').html()).toContain('form-components.editors.fill.input-color.img');
});
it('should not render image link if category images are not present', function () {
this.view = new InputColor(({
model: new Backbone.Model({
opacity: 0.5,
fixed: fixed,
attribute: 'column1'
}),
userModel: {
featureEnabled: function () {
return true;
}
},
modals: this.modals,
configModel: {},
editorAttrs: {
imageEnabled: true
},
query: 'SELECT * from table',
columns: [
{ label: 'column1', type: 'string' }
]
}));
this.view.render();
expect(this.view.$('.Editor-fillImage').html()).not.toContain('Img');
});
});
describe('with image', function () {
var fixture;
beforeEach(function () {
jasmine.Ajax.install();
jasmine.Ajax.stubRequest(new RegExp('^http(s)?.*/image.svg'))
.andReturn(svgResponse);
this.view = new InputColor(({
model: new Backbone.Model({
image: imgUrl,
opacity: 0.5,
fixed: fixed,
attribute: 'column1'
}),
userModel: {
featureEnabled: function () {
return true;
}
},
modals: this.modals,
configModel: {},
editorAttrs: {
imageEnabled: true
},
query: 'SELECT * from table',
columns: [
{ label: 'column1', type: 'string' }
]
}));
// For getting right values from the SVG element, it needs to be attached to the DOM
fixture = document.createElement('div');
fixture.id = 'fixture';
document.getElementsByTagName('body')[0].appendChild(fixture);
fixture.appendChild(this.view.$el[0]);
this.view.render();
});
afterEach(function () {
fixture.parentNode.removeChild(fixture);
jasmine.Ajax.uninstall();
});
it('should render the image', function () {
expect(this.view.$('.Editor-fillImage').length).toBe(1);
});
it('SVG should have been loaded', function () {
var image = this.view.$('.js-image');
expect(image[0].tagName.toUpperCase()).toBe('SVG');
expect(image.attr('xmlns:a')).toBeUndefined();
expect(image.attr('class')).toContain('Editor-fillImageAsset');
expect(image.attr('class')).toContain('js-image');
var cssFill = image.css('fill').toLowerCase();
var pathFill = image.find('path').css('fill').toLowerCase();
expect(cssFill === 'rgb(192, 255, 238)' || cssFill === '#c0ffee').toBe(true);
expect(pathFill === 'rgb(192, 255, 238)' || pathFill === '#c0ffee').toBe(true);
});
it('._updateImageColor should change fill attribute', function () {
// Trigger _updateImageColor via model change
this.view.model.set('fixed', '#0FF1CE'); // rgb(15, 241, 206)
var image = this.view.$('.js-image');
var cssFill = image.css('fill').toLowerCase();
expect(cssFill === 'rgb(15, 241, 206)' || cssFill === '#0ff1ce').toBe(true);
});
});
});
});
describe('migrate old range', function () {
beforeEach(function () {
this.model = new Backbone.Model({
bins: 5,
range: 'inverted_green',
attribute: 'column1',
quantification: 'jenks',
opacity: 0.5
});
this.view = new InputColor(({
model: this.model,
userModel: this.userModel,
configModel: this.configModel,
query: 'SELECT * from table',
columns: [
{ label: 'column1', type: 'number' },
{ label: 'column2', type: 'number' },
{ label: 'column3', type: 'number' }
]
}));
this.view.render();
});
it('should migrate the range', function () {
expect(this.model.get('range')).toBe(rampList['inverted_green'][5]);
});
});
describe('with help', function () {
beforeEach(function () {
this.view = new InputColor(({
model: this.model,
userModel: this.userModel,
configModel: this.configModel,
query: 'SELECT * from table',
columns: [
{ label: 'column1', type: 'number' },
{ label: 'column2', type: 'number' },
{ label: 'column3', type: 'number' }
],
editorAttrs: {
help: 'help'
}
}));
});
describe('.render', function () {
it('should render properly', function () {
this.view.render();
expect(_.size(this.view._subviews)).toBe(2);
expect(this.view.$('.js-help').attr('data-tooltip')).toContain('help');
});
});
});
it('should not have any leaks', function () {
expect(this.view).toHaveNoLeaks();
});
});
@@ -0,0 +1,102 @@
var Backbone = require('backbone');
var AssetHeaderView = require('builder/components/input-color/assets-picker/asset-header-view');
describe('components/form-components/editors/fill/input-color/assets-picker/asset-header-view', function () {
beforeEach(function () {
this.assetsCollection = new Backbone.Collection([
{ item: 1, state: '' },
{ item: 2, state: '' },
{ item: 3, state: '' }
]);
this.view = new AssetHeaderView({
title: 'Title',
editable: true,
assetsCollection: this.assetsCollection
});
this.view.render();
});
it('should render', function () {
expect(this.view.$el.text()).toContain('Title');
});
describe('options', function () {
beforeEach(function () {
this.assetsCollection.at(0).set('state', 'selected');
this.assetsCollection.at(1).set('state', 'selected');
});
it('should show select all link when some items are selected', function () {
expect(this.view.$el.find('.js-select-all').length).toBe(1);
});
it('should hide select all link when all items are selected', function () {
this.assetsCollection.at(2).set('state', 'selected');
expect(this.view.$el.find('.js-select-all').length).toBe(0);
});
it('should show deselect all link if all the items are selected', function () {
this.assetsCollection.at(2).set('state', 'selected');
expect(this.view.$el.find('.js-deselect-all').length).toBe(1);
});
it('should show remove link when an item is selected', function () {
expect(this.view.$el.find('.js-remove').length).toBe(1);
});
it('should hide remove link when no item is selected', function () {
this.assetsCollection.at(0).set('state', '');
this.assetsCollection.at(1).set('state', '');
this.assetsCollection.at(2).set('state', '');
expect(this.view.$el.find('.js-remove').length).toBe(0);
});
});
describe('triggers', function () {
beforeEach(function () {
this.assetsCollection.at(0).set('state', 'selected');
this.assetsCollection.at(1).set('state', 'selected');
});
it('should trigger select-all event', function () {
var selectAllTrigger;
this.view.bind('select-all', function () {
selectAllTrigger = true;
});
this.view.$el.find('.js-select-all').click();
expect(selectAllTrigger).toBeTruthy();
});
it('should trigger remove event', function () {
var removeTrigger;
this.view.bind('remove', function () {
removeTrigger = true;
});
this.view.$el.find('.js-remove').click();
expect(removeTrigger).toBeTruthy();
});
it('should trigger events for each option', function () {
var deselectTrigger;
this.assetsCollection.at(2).set('state', 'selected');
this.view.bind('deselect-all', function () {
deselectTrigger = true;
});
this.view.$el.find('.js-deselect-all').click();
expect(deselectTrigger).toBeTruthy();
});
});
afterEach(function () {
this.view.clean();
});
});
@@ -0,0 +1,118 @@
var _ = require('underscore');
var Backbone = require('backbone');
var CoreView = require('backbone/core-view');
var AssetsListView = require('builder/components/input-color/assets-picker/assets-list-view');
describe('components/form-components/editors/fill/input-color/asset-picker/assets-list-view', function () {
function createViewFn (options) {
var icons = [
{ name: 'icon1', icon: 'icon1' },
{ name: 'icon2', icon: 'icon2' },
{ name: 'icon3', icon: 'icon3' }
];
this.view = new AssetsListView(_.extend({
selectedAsset: new Backbone.Model(),
title: 'Title',
icons: icons,
disclaimer: 'Disclaimer',
folder: 'folder',
kind: 'marker',
size: '10'
}, options));
}
beforeEach(function () {
this.createView = createViewFn.bind(this);
});
afterEach(function () {
this.view.remove();
});
describe('.initialize', function () {
it('should call ._setupAssets and get assets with default options if no options provided', function () {
this.createView();
var itemNames = _.map(this.view._assetsCollection.models, function (model) {
return model.attributes.name;
});
expect(itemNames.length).toBe(3);
expect(_.contains(itemNames, 'icon1'));
expect(_.contains(itemNames, 'icon2'));
expect(_.contains(itemNames, 'icon3'));
});
it('should call ._setupAssets and get assets with provided options', function () {
this.createView({
folder: 'a folder',
size: 48,
host: 'a host',
ext: 'an extension'
});
_.each(this.view._assetsCollection.models, function (model) {
expect(model.attributes.ext).toBe('an extension');
expect(model.attributes.folder).toBe('a folder');
expect(model.attributes.host).toBe('a host');
expect(model.attributes.size).toBe(48);
});
});
it('should limit asset collection length if limit option is present', function () {
this.createView({
limit: 2
});
var itemNames = _.map(this.view._assetsCollection.models, function (model) {
return model.attributes.name;
});
expect(itemNames.length).toBe(2);
expect(_.contains(itemNames, 'icon1'));
expect(_.contains(itemNames, 'icon2'));
});
it('should add related models', function () {
spyOn(CoreView.prototype, 'add_related_model').and.callThrough();
this.createView();
expect(CoreView.prototype.add_related_model).toHaveBeenCalledWith(this.view._assetsCollection);
});
});
describe('render', function () {
it('should render icons according to the template', function () {
this.createView();
this.view.render();
var expectedIcons = ['icon1', 'icon2', 'icon3'];
_.each(expectedIcons, function (icon) {
var $icon = this.view.$("img[alt='" + icon + "']");
expect($icon.length).toBe(1);
expect($icon.attr('crossorigin')).toBe('anonymous');
expect($icon.attr('src').indexOf(icon)).not.toBe(0);
}, this);
});
});
describe('._selectItem', function () {
it('should select given item and deselect the others', function () {
var selectedAsset = new Backbone.Model();
this.createView({
selectedAsset: selectedAsset
});
this.view.render();
var url = this.view.$('.AssetsList-item:nth-child(1) img').attr('src');
this.view.$('.AssetsList-item:nth-child(1) .js-asset').click();
expect(selectedAsset.get('url')).toBe(url);
expect(selectedAsset.get('kind')).toBe('marker');
});
});
});
@@ -0,0 +1,327 @@
var $ = require('jquery');
var Backbone = require('backbone');
var ConfigModel = require('builder/data/config-model');
var UserModel = require('builder/data/user-model');
var AssetsView = require('builder/components/input-color/assets-picker/assets-view');
describe('components/form-components/editors/fill/input-color/assets-view', function () {
var createCalls = [];
var files = ['one', 'two'];
beforeEach(function () {
spyOn($, 'ajax').and.callFake(function (req) {
var d = $.Deferred();
d.resolve();
return d.promise();
});
this.model = new Backbone.Model();
this._configModel = new ConfigModel({
base_url: '/u/pepe'
});
this._userModel = new UserModel({}, {
configModel: this._configModel
});
this.view = new AssetsView({
model: this.model,
modalModel: {
destroy: function () {}
},
configModel: this._configModel,
userModel: this._userModel
});
this.view.render();
});
function mockCreate (callback) {
this.view._userAssetCollection.create = function (options, callbacks) {
var createCall = {
kind: options.kind,
type: options.type,
url: options.url,
filename: options.filename,
callbacks: callbacks
};
var model = this.add(options);
createCalls.push(createCall);
if (callback) {
if (callback === 'error') {
callbacks[callback].call(this, model, {
responseText: '{"error": ["hi, I am an error"]}'
});
} else if (callback === 'success') {
callbacks['complete'].call(this);
callbacks[callback].call(this);
} else {
callbacks[callback].call(this);
}
}
};
}
describe('render', function () {
it('should render tabs', function () {
expect(this.view.$el.text()).toBeDefined();
expect(this.view.$el.text()).toContain('components.modals.add-asset.icons');
expect(this.view.$el.text()).toContain('components.modals.add-asset.your-uploads');
expect(this.view.$el.text()).toContain('components.modals.add-asset.upload-file');
});
it('should render upload button', function () {
expect(this.view.$('.js-add').length).toBe(1);
expect(this.view.$('.js-add').hasClass('is-disabled')).toBeTruthy();
expect(this.view._stateModel.get('modalEnabled')).toBeFalsy();
});
it('should toggle the set button state', function () {
this.view._stateModel.set('modalEnabled', true);
expect(this.view.$('.js-add').hasClass('is-disabled')).toBeFalsy();
this.view._stateModel.set('modalEnabled', false);
expect(this.view.$('.js-add').hasClass('is-disabled')).toBeTruthy();
});
it('should toggle the set button state when there\'s no image selected', function () {
this.view._selectedAsset.set('url', 'batman.png');
expect(this.view.$('.js-add').hasClass('is-disabled')).toBeFalsy();
expect(this.view._stateModel.get('modalEnabled')).toBeTruthy();
this.view._selectedAsset.set('url', '');
expect(this.view.$('.js-add').hasClass('is-disabled')).toBeTruthy();
expect(this.view._stateModel.get('modalEnabled')).toBeFalsy();
});
it('should render disclaimer', function () {
expect(this.view.$el.text()).toContain('assets.maki-icons.disclaimer');
});
});
describe('._initSetButtonState', function () {
beforeEach(function () {
this._userModel.getOrganization = function () {
return new Backbone.Model({ id: 1 });
};
this._userModel.isInsideOrg = function () {
return true;
};
this.view = new AssetsView({
model: this.model,
modalModel: {
destroy: function () {}
},
configModel: this._configModel,
userModel: this._userModel
});
this.view.render();
});
it('should return nothing if there\'s no image selected', function () {
this.view.model.set('image', null);
expect(this.view._initSetButtonState()).toBeUndefined();
});
it('should enable the button if a marker is set', function () {
this.model.set({ image: 'hi.png', kind: 'marker' });
this.view._initSetButtonState();
expect(this.view.$('.js-add').hasClass('is-disabled')).toBeFalsy();
expect(this.view._stateModel.get('modalEnabled')).toBeTruthy();
});
it('should enable the button if a user icon is set', function () {
this.model.set({ image: 'hi.png', kind: 'custom-marker' });
this.view._userAssetCollection.add({ public_url: 'hi.png' });
this.view._initSetButtonState();
expect(this.view.$('.js-add').hasClass('is-disabled')).toBeFalsy();
expect(this.view._stateModel.get('modalEnabled')).toBeTruthy();
});
it('should enable the button if an org icon is set', function () {
this.model.set({ image: 'hi.png', kind: 'custom-marker' });
this.view._organizationAssetCollection.add({ public_url: 'hi.png' });
this.view._initSetButtonState();
expect(this.view.$('.js-add').hasClass('is-disabled')).toBeFalsy();
expect(this.view._stateModel.get('modalEnabled')).toBeTruthy();
});
afterEach(function () {
this.view.clean();
});
});
describe('._onFileSelected', function () {
it('should create an icon model for each selected file', function () {
mockCreate.call(this);
spyOn(this.view, '_getSelectedFiles').and.returnValue(files);
spyOn(this.view, '_beforeAssetUpload');
spyOn(this.view, '_onAssetUploaded');
spyOn(this.view, '_onAssetUploadError');
spyOn(this.view, '_onAssetUploadComplete');
this.view._onFileSelected();
expect(createCalls.length).toBe(2);
expect(createCalls[0].kind).toEqual('custom-marker');
expect(createCalls[0].filename).toEqual(files[0]);
expect(createCalls[0].type).toEqual('file');
expect(createCalls[1].kind).toEqual('custom-marker');
expect(createCalls[1].filename).toEqual(files[1]);
expect(createCalls[1].type).toEqual('file');
// Assert that every request callback has been hooked up
createCalls[0].callbacks['beforeSend']();
expect(this.view._beforeAssetUpload).toHaveBeenCalled();
createCalls[0].callbacks['success']();
expect(this.view._onAssetUploaded).toHaveBeenCalled();
createCalls[0].callbacks['error']();
expect(this.view._onAssetUploadError).toHaveBeenCalled();
createCalls[0].callbacks['complete']();
expect(this.view._onAssetUploadComplete).toHaveBeenCalled();
});
});
describe('._beforeAssetUpload', function () {
it('should set loading state', function () {
this.view._beforeAssetUpload();
expect(this.view._stateModel.get('uploads')).toBe(1);
expect(this.view._stateModel.get('status')).toBe('loading');
});
});
describe('._onAssetUploaded', function () {
it('should reset selection after a successfull upload', function () {
mockCreate.call(this, 'success');
spyOn(this.view, '_resetFileSelection');
spyOn(this.view, '_getSelectedFiles').and.returnValue(files);
this.view.$('.js-fileInput').trigger('change');
expect(this.view._resetFileSelection).toHaveBeenCalled();
});
it('should render the new uploaded file and go to the uploads tab', function () {
mockCreate.call(this, 'success');
spyOn(this.view, '_getSelectedFiles').and.returnValue(['file.png']);
this.view.$('.js-fileInput').trigger('change');
expect(this.view.$('.AssetsList-item').length).toBe(2);
expect(this.view._assetsTabPaneView.getSelectedTabPane().get('name')).toBe('your-uploads');
});
});
describe('._onAssetUploadError', function () {
beforeEach(function () {
mockCreate.call(this, 'error');
spyOn(this.view, '_getSelectedFiles').and.returnValue(files);
spyOn(this.view, '_resetFileSelection');
this.view.$('.js-fileInput').trigger('change');
});
it('should reset selection', function () {
expect(this.view._resetFileSelection).toHaveBeenCalled();
});
it('should show the proper error message', function () {
expect(this.view._stateModel.get('error_message')).toBe('hi, I am an error');
expect(this.view._stateModel.get('status')).toBe('error');
});
it('should remove the model from _userAssetCollection', function () {
expect(this.view._userAssetCollection.length).toBe(0);
});
});
describe('._uploadURL', function () {
it('should create an upload', function () {
var url = 'http://carto.com/img/pin.png';
mockCreate.call(this);
spyOn(this.view, '_beforeAssetUpload');
spyOn(this.view, '_onAssetUploaded');
spyOn(this.view, '_onAssetUploadError');
spyOn(this.view, '_onAssetUploadComplete');
this.view._uploadURL(url);
expect(createCalls.length).toBe(1);
expect(createCalls[0].kind).toEqual('custom-marker');
expect(createCalls[0].url).toEqual(url);
expect(createCalls[0].type).toEqual('url');
// Assert that every request callback has been hooked up
createCalls[0].callbacks['beforeSend']();
expect(this.view._beforeAssetUpload).toHaveBeenCalled();
createCalls[0].callbacks['success']();
expect(this.view._onAssetUploaded).toHaveBeenCalled();
createCalls[0].callbacks['error']();
expect(this.view._onAssetUploadError).toHaveBeenCalled();
createCalls[0].callbacks['complete']();
expect(this.view._onAssetUploadComplete).toHaveBeenCalled();
});
});
describe('._onAssetUploadComplete', function () {
it('should go to the upload tab', function () {
this.view._stateModel.set('uploads', 2);
mockCreate.call(this, 'complete');
spyOn(this.view, '_getSelectedFiles').and.returnValue(files);
this.view.$('.js-fileInput').trigger('change');
expect(this.view._stateModel.get('status')).toBe('show');
expect(this.view._stateModel.get('uploads')).toBe(0);
expect(this.view._assetsTabPaneView.getSelectedTabPaneName()).toBe('your-uploads');
});
});
describe('_onSetImage', function () {
it('should kill event, trigger a `change` event and destroy modal', function () {
var changeTriggered = false;
var changeImage;
this.view._selectedAsset.set({
url: 'batman.png',
kind: 'marker'
});
this.view.on('change', function (data) {
changeTriggered = true;
changeImage = data;
});
spyOn(this.view, 'killEvent');
spyOn(this.view._modalModel, 'destroy');
this.view.$('.js-add').click();
expect(this.view.killEvent).toHaveBeenCalled();
expect(changeTriggered).toBe(true);
expect(changeImage.url).toBe('batman.png');
expect(changeImage.kind).toBe('marker');
expect(this.view._modalModel.destroy).toHaveBeenCalled();
});
});
it('should not have leaks', function () {
expect(this.view).toHaveNoLeaks();
});
afterEach(function () {
createCalls = [];
this.view.clean();
});
});
@@ -0,0 +1,69 @@
var Backbone = require('backbone');
var InputAssetPickerHeader = require('builder/components/input-color/assets-picker/input-asset-picker-header');
describe('components/form-components/editors/fill/input-color/assets-picker/input-asset-picker-header', function () {
beforeEach(function () {
this.model = new Backbone.Model({
index: 0,
ramp: [{
color: '#FF0000',
title: 'hola',
image: 'http://www.image.com/image.jpg'
}]
});
this.view = new InputAssetPickerHeader({
index: 0,
model: this.model
});
this.view.render();
});
describe('render', function () {
it('should render template', function () {
expect(this.view.$el.html()).toContain('CDB-Box-modalHeader');
});
});
describe('.getRampItem', function () {
it('should return ramp item element', function () {
var item = this.view._getRampItem();
expect(item.color).toBe('#FF0000');
});
});
describe('._onClickBack', function () {
it('should trigger back function', function () {
var isBack;
this.view.bind('back', function () {
isBack = true;
}, this);
this.view.$('.js-back').click();
expect(isBack).toBeTruthy();
});
});
describe('._onGoToColorPicker', function () {
it('should trigger goToColorPicker function', function () {
var isInColorPicker;
this.view.bind('goToColorPicker', function () {
isInColorPicker = true;
}, this);
this.view.$('.js-colorPicker').click();
expect(isInColorPicker).toBeTruthy();
});
});
it('should not have leaks', function () {
expect(this.view).toHaveNoLeaks();
});
afterEach(function () {
this.view.clean();
});
});
@@ -0,0 +1,101 @@
var InputAssetPickerView = require('builder/components/input-color/assets-picker/input-asset-picker-view');
var UserModel = require('builder/data/user-model');
var ConfigModel = require('builder/data/config-model');
var FactoryModals = require('../../../../../../factories/modals');
var Backbone = require('backbone');
describe('components/form-components/editors/fill/input-color/assets-picker/input-asset-picker-view', function () {
beforeEach(function () {
this.userModel = new UserModel({
username: 'pepe'
}, {
configModel: 'c'
});
this.configModel = new ConfigModel({
base_url: '/u/pepe'
});
this.model = new Backbone.Model({
ramp: [{
color: '#FABADA',
title: 'hola',
image: 'http://www.image.com/image.jpg'
}]
});
this.view = new InputAssetPickerView({
index: 0,
ramp: [{
color: '#FABADA',
title: 'hola',
image: 'http://www.image.com/image.jpg'
}],
userModel: this.userModel,
configModel: this.configModel,
modals: FactoryModals.createModalService()
});
this.view.render();
});
describe('render', function () {
it('should render _headerView', function () {
expect(this.view._headerView).toBeDefined();
});
it('should render _assetPicker', function () {
expect(this.view._assetPicker).toBeDefined();
});
});
describe('._getRampItem', function () {
it('should return ramp item element', function () {
var item = this.view._getRampItem();
expect(item.color).toBe('#FABADA');
});
});
describe('._onChangeImage', function () {
it('should trigger change:image on view and model', function () {
this.view._onChangeImage({ url: 'new_image' });
expect(this.view.options.ramp[0].image).toBe('new_image');
expect(this.view.model.get('ramp')[0].image).toBe('new_image');
});
});
describe('._onClickBack', function () {
it('should trigger back function', function () {
var isBack;
this.view._headerView.bind('back', function () {
isBack = true;
}, this);
this.view._headerView.$('.js-back').click();
expect(isBack).toBeTruthy();
});
});
describe('._onGoToColorPicker', function () {
it('should trigger goToColorPicker function', function () {
var isInColorPicker;
this.view._headerView.bind('goToColorPicker', function () {
isInColorPicker = true;
}, this);
this.view._headerView.$('.js-colorPicker').click();
expect(isInColorPicker).toBeTruthy();
});
});
it('should not have leaks', function () {
expect(this.view).toHaveNoLeaks();
});
afterEach(function () {
this.view.clean();
});
});
@@ -0,0 +1,82 @@
var $ = require('jquery');
var Backbone = require('backbone');
var ConfigModel = require('builder/data/config-model');
var UserModel = require('builder/data/user-model');
var AssetsCollection = require('builder/data/assets-collection');
var OrganizationAssetsCollection = require('builder/data/organization-assets-collection');
var OrganizationAssetsListView = require('builder/components/input-color/assets-picker/organization-assets-list-view');
describe('components/form-components/editors/fill/input-color/assets-picker/organization-assets-list-view', function () {
beforeEach(function () {
this.model = new Backbone.Model({
image: '/image.png'
});
this.selectedAsset = new Backbone.Model();
var configModel = new ConfigModel({
base_url: '/u/pepe'
});
var userModel = new UserModel({}, {
configModel: configModel
});
this._userAssetCollection = new AssetsCollection([{
item: 1, state: ''
}, {
item: 2, state: ''
}, {
item: 3, state: ''
}], {
configModel: configModel,
userModel: userModel
});
this._organizationAssetCollection = new OrganizationAssetsCollection([{
item: 1, state: ''
}, {
item: 2, state: ''
}, {
item: 3, state: ''
}], {
configModel: configModel,
orgId: userModel
});
this.view = new OrganizationAssetsListView({
title: 'Title',
model: this.model,
userAssetCollection: this._userAssetCollection,
organizationAssetCollection: this._organizationAssetCollection,
selectedAsset: this.selectedAsset,
userModel: userModel
});
this.view.render();
});
it('should render the assets', function () {
expect(this.view.$el.find('.js-asset').length).toBe(this._userAssetCollection.size());
});
it('should select an asset and deselect all the user assets', function () {
this._userAssetCollection.at(0).set('state', 'selected');
expect(this._organizationAssetCollection.where({ state: 'selected' }).length).toBe(0);
expect(this._organizationAssetCollection.at(0).get('state')).toBe('');
expect(this._userAssetCollection.where({ state: 'selected' }).length).toBe(1);
expect(this._userAssetCollection.at(0).get('state')).toBe('selected');
$(this.view.$('.js-asset')[0]).click();
expect(this.view.$('.is-selected').length).toBe(1);
expect(this._organizationAssetCollection.where({ state: 'selected' }).length).toBe(1);
expect(this._organizationAssetCollection.at(0).get('state')).toBe('selected');
expect(this._userAssetCollection.where({ state: 'selected' }).length).toBe(0);
expect(this._userAssetCollection.at(0).get('state')).toBe('');
});
afterEach(function () {
this.view.clean();
});
});
@@ -0,0 +1,48 @@
var Backbone = require('backbone');
var _ = require('underscore');
var View = require('builder/components/input-color/assets-picker/static-asset-item-view');
describe('components/form-components/editors/fill/input-color/asset-picker/static-asset-item-view', function () {
beforeEach(function () {
this.model = new Backbone.Model({
state: ''
});
this.view = new View({ model: this.model });
});
describe('initialize', function () {
it('should bind change:state that toggles selected', function () {
expect(_.indexOf(this.view.$el[0].classList, 'is-selected')).toBe(-1);
this.view.model.set('state', 'selected');
expect(_.indexOf(this.view.$el[0].classList, 'is-selected')).not.toBe(-1);
});
});
describe('._onClick', function () {
it('should kill event, trigger selected and change model state', function () {
var selectedTriggered = false;
var selectedPayload;
this.view.on('selected', function (payload) {
selectedTriggered = true;
selectedPayload = payload;
});
var event = 'an event';
spyOn(this.view, 'killEvent');
this.view._onClick(event);
expect(this.view.killEvent).toHaveBeenCalledWith(event);
expect(selectedTriggered).toBe(true);
expect(selectedPayload).toBe(this.model);
expect(this.view.model.get('state')).toBe('selected');
});
});
it('should not have leaks', function () {
expect(this.view).toHaveNoLeaks();
});
// render function is already tested in assets-list-view.spec.js render
});
@@ -0,0 +1,56 @@
var Backbone = require('backbone');
var ConfigModel = require('builder/data/config-model');
var UserModel = require('builder/data/user-model');
var UploadAssetsTab = require('builder/components/input-color/assets-picker/upload-assets-tab');
describe('components/form-components/editors/fill/input-color/assets-picker/upoad-assets-tab', function () {
beforeEach(function () {
var configModel = new ConfigModel({
base_url: '/u/pepe'
});
var userModel = new UserModel({}, {
configModel: configModel
});
this.view = new UploadAssetsTab({
model: new Backbone.Model(),
configModel: configModel,
userModel: userModel
});
this.view.render();
});
it('should render', function () {
expect(this.view.$el.text()).toContain('components.modals.assets-picker.upload-desc');
expect(this.view.$el.text()).toContain('components.modals.assets-picker.submit');
expect(this.view.$el.text()).toContain('components.modals.assets-picker.upload-file-url');
});
describe('._onClickSubmit', function () {
it('should trigger an event', function () {
var uploadURLEvent;
var uploadURLEventData;
this.view.bind('upload-url', function (data) {
uploadURLEvent = true;
uploadURLEventData = data;
}, this);
var url = 'http://carto.com/pizza.png';
this.view.$('.js-url').val(url);
this.view.$('.js-submit').click();
expect(uploadURLEvent).toBeTruthy();
expect(uploadURLEventData).toBe(url);
});
});
it('should not have leaks', function () {
expect(this.view).toHaveNoLeaks();
});
afterEach(function () {
this.view.clean();
});
});
@@ -0,0 +1,189 @@
var $ = require('jquery');
var Backbone = require('backbone');
var UserAssetsListView = require('builder/components/input-color/assets-picker/user-assets-list-view');
var AssetsCollection = require('builder/data/assets-collection');
var ConfigModel = require('builder/data/config-model');
var UserModel = require('builder/data/user-model');
var OrganizationAssetsCollection = require('builder/data/organization-assets-collection');
var AssetModel = require('builder/data/asset-model');
describe('components/form-components/editors/fill/input-color/assets-picker/user-assets-list-view', function () {
beforeEach(function () {
this.model = new Backbone.Model({
image: '/image.png'
});
this.selectedAsset = new Backbone.Model();
this.configModel = new ConfigModel({
base_url: '/u/pepe'
});
this.userModel = new UserModel({}, {
configModel: this.configModel
});
var asset1 = new AssetModel({
item: 1, state: '', public_url: 'one.jpg'
});
var asset2 = new AssetModel({
item: 2, state: '', public_url: 'two.png'
});
var asset3 = new AssetModel({
item: 3, state: '', public_url: 'three.gif'
});
this._userAssetCollection = new AssetsCollection([asset1, asset2, asset3], {
configModel: this.configModel,
userModel: this.userModel
});
this.view = new UserAssetsListView({
title: 'Title',
model: this.model,
userAssetCollection: this._userAssetCollection,
selectedAsset: this.selectedAsset,
userModel: this.userModel
});
this.view.render();
});
it('should render the assets', function () {
expect(this.view.$el.find('.js-asset').length).toBe(this._userAssetCollection.size() + 1);
});
it('should render the add button', function () {
expect(this.view.$el.find('.AssetsList-item--text .js-asset').text().trim()).toBe('+');
expect(this.view.$el.find('.AssetsList-item--text .js-asset').length).toBe(1);
});
it('should trigger an upload event when clicking the add button', function () {
var triggered = false;
this.view.bind('init-upload', function () {
triggered = true;
}, this);
this.view.$el.find('.AssetsList-item--text .js-asset').click();
expect(triggered).toBeTruthy();
});
it('should select an asset', function () {
this._userAssetCollection.at(0).set('state', '');
this._userAssetCollection.at(1).set('state', '');
this._userAssetCollection.at(2).set('state', '');
expect(this._userAssetCollection.where({ state: 'selected' }).length).toBe(0);
$(this.view.$('.js-asset')[1]).click();
expect(this.view.$('.is-selected').length).toBe(1);
expect(this._userAssetCollection.where({ state: 'selected' }).length).toBe(1);
expect(this._userAssetCollection.at(0).get('state')).toBe('selected');
});
it('should select all the assets', function () {
this._userAssetCollection.at(0).set('state', 'selected');
this.view.$('.js-select-all').click();
expect(this.view.$('.is-selected').length).toBe(3);
expect(this._userAssetCollection.at(0).get('state')).toBe('selected');
expect(this._userAssetCollection.at(1).get('state')).toBe('selected');
expect(this._userAssetCollection.at(2).get('state')).toBe('selected');
});
it('should deselect all the assets', function () {
this._userAssetCollection.at(0).set('state', 'selected');
this._userAssetCollection.at(1).set('state', 'selected');
this._userAssetCollection.at(2).set('state', 'selected');
this.view.$('.js-deselect-all').click();
expect(this._userAssetCollection.at(0).get('state')).toBe('');
expect(this._userAssetCollection.at(1).get('state')).toBe('');
expect(this._userAssetCollection.at(2).get('state')).toBe('');
expect(this.view.$('.is-selected').length).toBe(0);
});
describe('when user is inside organization', function () {
var view;
beforeEach(function () {
spyOn(this.userModel, 'isInsideOrg').and.returnValue(true);
this._organizationAssetCollection = new OrganizationAssetsCollection([{
item: 1, state: ''
}, {
item: 2, state: ''
}, {
item: 3, state: ''
}], {
configModel: this.configModel,
orgId: this.userModel
});
view = new UserAssetsListView({
title: 'Title',
model: this.model,
userAssetCollection: this._userAssetCollection,
organizationAssetCollection: this._organizationAssetCollection,
selectedAsset: this.selectedAsset,
userModel: this.userModel
});
view.render();
});
it('should select an asset and deselect all the organization assets', function () {
this._organizationAssetCollection.at(0).set('state', 'selected');
expect(this._userAssetCollection.where({ state: 'selected' }).length).toBe(0);
expect(this._userAssetCollection.at(0).get('state')).toBe('');
expect(this._organizationAssetCollection.where({ state: 'selected' }).length).toBe(1);
expect(this._organizationAssetCollection.at(0).get('state')).toBe('selected');
$(view.$('.js-asset')[1]).click();
expect(this.view.$('.is-selected').length).toBe(1);
expect(this._userAssetCollection.where({ state: 'selected' }).length).toBe(1);
expect(this._userAssetCollection.at(0).get('state')).toBe('selected');
expect(this._organizationAssetCollection.where({ state: 'selected' }).length).toBe(0);
expect(this._organizationAssetCollection.at(0).get('state')).toBe('');
});
});
it('should remove selected assets', function () {
this._userAssetCollection.at(0).set('state', 'selected');
this._userAssetCollection.at(1).set('state', 'selected');
this._userAssetCollection.at(2).set('state', '');
this.view.$('.js-remove').click();
expect(this._userAssetCollection.size()).toBe(1);
});
it('should unset the selected asset', function () {
var self = this;
AssetModel.prototype.destroy = function () {
self.view._onDestroyFinished({ status: 200 });
};
this._userAssetCollection.at(0).set('state', 'selected');
this._userAssetCollection.at(1).set('state', '');
this._userAssetCollection.at(2).set('state', '');
expect(this.selectedAsset.get('url')).toBe('one.jpg');
expect(this.selectedAsset.get('kind')).toBe('custom-marker');
this.view.$('.js-remove').click();
expect(this.selectedAsset.get('url')).toBe(undefined);
expect(this.selectedAsset.get('kind')).toBe(undefined);
});
it('should not have leaks', function () {
expect(this.view).toHaveNoLeaks();
});
afterEach(function () {
this.view.clean();
});
});
@@ -0,0 +1,70 @@
var _ = require('underscore');
var Backbone = require('backbone');
var InputColorDialogContent = require('builder/components/input-color/input-color-dialog-content');
var FactoryModals = require('../../../../../factories/modals');
describe('components/form-components/editors/fill/input-color/input-color-dialog-content', function () {
beforeEach(function () {
this.model = new Backbone.Model({
bins: 5,
range: ['#FFF', '#FABADA', '#00FF00', '#000', '#999999'],
attribute: 'column1',
quantification: 'jenks',
opacity: 0.5
});
this.view = new InputColorDialogContent(({
configModel: {},
userModel: {
featureEnabled: function () { return true; }
},
modals: FactoryModals.createModalService(),
query: 'SELECT * from table',
columns: [
{ label: 'column1', type: 'number' },
{ label: 'column2', type: 'number' },
{ label: 'column3', type: 'number' }
],
model: this.model,
editorAttrs: {}
}));
this.view.render();
});
it('should render', function () {
expect(_.size(this.view._subviews)).toBe(1);
});
it('should generate two panes', function () {
expect(this.view.$el.html()).toContain('form-components.editors.fill.input-color.solid');
expect(this.view.$el.html()).toContain('form-components.editors.fill.input-color.value');
});
it('should populate hideTabs attribute if it is received as option', function () {
var view = new InputColorDialogContent(({
configModel: {},
userModel: {
featureEnabled: function () { return true; }
},
modals: FactoryModals.createModalService(),
query: 'SELECT * from table',
columns: [
{ label: 'column1', type: 'number' },
{ label: 'column2', type: 'number' },
{ label: 'column3', type: 'number' }
],
model: this.model,
editorAttrs: {
hideTabs: ['quantification']
}
}));
expect(view._hideTabs).toEqual(['quantification']);
});
it('should not have leaks', function () {
expect(this.view).toHaveNoLeaks();
});
afterEach(function () {
this.view.remove();
});
});
@@ -0,0 +1,47 @@
var Backbone = require('backbone');
var ConfigModel = require('builder/data/config-model');
var InputColorFileView = require('builder/components/input-color/input-color-file-view');
var utils = require('builder/helpers/utils');
var MakiIcons = require('builder/components/input-color/assets/maki-icons');
var FactoryModals = require('../../../../../factories/modals');
describe('components/form-components/editors/fill/input-color/input-color-file-view', function () {
beforeEach(function () {
this.model = new Backbone.Model({
image: 'http://www.domain.com/image.png',
fixed: '#ff0000',
index: 0,
ramp: [{
color: '#c0ffee',
title: 'hola',
image: 'http://www.image.com/image.jpg'
}]
});
this._configModel = new ConfigModel({ base_url: '/u/pepe' });
this.view = new InputColorFileView(({
model: this.model,
userModel: {
featureEnabled: function () { return true; }
},
configModel: this._configModel,
modals: FactoryModals.createModalService()
}));
this.view.render();
});
it('should render properly', function () {
expect(this.view.$el.html()).toContain('form-components.editors.fill.image.recently-title');
expect(this.view.$el.find('.js-asset').length).toBe(MakiIcons.icons.length + 1); // None + icons
expect(utils.endsWith(this.view.$('img').attr('src'), '?req=markup')).toBe(true);
});
it('should not have leaks', function () {
expect(this.view).toHaveNoLeaks();
});
afterEach(function () {
this.view.remove();
});
});
@@ -0,0 +1,111 @@
var $ = require('jquery');
var _ = require('underscore');
var Backbone = require('backbone');
var ConfigModel = require('builder/data/config-model');
var InputColorFixedContentView = require('builder/components/input-color/input-color-fixed-content-view');
var FactoryModals = require('../../../../../factories/modals');
describe('components/form-components/editors/fill/input-color/input-color-fixed-content-view', function () {
beforeEach(function () {
spyOn($, 'ajax').and.callFake(function (req) {
var container = document.createElement('div');
var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
svg.setAttribute('width', '200');
svg.setAttribute('height', '200');
svg.setAttribute('version', '1.1');
svg.setAttribute('id', 'mysvg');
container.appendChild(svg);
var d = $.Deferred();
d.resolve(container);
return d.promise();
});
this._configModel = new ConfigModel({ base_url: '/u/pepe' });
this.model = new Backbone.Model({
image: '',
fixed: '#ff0000',
opacity: 1
});
});
describe('with image enabled', function () {
beforeEach(function () {
spyOn(InputColorFixedContentView.prototype, '_updateImageTabPane').and.callThrough();
spyOn(InputColorFixedContentView.prototype, '_updateTextTabPane').and.callThrough();
this.view = new InputColorFixedContentView({
model: this.model,
editorAttrs: {
imageEnabled: true,
hidePanes: ['value']
},
userModel: {
featureEnabled: function () { return true; }
},
configModel: this._configModel,
modals: FactoryModals.createModalService()
});
this.view.render();
});
it('should render properly', function () {
expect(_.size(this.view._subviews)).toBe(1);
expect(this.view.$el.find('.CDB-NavMenu-item').length).toBe(2);
expect(this.view._tabPaneView).toBeDefined();
});
it('should update color', function () {
expect(this.view.$('.Editor-boxModalHeader').html()).toContain('#ff0000');
this.model.set('fixed', '#fabada');
expect(InputColorFixedContentView.prototype._updateTextTabPane).toHaveBeenCalled();
expect(InputColorFixedContentView.prototype._updateImageTabPane).toHaveBeenCalled();
expect(this.view.$('.Editor-boxModalHeader').html()).toContain('#fabada');
});
it('should update image', function () {
expect(this.view.$('.Editor-boxModalHeader').text()).toContain('form-components.editors.fill.input-color.img');
this.model.set('image', 'http://image.io/image1.svg');
expect(InputColorFixedContentView.prototype._updateTextTabPane).not.toHaveBeenCalled();
expect(InputColorFixedContentView.prototype._updateImageTabPane).toHaveBeenCalled();
expect(this.view.$('.Editor-boxModalHeader').html()).toContain('<div class="Tab-paneLabelImageContainer js-image-container">');
});
it('should not have leaks', function () {
expect(this.view).toHaveNoLeaks();
});
afterEach(function () {
this.view.remove();
});
});
describe('without image enabled', function () {
beforeEach(function () {
this.view = new InputColorFixedContentView({
model: this.model,
editorAttrs: {
hidePanes: ['value']
}
});
this.view.render();
});
it('should render properly', function () {
expect(_.size(this.view._subviews)).toBe(0);
expect(this.view.$el.find('.CDB-NavMenu-item').length).toBe(0);
expect(this.view._tabPaneView).not.toBeDefined();
});
it('should not have leaks', function () {
expect(this.view).toHaveNoLeaks();
});
afterEach(function () {
this.view.remove();
});
});
});
@@ -0,0 +1,61 @@
var InputColorPickerView = require('builder/components/input-color/input-color-picker/input-color-picker-view');
describe('components/form-components/editors/fill/input-color/input-color-picker/input-color-picker-view', function () {
beforeEach(function () {
this.view = new InputColorPickerView({ ramp: [ 303 ], opacity: 0.81 });
});
afterEach(function () {
this.view.remove();
});
describe('initialization', function () {
it('should throw Error if no ramp provided', function () {
var wrapper = function () {
new InputColorPickerView({}); // eslint-disable-line no-new
};
expect(wrapper).toThrowError('ramp is required');
});
it('should throw Error if no opacity provided', function () {
var wrapper = function () {
new InputColorPickerView({ ramp: [] }); // eslint-disable-line no-new
};
expect(wrapper).toThrowError('opacity is required');
});
it('should create proper model and bindings', function () {
var view = new InputColorPickerView({ ramp: [ 303 ], opacity: 0.81 });
expect(view.model.get('ramp')).toEqual([ 303 ]);
expect(view.model.get('opacity')).toEqual(0.81);
});
it('should have bindings for changes in model', function () {
var view = new InputColorPickerView({ ramp: [ 303 ], opacity: 0.81 });
expect(view.model._events['change:index'][0].callback).toEqual(jasmine.anything());
expect(view.model._events['change:opacity'][0].callback).toEqual(jasmine.anything());
});
});
describe('._onOpacityChanged', function () {
it('should trigger change:opacity when opacity changes', function () {
var view = new InputColorPickerView({ ramp: [ 303 ], opacity: 0.81 });
var opacity = 0;
function onOpacityChanged (value) {
opacity = value;
}
view.bind('change:opacity', onOpacityChanged);
view.model.set('opacity', 0.5);
expect(opacity).toBe(0.5);
});
});
it('should not have leaks', function () {
expect(this.view).toHaveNoLeaks();
});
});
@@ -0,0 +1,156 @@
var Backbone = require('backbone');
var InputColorPickerHeader = require('builder/components/input-color/input-color-picker/input-color-picker-header');
describe('components/form-components/editors/fill/input-color/input-color-picker/input-color-picker-header', function () {
beforeEach(function () {
this.model = new Backbone.Model({
ramp: [{
val: '#c0ffee',
color: '#c0ffee'
}, {
val: '#bada55',
color: '#bada55'
}, {
val: '#decade',
color: '#decade'
}],
opacity: 0.45,
index: 0
});
this.view = new InputColorPickerHeader({ model: this.model });
});
describe('events', function () {
it('should be properly hooked up', function () {
expect(this.view.events['click .js-color']).toEqual('_onClickColor');
expect(this.view.events['keyup .js-a']).toEqual('_onChangeOpacity');
});
});
describe('render', function () {
it('should create slider and opacity input with proper values', function () {
this.view.render();
var $slider = this.view.$('.js-slider');
var expectedOpacity = this.model.get('opacity');
expect(+this.view.$('.js-a').val()).toBe(expectedOpacity);
expect($slider.slider('instance')).toEqual(jasmine.anything());
expect($slider.slider('option', 'max')).toBe(1);
expect($slider.slider('option', 'min')).toBe(0);
expect($slider.slider('option', 'step')).toBe(0.02);
expect($slider.slider('option', 'orientation')).toEqual('horizontal');
expect($slider.slider('option', 'disabled')).toBe(false);
expect($slider.slider('option', 'range')).toEqual('min');
expect($slider.slider('option', 'value')).toEqual(this.view._inverseSliderValue(expectedOpacity));
expect($slider.slider('option', 'slide')).toEqual(jasmine.anything());
});
it('should call _reRenderOpacity and not render anything else if opacity changes', function () {
spyOn(this.view, '_reRenderOpacity');
spyOn(this.view, 'clearSubViews');
this.view.render({
changed: {
opacity: true
}
});
expect(this.view._reRenderOpacity).toHaveBeenCalled();
expect(this.view.clearSubViews).not.toHaveBeenCalled();
});
});
describe('._onSlideChange', function () {
it('should set model opacity inverting the value', function () {
var opacity = 0.23;
var expectedOpacity = this.view._inverseSliderValue(opacity);
this.view._onSlideChange(null, { value: opacity });
expect(this.view.model.get('opacity')).toBe(expectedOpacity);
});
});
describe('._inverseSliderValue', function () {
it('should inverse the provided value', function () {
expect(this.view._inverseSliderValue(0)).toBe(1);
expect(this.view._inverseSliderValue(1)).toBe(0);
expect(this.view._inverseSliderValue(0.4)).toBe(0.6);
expect(this.view._inverseSliderValue(0.2345)).toBe(0.77);
});
});
describe('._onChangeOpacity', function () {
var selector = '.js-a';
var errorClass = 'has-error';
beforeEach(function () {
this.view.render();
});
it('should change model opacity and have no error if opacity is valid', function () {
var opacity = 0.31;
this.view.$(selector).val(opacity);
this.view._onChangeOpacity();
expect(this.view.$(selector).hasClass(errorClass)).toBe(false);
expect(this.view.model.get('opacity')).toBe(opacity);
});
it('should not change model opacity and have error if opacity is no valid', function () {
var opacity = 'hip';
this.view.$(selector).val(opacity);
this.view._onChangeOpacity();
expect(this.view.$(selector).hasClass(errorClass)).toBe(true);
expect(this.view.model.get('opacity')).toBe(0.45); // the original opacity
});
});
describe('._isValidOpacity', function () {
it('should return if the opacity input is valid', function () {
expect(this.view._isValidOpacity('0')).toBe(true);
expect(this.view._isValidOpacity('0.1')).toBe(true);
expect(this.view._isValidOpacity('0.234')).toBe(true);
expect(this.view._isValidOpacity('1')).toBe(true);
expect(this.view._isValidOpacity('0.')).toBe(false);
expect(this.view._isValidOpacity('.34')).toBe(false);
expect(this.view._isValidOpacity('1.1')).toBe(false);
expect(this.view._isValidOpacity('')).toBe(false);
expect(this.view._isValidOpacity('-0.4')).toBe(false);
expect(this.view._isValidOpacity('hello')).toBe(false);
expect(this.view._isValidOpacity('0.f')).toBe(false);
});
});
describe('._reRenderOpacity', function () {
beforeEach(function () {
this.view.render();
});
it('should update input when opacity changes', function () {
this.view.$('.js-a').val(0.75);
this.view.model.set('opacity', 0.69);
expect(+this.view.$('.js-a').val()).toBe(0.69);
});
it('should update slider value when opacity changes', function () {
this.view.$('.js-slider').slider('value', 0.75);
this.view.model.set('opacity', 0.68);
expect(this.view.$('.js-slider').slider('value')).toBe(this.view._inverseSliderValue(0.68));
});
});
it('should not have leaks', function () {
expect(this.view).toHaveNoLeaks();
});
afterEach(function () {
this.view.remove();
});
});
@@ -0,0 +1,60 @@
var CustomListItemModel = require('builder/components/custom-list/custom-list-item-model');
var CategoriesListItemView = require('builder/components/input-color/input-qualitative-ramps/categories-list/list-item-view/categories-list-item-view');
var inputColorCategoriesListItemTemplate = require('builder/components/input-color/input-qualitative-ramps/categories-list/list-item-view/categories-list-item.tpl');
describe('components/form-components/editors/fill/input-color/input-qualitative-ramps/categories-list/list-item-view/categories-list-item-view', function () {
beforeEach(function () {
this.model = new CustomListItemModel({
label: 'hello',
val: '#FFF',
image: 'https://s3.amazonaws.com/com.cartodb.users-assets.production/maki-icons/star-stroked-18.svg'
});
this.view = new CategoriesListItemView(({
model: this.model,
typeLabel: 'column',
template: inputColorCategoriesListItemTemplate,
imageEnabled: true
}));
spyOn(this.view, '_loadImages');
this.view.render();
});
it('should render properly', function () {
expect(this.view.$('.CDB-Text').length).toBe(1);
expect(this.view.$('.CDB-Text').attr('title')).toBe('hello');
expect(this.view.$('.js-colorPicker').attr('style')).toBe('background-color: #FFF;');
expect(this.view.$('.js-image-container').length).toBe(1);
});
describe('_onClick', function () {
it('should set js-assetPicker class in model when image is clicked', function () {
this.view.$('.js-image-container').click();
expect(this.model.get('selectedClass')).toEqual(['js-assetPicker']);
});
it('should set js-assetPicker class in model when IMG label is clicked', function () {
this.model.unset('image');
this.view.render();
this.view.$('.js-assetPicker').click();
expect(this.model.get('selectedClass')).toEqual(['js-assetPicker']);
});
it('should not set js-assetPicker class in model when rest of the item is clicked', function () {
this.model.unset('image');
this.view.render();
this.view.$el.click();
expect(this.model.get('selectedClass')).toEqual([]);
});
});
it('should not have leaks', function () {
expect(this.view).toHaveNoLeaks();
});
afterEach(function () {
this.view.remove();
});
});
@@ -0,0 +1,296 @@
var Backbone = require('backbone');
var CategoriesListView = require('builder/components/input-color/input-qualitative-ramps/categories-list/list-view/input-categories-list-view');
describe('components/form-components/editors/fill/input-color/input-qualitative-ramps/categories-list/list-view/input-categories-list-view', function () {
var view, model;
var range = ['#000000', '#1D6996'];
var rangeInRGB = ['rgb(0, 0, 0)', 'rgb(29, 105, 150)'];
describe('when the attribute is boolean', function () {
beforeEach(function () {
model = new Backbone.Model({
type: 'color',
attribute: 'fake_boolean_attribute',
attribute_type: 'boolean',
images: ['', ''],
range: range,
domain: [true, false],
selected: true
});
view = new CategoriesListView({
maxValues: 10,
model: model,
imageEnabled: false
});
view.render();
});
describe('.render', function () {
it('should have a back button', function () {
expect(view.$('.js-back')).toBeDefined();
});
it('should back button should have the "Color schemes" label', function () {
expect(view.$('.label').text().trim()).toEqual('Color Schemes');
});
it('should be properly rendered', function () {
// Different browsers may return CSS color values that are logically
// but not textually equal, e.g., #FFF, #ffffff, and rgb(255,255,255)
// http://api.jquery.com/css/
expect(view.$('.js-color:eq(0)').css('background-color')).toEqual(rangeInRGB[0]);
expect(view.$('.js-color:eq(1)').css('background-color')).toEqual(rangeInRGB[1]);
expect(view.$('.js-color:eq(2)').css('background-color')).toEqual(undefined);
});
it('should be properly rendered when there are null values', function () {
var colorRange = ['#5F4690', '#1D6996', '#FFFFFF'];
var colorRangeInRGB = ['rgb(95, 70, 144)', 'rgb(29, 105, 150)', 'rgb(255, 255, 255)'];
var model = new Backbone.Model({
type: 'color',
attribute: 'fake_boolean_attribute',
attribute_type: 'boolean',
images: ['', ''],
range: colorRange,
domain: [true, false, null],
selected: true
});
var view = new CategoriesListView({
maxValues: 10,
model: model,
imageEnabled: false
});
view.render();
expect(view.$('.js-color:eq(0)').css('background-color')).toEqual(colorRangeInRGB[0]);
expect(view.$('.js-color:eq(1)').css('background-color')).toEqual(colorRangeInRGB[1]);
expect(view.$('.js-color:eq(2)').css('background-color')).toEqual(colorRangeInRGB[2]);
view.remove();
});
});
afterEach(function () {
view.remove();
});
});
describe('when the attribute is numeric', function () {
beforeEach(function () {
model = new Backbone.Model({
type: 'color',
attribute: 'fake_numeric_attribute',
attribute_type: 'numeric',
images: ['', ''],
range: range,
domain: [1, 2],
selected: true
});
view = new CategoriesListView({
maxValues: 10,
model: model,
imageEnabled: false
});
view.render();
});
describe('.render', function () {
it('should have a back button', function () {
expect(view.$('.js-back')).toBeDefined();
});
it('should back button should have the "Color schemes" label', function () {
expect(view.$('.label').text().trim()).toEqual('Color Schemes');
});
it('should be properly rendered', function () {
// Different browsers may return CSS color values that are logically
// but not textually equal, e.g., #FFF, #ffffff, and rgb(255,255,255)
// http://api.jquery.com/css/
expect(view.$('.js-color:eq(0)').css('background-color')).toEqual(rangeInRGB[0]);
expect(view.$('.js-color:eq(1)').css('background-color')).toEqual(rangeInRGB[1]);
expect(view.$('.js-color:eq(2)').css('background-color')).toEqual(undefined);
});
it('should be properly rendered when there are null values', function () {
var colorRange = ['#5F4690', '#1D6996', '#FFFFFF'];
var colorRangeInRGB = ['rgb(95, 70, 144)', 'rgb(29, 105, 150)', 'rgb(255, 255, 255)'];
var model = new Backbone.Model({
type: 'color',
attribute: 'fake_numeric_attribute',
attribute_type: 'numeric',
images: ['', ''],
range: colorRange,
domain: [1, 2, null],
selected: true
});
var view = new CategoriesListView({
maxValues: 10,
model: model,
imageEnabled: false
});
view.render();
expect(view.$('.js-color:eq(0)').css('background-color')).toEqual(colorRangeInRGB[0]);
expect(view.$('.js-color:eq(1)').css('background-color')).toEqual(colorRangeInRGB[1]);
expect(view.$('.js-color:eq(2)').css('background-color')).toEqual(colorRangeInRGB[2]);
view.remove();
});
});
afterEach(function () {
view.remove();
});
});
describe('when the attribute is string', function () {
beforeEach(function () {
model = new Backbone.Model({
type: 'color',
attribute: 'fake_string_attribute',
attribute_type: 'string',
images: ['', ''],
range: range,
domain: ['string_attribute_1', 'string_attribute_2'],
selected: true
});
view = new CategoriesListView({
maxValues: 10,
model: model,
imageEnabled: false
});
view.render();
});
describe('.render', function () {
it('should have a back button', function () {
expect(view.$('.js-back')).toBeDefined();
});
it('should back button should have the "Color schemes" label', function () {
expect(view.$('.label').text().trim()).toEqual('Color Schemes');
});
it('should be properly rendered', function () {
// Different browsers may return CSS color values that are logically
// but not textually equal, e.g., #FFF, #ffffff, and rgb(255,255,255)
// http://api.jquery.com/css/
expect(view.$('.js-color:eq(0)').css('background-color')).toEqual(rangeInRGB[0]);
expect(view.$('.js-color:eq(1)').css('background-color')).toEqual(rangeInRGB[1]);
expect(view.$('.js-color:eq(2)').css('background-color')).toEqual(undefined);
});
it('should be properly rendered when there are null values', function () {
var colorRange = ['#5F4690', '#1D6996', '#FFFFFF'];
var colorRangeInRGB = ['rgb(95, 70, 144)', 'rgb(29, 105, 150)', 'rgb(255, 255, 255)'];
var model = new Backbone.Model({
type: 'color',
attribute: 'fake_string_attribute',
attribute_type: 'date',
images: ['', ''],
range: colorRange,
domain: ['string_attribute_1', 'string_attribute_2', null],
selected: true
});
var view = new CategoriesListView({
maxValues: 10,
model: model,
imageEnabled: false
});
view.render();
expect(view.$('.js-color:eq(0)').css('background-color')).toEqual(colorRangeInRGB[0]);
expect(view.$('.js-color:eq(1)').css('background-color')).toEqual(colorRangeInRGB[1]);
expect(view.$('.js-color:eq(2)').css('background-color')).toEqual(colorRangeInRGB[2]);
view.remove();
});
});
afterEach(function () {
view.remove();
});
});
describe('when the attribute is a date', function () {
beforeEach(function () {
model = new Backbone.Model({
type: 'color',
attribute: 'fake_date_attribute',
attribute_type: 'date',
images: ['', ''],
range: range,
domain: ['2018-01-01T00:00:00+00:00', '2018-01-02T00:00:00+00:00'],
selected: true
});
view = new CategoriesListView({
maxValues: 10,
model: model,
imageEnabled: false
});
view.render();
});
describe('.render', function () {
it('should have a back button', function () {
expect(view.$('.js-back')).toBeDefined();
});
it('should back button should have the "Color schemes" label', function () {
expect(view.$('.label').text().trim()).toEqual('Color Schemes');
});
it('should be properly rendered', function () {
// Different browsers may return CSS color values that are logically
// but not textually equal, e.g., #FFF, #ffffff, and rgb(255,255,255)
// http://api.jquery.com/css/
expect(view.$('.js-color:eq(0)').css('background-color')).toEqual(rangeInRGB[0]);
expect(view.$('.js-color:eq(1)').css('background-color')).toEqual(rangeInRGB[1]);
expect(view.$('.js-color:eq(2)').css('background-color')).toEqual(undefined);
});
it('should be properly rendered when there are null values', function () {
var colorRange = ['#5F4690', '#1D6996', '#FFFFFF'];
var colorRangeInRGB = ['rgb(95, 70, 144)', 'rgb(29, 105, 150)', 'rgb(255, 255, 255)'];
var model = new Backbone.Model({
type: 'color',
attribute: 'fake_date_attribute',
attribute_type: 'date',
images: ['', ''],
range: colorRange,
domain: ['2018-01-01T00:00:00+00:00', '2018-01-02T00:00:00+00:00', null],
selected: true
});
var view = new CategoriesListView({
maxValues: 10,
model: model,
imageEnabled: false
});
view.render();
expect(view.$('.js-color:eq(0)').css('background-color')).toEqual(colorRangeInRGB[0]);
expect(view.$('.js-color:eq(1)').css('background-color')).toEqual(colorRangeInRGB[1]);
expect(view.$('.js-color:eq(2)').css('background-color')).toEqual(colorRangeInRGB[2]);
view.remove();
});
});
afterEach(function () {
view.remove();
});
});
});
@@ -0,0 +1,79 @@
var _ = require('underscore');
var Backbone = require('backbone');
var InputCategoriesRampsListItemView = require('builder/components/input-color/input-qualitative-ramps/color-ramps-list/list-item-view/color-ramps-list-item-view');
var InputCategoriesRampsListItemTemplate = require('builder/components/input-color/input-qualitative-ramps/color-ramps-list/list-item-view/color-ramps-list-item.tpl');
describe('components/form-components/editors/fill/input-color/input-qualitative-ramps/color-ramps-list/list-item-view/color-ramps-list-item-view', function () {
var view, model;
var colorRamp = ['#855C75', '#D9AF6B', '#AF6458', '#736F4C', '#526A83', '#625377', '#68855C', '#9C9C5E', '#A06177', '#8C785D', '#7C7C7C'];
var createViewFn = function (options) {
if (!options) options = {};
model = new Backbone.Model({
disabled: false,
selected: _.isUndefined(options.selected) ? true : options.selected
});
model.getName = function () {
return colorRamp;
};
model.getValue = function () {
return colorRamp;
};
var view = new InputCategoriesRampsListItemView({
model: model,
typeLabel: 'column',
template: InputCategoriesRampsListItemTemplate
});
return view;
};
beforeEach(function () {
view = createViewFn();
});
it('should have no leaks', function () {
expect(view).toHaveNoLeaks();
});
it('should render properly', function () {
view.render();
expect(view.$el.find('.js-listItemLink').hasClass('is-selected')).toBe(true);
expect(view.$el.find('.js-listItemLink').hasClass('is-disabled')).toBe(false);
expect(view.$el.find('.ColorBarContainer .ColorBar').length).toBe(colorRamp.length);
});
it('should add "is-highlighted" when mouse is over the view', function () {
view._onMouseEnter();
expect(view.$el.hasClass('is-highlighted')).toBe(true);
});
it('should add "is-highlighted" when mouse leaves the view', function () {
view._onMouseEnter();
expect(view.$el.hasClass('is-highlighted')).toBe(true);
view._onMouseLeave();
expect(view.$el.hasClass('is-highlighted')).toBe(false);
});
it('should trigger "customize" event if the view is clicked and is selected', function () {
spyOn(view, 'trigger');
view._onClick();
expect(view.trigger).toHaveBeenCalledWith('customEvent', 'customize', model.getValue(), view);
});
it('should select the element if clicked and it wasn\'t selected', function () {
var view = createViewFn({
selected: false
});
view._onClick();
expect(model.get('selected')).toBe(true);
});
});
@@ -0,0 +1,169 @@
var _ = require('underscore');
var Backbone = require('backbone');
var InputCategoriesRampsListView = require('builder/components/input-color/input-qualitative-ramps/color-ramps-list/list-view/color-ramps-list-view');
describe('components/form-components/editors/fill/input-color/input-qualitative-ramps/color-ramps-list/list-view/color-ramps-list-view', function () {
var view, model;
var ramp = ['#5F4690', '#1D6996', '#38A6A5', '#0F8554', '#73AF48', '#EDAD08', '#E17C05', '#CC503E', '#94346E', '#6F4070', '#666666'];
var createViewFn = function (options) {
if (!options) options = {};
model = new Backbone.Model({
type: 'color',
attribute: 'common_species',
attribute_type: 'string',
range: _.isUndefined(options.range) ? ramp : options.range,
images: ['', '', '', '', '', '', '', '', '', '', ''],
domain: ['Brisbane Box', 'Sycamore', 'New Zealand Xmas Tree', 'Swamp Myrtle', 'Hybrid Strawberry Tree', 'Laurel Fig', 'Victorian Box', 'Cherry Plum', 'Southern Magnolia', 'Brisbane Box'],
selected: true
});
var view = new InputCategoriesRampsListView({
model: model,
maxValues: 10,
requiredNumberOfColors: 10
});
return view;
};
beforeEach(function () {
view = createViewFn();
});
describe('.render', function () {
beforeEach(function () {
view.render();
});
it('should render properly', function () {
expect(view.$el.find('.js-rampsList').length).toBe(1);
expect(view.$el.find('.js-list').children().length).not.toBeLessThan(1);
});
it('should render the custom ramp if any', function () {
var customRamp = ['#5F4690', '#1D6996', '#38A6A5', '#0F8554', '#73AF48', '#EDAD08', '#E17C05', '#CC503E', '#94346E', '#6F4070', '#999999'];
view = createViewFn({
range: customRamp
});
view.render();
expect(view.$el.find('.js-customList').hasClass('is-customized')).toBe(true);
expect(view.$el.find('.js-customList .ColorBarContainer').children().length).toBe(customRamp.length);
});
});
describe('._selectRamp', function () {
it('should select a ramp', function () {
view.render();
view._selectRamp(new Backbone.Model({
val: ramp
}));
var rampDOMElement = view.$('.js-listItem[data-val="' + ramp.join(',') + '"] .js-listItemLink');
expect(rampDOMElement.hasClass('is-selected')).toBe(true);
});
});
describe('._onSelectItem', function () {
it('should set the selected ramp in the model and trigger an event', function () {
spyOn(view, 'trigger');
var item = new Backbone.Model({
val: ramp
});
view._onSelectItem(item);
expect(model.get('range')).toBe(ramp);
expect(view.trigger).toHaveBeenCalledWith('ramp-selected', ramp, view);
});
});
describe('._setupCollection', function () {
it('should setup the collection with the provided qualitative ramps', function () {
view = createViewFn();
view._setupCollection();
expect(view.collection.length).toBe(6);
});
it('should select mark the ramp as selected if is in the model', function () {
view = createViewFn({
range: ramp
});
view._setupCollection();
var selectedRamp = view.collection.find(function (model) {
return model.get('val').join() === ramp.join();
});
expect(selectedRamp.get('selected')).toBe(true);
});
it('should select the selected ramp as custom if is not inside the collection', function () {
var customRamp = ['#000000'];
view = createViewFn({
range: customRamp
});
expect(view._customRamp.get('range')).toBe(customRamp);
expect(view.collection.findWhere({ selected: true })).toBeUndefined();
});
});
describe('._onClickCustomize', function () {
beforeEach(function () {
view = createViewFn({
range: ramp
});
view._setupCollection();
});
it('should set the current selected ramp as custom', function () {
var selectedRamp = view.collection.findWhere({ selected: true });
view._onClickCustomize();
expect(view._customRamp.get('range')).toBe(selectedRamp);
});
it('should trigger a customize event', function () {
spyOn(view, 'trigger');
view._onClickCustomize();
expect(view.trigger).toHaveBeenCalled();
});
});
describe('._onClickClear', function () {
it('should clear customRamp range', function () {
var customRamp = ['#000000'];
view = createViewFn({
range: customRamp
});
expect(view._customRamp.get('range')).toBe(customRamp);
view._onClickClear();
expect(view._customRamp.get('range')).toBe(null);
});
it('should select the first ramp in the collection', function () {
view.collection.getSelectedItem().set('selected', false);
view._onClickClear();
expect(view.collection.at(0).get('selected')).toBe(true);
});
});
describe('._onClickCustomRamp', function () {
it('should change to customize view if custom ramp is applied', function () {
var customRamp = ['#999999', '#FFF000'];
view = createViewFn({
range: customRamp
});
spyOn(view, 'trigger');
view._onClickCustomRamp();
expect(view.trigger).toHaveBeenCalledWith('customize', view.collection.findWhere({ selected: true }), view);
});
});
});
@@ -0,0 +1,170 @@
var Backbone = require('backbone');
var InputColorCategories = require('builder/components/input-color/input-qualitative-ramps/main-view');
var ConfigModel = require('builder/data/config-model');
var UserModel = require('builder/data/user-model');
var FactoryModals = require('../../../../../../factories/modals');
var rampList = require('cartocolor');
var cdb = require('internal-carto.js');
describe('components/form-components/editors/fill/input-color/input-qualitative-ramps/main-view', function () {
beforeEach(function () {
this.configModel = new ConfigModel({
base_url: '/u/pepe',
user_name: 'pepe'
});
this.userModel = new UserModel({}, {
configModel: this.configModel,
feature_flags: []
});
this.model = new Backbone.Model({
domain: [0, '', 'Three'],
range: ['#E7E1EF', '#C994C7', '#DD1C77'],
images: ['', '', ''],
attribute: 'column1',
quantification: 'jenks'
});
this.modals = FactoryModals.createModalService();
spyOn(cdb.SQL.prototype, 'execute').and.callFake(function (query, vars, params) {
params && params.success();
});
this.view = new InputColorCategories(({
model: this.model,
userModel: this.userModel,
modals: this.modals,
query: 'SELECT * FROM table',
columns: [
{ label: 'column1', type: 'string' },
{ label: 'column2', type: 'string' },
{ label: 'column3', type: 'number' }
],
configModel: this.configModel
}));
this.view.render();
});
describe('.render', function () {
it('should have a back button', function () {
expect(this.view.$('.js-prevStep')).toBeDefined();
});
it('should display the attribute name in the header', function () {
expect(this.view.$('.js-label').text()).toEqual(this.model.get('attribute'));
});
it('should display color ranges with 4 colors', function () {
// 4 colors = 3 domain values colors + Others color
var fistRange = this.view.$('.ColorBarContainer')[0];
expect(fistRange.children.length).toEqual(4);
});
it('should display a button to select a custom color set', function () {
expect(this.view.$('.js-custom-color-set')).toBeDefined();
});
});
it('should not render quantification if hideTabs is defined and quantification is one of the items', function () {
this.view.render();
expect(this.view.$el.html()).toContain('js-quantification');
this.view._hideTabs = ['quantification'];
this.view.render();
expect(this.view.$el.html()).not.toContain('js-quantification');
this.view._hideTabs = [];
this.view.render();
expect(this.view.$el.html()).toContain('js-quantification');
});
it('should show the loader', function () {
// Not providing any response, we will let the loader be showed forever
cdb.SQL.prototype.execute.and.callFake(function (query, vars, params) { });
this.model.set('attribute', 'column2');
expect(this.view.$('.js-loader').length).toBe(1);
expect(this.view.$('.InputColorCategory-content.js-content').length).toBe(0);
});
describe('._createColorPickerView', function () {
it('should set picker view opacity to 1 when no opacity is provided', function () {
this.view.model.set('opacity', undefined);
var pickerView = this.view._createColorPickerView();
expect(pickerView.model.get('opacity')).toBe(1);
});
it('should set picker view opacity to the value provided', function () {
var opacity = 0.83;
this.view.model.set('opacity', opacity);
var pickerView = this.view._createColorPickerView();
expect(pickerView.model.get('opacity')).toBe(opacity);
});
it('should subscribe to picker view change of opacity', function () {
this.view.model.set('opacity', 0.83);
var pickerView = this.view._createColorPickerView();
pickerView.model.set('opacity', 0.69);
expect(this.view.model.get('opacity')).toBe(0.69);
});
it('should enable image edition if the item is not the latest', function () {
this.view._index = 0;
this.view.options.imageEnabled = true;
var pickerView = this.view._createColorPickerView();
expect(pickerView.options.imageEnabled).toBe(true);
});
it('should disable image edition if the item is the latest', function () {
var MAX_VALUES = 10; // Mirror the constant from input-color-categories.js
this.view._index = MAX_VALUES;
this.view.options.imageEnabled = true;
var pickerView = this.view._createColorPickerView();
expect(pickerView.options.imageEnabled).toBe(false);
});
});
describe('._createRangeListView', function () {
it('should not add the img selector to the latest item', function () {
this.view.options.imageEnabled = true;
var rangeListView = this.view._createRangeListView();
var list = rangeListView.render().$el.find('.CustomList-item');
expect(list.last().find('RampItem-img').length).toBe(0);
});
});
describe('._updateRangeAndDomain', function () {
var MAX_VALUES = 10; // Mirror the constant from input-color-categories.js
it('updates correctly the domain and range colors for the current categories', function () {
var rows = JSON.parse('[{"nombre":"Almagro"},{"nombre":"Arapiles"},{"nombre":"Cortes"},{"nombre":"Embajadores"},{"nombre":"Gaztambide"},{"nombre":"Jerónimos"},{"nombre":"Justicia"},{"nombre":"Palacio"},{"nombre":"RiosRosas"},{"nombre":"Sol"},{"nombre":"Trafalgar"}]');
this.view.model.set({ 'attribute': 'nombre' }, { silent: true });
this.view._updateRangeAndDomain(rows);
expect(this.view.model.get('domain').length).toBe(10);
expect(this.view.model.get('range')[MAX_VALUES]).toBe(rampList.Prism[MAX_VALUES + 1][MAX_VALUES + 1]);
});
});
it('should not have leaks', function () {
expect(this.view).toHaveNoLeaks();
});
afterEach(function () {
this.view.remove();
});
});
@@ -0,0 +1,112 @@
var Backbone = require('backbone');
var InputColorRamps = require('builder/components/input-color/input-quantitative-ramps/main-view');
describe('components/form-components/editors/fill/input-color/input-quantitative-ramps/main-view', function () {
describe('on model with a range', function () {
beforeEach(function () {
this.model = new Backbone.Model({
bins: 7,
range: ['#F1EEF6', '#D4B9DA', '#C994C7', '#DF65B0', '#E7298A', '#CE1256', '#91003F'],
attribute: 'column1',
quantification: 'jenks'
});
this.view = new InputColorRamps(({
model: this.model
}));
this.view.render();
});
it('should render properly', function () {
expect(this.view.$el.html()).toContain('column1');
expect(this.view.$el.html()).toContain('7 form-components.editors.fill.input-ramp.buckets');
expect(this.view.$el.html()).toContain('form-components.editors.fill.quantification.methods.jenks');
});
it('should pick a similar ramp when changing bins', function () {
this.model.set('bins', 5);
expect(this.model.get('range').join(',').toLowerCase()).toBe('#f1eef6,#d7b5d8,#df65b0,#dd1c77,#980043');
});
it('should refresh when the attribute is changed', function () {
this.model.set('attribute', 'column2');
expect(this.view.$el.html()).toContain('column2');
});
afterEach(function () {
this.view.remove();
});
});
describe('model without previous range', function () {
beforeEach(function () {
this.model = new Backbone.Model({
fixed: '#FF0000'
});
this.view = new InputColorRamps(({
model: this.model
}));
});
it('should initialize the model with default values', function () {
expect(this.model.get('quantification')).toBe('quantiles');
expect(this.model.get('bins')).toBe('5');
expect(this.model.get('fixed')).toBe(undefined);
});
it('should not have leaks', function () {
expect(this.view).toHaveNoLeaks();
});
afterEach(function () {
this.view.remove();
});
});
describe('model with previous bins', function () {
beforeEach(function () {
this.model = new Backbone.Model({
bins: 12
});
this.view = new InputColorRamps(({
model: this.model
}));
});
it('should set a default number of bins based on the current ramp list', function () {
expect(this.model.get('bins')).toBe('7');
});
afterEach(function () {
this.view.remove();
});
});
describe('model without valid range', function () {
beforeEach(function () {
this.model = new Backbone.Model({
range: ['#F1EEF6']
});
this.view = new InputColorRamps(({
model: this.model
}));
});
it('should set a default ramp list', function () {
expect(this.model.get('bins')).toBe('5');
expect(this.model.get('range').length).toBe(5);
});
it('should not have leaks', function () {
expect(this.view).toHaveNoLeaks();
});
afterEach(function () {
this.view.remove();
});
});
});
@@ -0,0 +1,46 @@
var Backbone = require('backbone');
var InputRampContentView = require('builder/components/input-color/input-quantitative-ramps/input-ramp-content-view');
describe('components/form-components/editors/fill/input-color/input-quantitative-ramps/input-ramp-content-view', function () {
function createView (opacity) {
this.model = new Backbone.Model({
range: ['#c0ffee', '#bada55', '#decade'],
opacity: opacity
});
return new InputRampContentView({ model: this.model });
}
describe('._createColorPickerView', function () {
it('should return picker view with default opacity if no one is provided', function () {
var view = createView();
var pickerView = view._createColorPickerView();
expect(pickerView.model.get('opacity')).toEqual(1);
view.remove();
});
it('should return picker view with the provided opacity', function () {
var view = createView(0.43);
var pickerView = view._createColorPickerView();
expect(pickerView.model.get('opacity')).toEqual(0.43);
view.remove();
});
it('should update own opacity when picker view updates its', function () {
var view = createView(0.43);
var pickerView = view._createColorPickerView();
pickerView.model.set('opacity', 0.84);
expect(view.model.get('opacity')).toEqual(0.84);
view.remove();
});
it('should not have leaks', function () {
var view = createView(0.43);
expect(view).toHaveNoLeaks();
view.remove();
});
});
});
@@ -0,0 +1,138 @@
var _ = require('underscore');
var Backbone = require('backbone');
var InputRampListView = require('builder/components/input-color/input-quantitative-ramps/input-ramp-list-view');
var rampList = require('cartocolor');
describe('components/form-components/editors/fill/input-color/input-quantitative-ramps/input-ramp-list-view', function () {
describe('with a default ramp', function () {
beforeEach(function () {
this.model = new Backbone.Model({
bins: 7,
range: ['#f6d2a9', '#f5b78e', '#f19c7c', '#ea8171', '#dd686c', '#ca5268', '#b13f64'],
attribute: 'column1',
quantification: 'jenks'
});
this.view = new InputRampListView(({
model: this.model
}));
this.view.render();
});
it('should render properly', function () {
expect(this.view.$('.js-listItem').length).toBe(_.toArray(rampList).length);
expect(this.view.$('.js-customList').text()).toContain('form-components.editors.fill.customize');
});
it('should select ramp on click', function () {
this.view.$('.js-listItem:eq(2) .js-listItemLink').click();
var selectedRamp = _.toArray(rampList)[2];
var ramp = selectedRamp[7];
var tags = selectedRamp.tags;
expect(tags).toContain('quantitative');
expect(this.model.get('range').join(',').toLowerCase()).toBe('#f6d2a9,#f5b78e,#f19c7c,#ea8171,#dd686c,#ca5268,#b13f64');
expect(this.view.$('.js-listItem:eq(2)').data('val')).toContain(ramp.join(','));
expect(this.view.$('.js-listItem.is-selected').length).toBe(1);
});
it('should invert the ramp', function () {
expect(this.view.collection.at(2).get('val').join(',').toLowerCase()).toBe('#f6d2a9,#f5b78e,#f19c7c,#ea8171,#dd686c,#ca5268,#b13f64');
this.view.$('.js-listItem:eq(2) .js-listItemLink').click();
this.view.$('.js-listItem:eq(2) .js-invert').click();
var firstRamp = _.toArray(rampList)[1];
var selectedRamp = _.toArray(rampList)[2];
var thirdRamp = _.toArray(rampList)[3];
var ramp = selectedRamp[7];
var tags = selectedRamp.tags;
expect(tags).toContain('quantitative');
expect(this.model.get('range').join(',').toLowerCase()).toBe('#b13f64,#ca5268,#dd686c,#ea8171,#f19c7c,#f5b78e,#f6d2a9');
expect(this.view.collection.at(2).get('val').join(',').toLowerCase()).toBe('#b13f64,#ca5268,#dd686c,#ea8171,#f19c7c,#f5b78e,#f6d2a9');
expect(this.view.$('.js-listItem:eq(1)').data('val')).toContain(firstRamp[7].join(','));
expect(this.view.$('.js-listItem:eq(2)').data('val')).toContain(ramp.reverse().join(','));
expect(this.view.$('.js-listItem:eq(3)').data('val')).toContain(thirdRamp[7].join(','));
expect(this.view.$('.js-listItem.is-selected').length).toBe(1);
expect(this.view.$('.js-listItem.is-inverted').length).toBe(1);
});
it('should update ramps on attribute type changes and select the first one', function () {
spyOn(this.view, 'render').and.callThrough();
this.model.set('attribute_type', 'string');
expect(this.view.render).toHaveBeenCalled();
expect(this.view.$('.js-listItem:eq(0)').data('val')).toContain(this.view.collection.at(0).get('val').join(','));
expect(this.view.$('.js-listItem:eq(0)').hasClass('is-selected')).toBe(true);
expect(this.view.$('.js-customize').text()).toBe('form-components.editors.fill.customize');
});
it('should not have leaks', function () {
expect(this.view).toHaveNoLeaks();
});
afterEach(function () {
this.view.remove();
});
});
describe('with a custom ramp', function () {
beforeEach(function () {
this.model = new Backbone.Model({
bins: 3,
range: ['#FABADA', '#FADFAD', '#BADBAD'],
attribute: 'column1',
quantification: 'jenks'
});
this.view = new InputRampListView(({
model: this.model
}));
this.view.render();
});
it('should render properly', function () {
expect(this.view.$('.js-customRamp').hasClass('is-selected')).toBeTruthy();
expect(this.view.$('.js-customRamp .ColorBar:eq(0)').css('background-color')).toBe('rgb(250, 186, 218)');
expect(this.view.$('.js-customRamp .ColorBar:eq(1)').css('background-color')).toBe('rgb(250, 223, 173)');
expect(this.view.$('.js-customRamp .ColorBar:eq(2)').css('background-color')).toBe('rgb(186, 219, 173)');
});
it('should select the custom ramp', function () {
this.view.$('.js-listItemLink:eq(0)').click();
this.view.$('.js-customRamp').click();
expect(this.view.$('.js-customRamp').hasClass('is-selected')).toBeTruthy();
});
it('should start the customization process clicking on the customized ramp again', function () {
var customizeEventTriggered = false;
this.view.$('.js-listItemLink:eq(0)').click();
this.view.$('.js-customRamp').click();
this.view.bind('customize', function () {
customizeEventTriggered = true;
}, this);
this.view.$('.js-customRamp').click();
expect(customizeEventTriggered).toBeTruthy();
});
it('should clear the custom ramp', function () {
expect(this.view.$('.js-customRamp .ColorBar').length).toBe(3);
this.view.$('.js-clear').click();
expect(this.view.$('.js-customRamp .ColorBar').length).toBe(0);
});
it('should not have leaks', function () {
expect(this.view).toHaveNoLeaks();
});
afterEach(function () {
this.view.remove();
});
});
});
@@ -0,0 +1,111 @@
var _ = require('underscore');
var Backbone = require('backbone');
var InputNumber = require('builder/components/input-number/input-number');
describe('components/form-components/editors/fill/input-number', function () {
beforeEach(function () {
this.model = new Backbone.Model({
range: [1, 30],
attribute: 'the_geom',
quantification: 'Quantile'
});
this.view = new InputNumber(({
model: this.model,
columns: ['pepe', 'paco', 'juan']
}));
this.view.render();
});
afterEach(function () {
this.view.remove();
});
it('should get selected', function () {
this.model.set('selected', true);
expect(this.view.$el.hasClass('is-active')).toBeTruthy();
});
it('should create a content view', function () {
expect(this.view.model.get('createContentView')).toBeDefined();
});
it('should trigger a click event when clicked', function () {
var clickEvent = false;
this.view.bind('click', function () {
clickEvent = true;
});
this.view.$el.click();
expect(clickEvent).toBeTruthy();
});
describe('fixed value', function () {
beforeEach(function () {
this.model = new Backbone.Model({
fixed: 128
});
this.view = new InputNumber(({
model: this.model,
columns: ['pepe', 'paco', 'juan']
}));
this.view.render();
});
it('should render properly', function () {
expect(this.view.$el.text()).toContain('128');
});
it('should update when the value is changed', function () {
this.model.set('fixed', 50);
expect(this.view.$el.text()).toContain('50');
});
});
describe('range', function () {
beforeEach(function () {
this.model = new Backbone.Model({
range: [1, 30],
attribute: 'the_geom',
quantification: 'Quantile'
});
this.view = new InputNumber(({
model: this.model,
columns: ['pepe', 'paco', 'juan']
}));
this.view.render();
});
it('should render properly', function () {
expect(this.view.$el.text()).toContain('1..30');
});
it('should update when the value is changed', function () {
this.model.set('range', [1, 50]);
expect(this.view.$el.text()).toContain('1..50');
});
});
describe('with help', function () {
beforeEach(function () {
this.view = new InputNumber(({
model: this.model,
columns: ['pepe', 'paco', 'juan'],
editorAttrs: {
help: 'help'
}
}));
});
describe('.render', function () {
it('should render properly', function () {
this.view.render();
expect(_.size(this.view._subviews)).toBe(1);
expect(this.view.$('.js-help').attr('data-tooltip')).toContain('help');
});
});
});
it('should not have leaks', function () {
expect(this.view).toHaveNoLeaks();
});
});
@@ -0,0 +1,61 @@
var cdb = require('internal-carto.js');
var Backbone = require('backbone');
var InputNumberContentView = require('builder/components/input-number/input-number-content-view');
describe('components/form-components/editors/fill/input-number/input-number-content-view', function () {
describe('on model with a range', function () {
beforeEach(function () {
this.model = new Backbone.Model({
bins: 7,
range: [1, 100],
attribute: 'age',
quantification: 'jenks',
selected: true,
type: 'size'
});
this.min = 1;
this.max = 45;
this.view = new InputNumberContentView({
stackLayoutModel: new cdb.core.Model(),
model: this.model,
min: this.min,
max: this.max
});
this.view.render();
});
it('should calculate the right range', function () {
var range = this.view._calculateRangeFromFixed(13.5);
expect(range).toEqual([4, 22]);
});
it('should have calculated the right range', function () {
expect(this.model.get('range')).toEqual([1, 100]);
});
it('should not have leaks', function () {
expect(this.view).toHaveNoLeaks();
});
it('should not overwrite the range when not necessary', function () {
this.model.set('range', [10, 12]);
this.view.render();
expect(this.model.get('range')).toEqual([10, 12]);
this.view.render();
expect(this.model.get('range')).toEqual([10, 12]);
});
it('should overwrite the range when necessary', function () {
this.model.set('range', [10, 10]);
this.view.render();
expect(this.model.get('range')).not.toEqual([10, 10]);
});
afterEach(function () {
this.view.remove();
});
});
});
@@ -0,0 +1,35 @@
var Backbone = require('backbone');
var InputNumberDialogContent = require('builder/components/input-number/input-number-dialog-content');
var COLUMNS = ['schmeckles', 'flurbos'];
describe('input-number-dialog-content', function () {
beforeEach(function () {
this.model = new Backbone.Model({
fixed: 42,
attribute: 'wadus'
});
});
it('should set the range to fixed, fixed if no defaultRange specified', function () {
var view = new InputNumberDialogContent({
columns: COLUMNS,
model: this.model
});
view._updateRangeValue();
expect(this.model.get('range')).toEqual([42, 42]);
});
it('should set the range to the defaultRange if specified', function () {
var view = new InputNumberDialogContent({
columns: COLUMNS,
model: this.model,
editorAttrs: {
defaultRange: [19, 87]
}
});
view._updateRangeValue();
expect(this.model.get('range')).toEqual([19, 87]);
});
});
@@ -0,0 +1,109 @@
var Backbone = require('backbone');
var InputNumberValueContentView = require('builder/components/input-number/input-number-value-content-view');
describe('components/form-components/editors/fill/input-number/input-number-value-content-view', function () {
describe('on model with a range', function () {
beforeEach(function () {
this.model = new Backbone.Model({
bins: 7,
range: [1, 100],
attribute: 'age',
quantification: 'jenks',
selected: true,
type: 'size'
});
var columns = [
{ label: 'cartodb_id', type: 'number', val: 'cartodb_id' },
{ label: 'the_geom', type: 'geometry', val: 'the_geom' },
{ label: 'address', type: 'string', val: 'address' },
{ label: 'age', type: 'number', val: 'age' }
];
this.view = new InputNumberValueContentView({
model: this.model,
columns: columns,
min: 0,
max: 100
});
this.view.render();
});
it('should render properly', function () {
expect(this.view.$el.html()).toContain('age');
expect(this.view.$el.html()).toContain('form-components.editors.fill.quantification.methods.jenks');
expect(this.view.$el.html()).toContain('7 form-components.editors.fill.input-ramp.buckets');
expect(this.view.$el.html()).toContain('Max');
expect(this.view.$el.html()).toContain('Min');
});
it('should render the quantification list', function () {
this.view.$('.js-quantification').click();
expect(this.view.$el.html()).toContain('form-components.editors.fill.quantification.title');
expect(this.view.$('.js-listItem').length).toBe(4);
});
it('should render the bins list', function () {
this.view.$('.js-bins').click();
expect(this.view.$el.html()).toContain('form-components.editors.fill.bins');
expect(this.view.$('.js-listItem').length).toBe(6);
});
it('should not have leaks', function () {
expect(this.view).toHaveNoLeaks();
});
afterEach(function () {
this.view.remove();
});
});
describe('on a model with a range but without a defined bins count', function () {
beforeEach(function () {
this.model = new Backbone.Model({
range: [1, 100],
attribute: 'age',
quantification: 'jenks',
selected: true,
type: 'size'
});
var columns = [
{ label: 'cartodb_id', type: 'number', val: 'cartodb_id' },
{ label: 'the_geom', type: 'geometry', val: 'the_geom' },
{ label: 'address', type: 'string', val: 'address' },
{ label: 'age', type: 'number', val: 'age' }
];
this.view = new InputNumberValueContentView({
model: this.model,
columns: columns,
min: 0,
max: 100
});
this.view.render();
});
it('should set the default bins count to 5', function () {
expect(+this.model.get('bins')).toBe(5);
});
it('should render properly', function () {
expect(this.view.$el.html()).toContain('age');
expect(this.view.$el.html()).toContain('form-components.editors.fill.quantification.methods.jenks');
expect(this.view.$el.html()).toContain('5 form-components.editors.fill.input-ramp.buckets');
expect(this.view.$el.html()).toContain('Max');
expect(this.view.$el.html()).toContain('Min');
});
it('should not have leaks', function () {
expect(this.view).toHaveNoLeaks();
});
afterEach(function () {
this.view.remove();
});
});
});
@@ -0,0 +1,84 @@
var Backbone = require('backbone');
var LazySearchCollection = require('builder/components/form-components/editors/lazy-select/lazy-search-collection');
var AnalysisDefinitionNodeModel = require('builder/data/analysis-definition-node-model');
describe('components/form-components/editors/lazy-select/lazy-search-collection', function () {
beforeEach(function () {
var configModel = new Backbone.Model({
base_url: '/u/foo',
user_name: 'foo',
sql_api_template: 'foo',
api_key: 'foo'
});
this.nodeDefModel = new AnalysisDefinitionNodeModel({
id: 'a1',
source: 'a0'
}, {
configModel: configModel,
collection: new Backbone.Collection()
});
this.querySchemaModel = new Backbone.Model({
query: 'select * from wadus'
});
this.nodeDefModel.querySchemaModel = this.querySchemaModel;
var model = new Backbone.Model({
name: 'foo'
});
this.collection = new LazySearchCollection([], {
configModel: configModel,
nodeDefModel: this.nodeDefModel,
rowModel: model,
column: 'name'
});
spyOn(this.collection.SQL, 'execute').and.callFake(function (query, vars, params) {
params && params.success({
rows: [
{
name: 'foo'
},
{
name: 'bar'
},
{
name: 'carto'
}
]
});
});
});
it('initial state', function () {
expect(this.collection.getState()).toBe('empty');
});
it('fetch', function () {
this.collection.fetch();
expect(this.collection.length).toBe(3);
expect(this.collection.getState()).toBe('fetched');
});
it('model', function () {
this.collection.fetch();
var m = this.collection.at(0);
expect(m.getValue()).toBe('foo');
expect(m.getName()).toBe('foo');
});
it('getSelected', function () {
this.collection.fetch();
var m = this.collection.at(0);
this.collection.setSelected(m.getValue());
var selected = this.collection.getSelectedItem();
expect(selected.getValue()).toBe(m.getValue());
});
});
@@ -0,0 +1,211 @@
var $ = require('jquery');
var Backbone = require('backbone');
var _ = require('underscore');
var AnalysisDefinitionNodeModel = require('builder/data/analysis-definition-node-model');
describe('components/form-components/editors/lazy-select', function () {
var dispatchDocumentEvent = function (type, opts) {
var e = document.createEvent('HTMLEvents');
e.initEvent(type, false, true);
if (opts.which) {
e.which = opts.which;
}
document.dispatchEvent(e, opts);
};
var createViewFn = function (options) {
var model = new Backbone.Model({
names: 'pepe',
latitude: undefined
});
var configModel = new Backbone.Model({
base_url: '/u/foo',
user_name: 'foo',
sql_api_template: 'foo',
api_key: 'foo'
});
var nodeDefModel = new AnalysisDefinitionNodeModel({
id: 'a1',
source: 'a0'
}, {
configModel: configModel,
collection: new Backbone.Collection()
});
var querySchemaModel = new Backbone.Model({
query: 'select * from wadus'
});
nodeDefModel.querySchemaModel = querySchemaModel;
var defaultOptions = {
key: 'names',
schema: {
options: [{
columna: 'foo'
}, {
columna: 'bar'
}, {
columna: 'carto'
}]
},
model: model,
configModel: configModel,
nodeDefModel: nodeDefModel,
column: 'columna'
};
var view = new Backbone.Form.editors.LazySelect(_.extend(defaultOptions, options));
view.render();
return view;
};
beforeEach(function () {
this.createView = createViewFn.bind(this);
});
afterEach(function () {
this.view && this.view.remove();
});
it('should genereate an options collection', function () {
this.view = this.createView();
expect(this.view.searchCollection).toBeDefined();
expect(this.view.searchCollection.size()).toBe(3);
});
describe('render', function () {
it('should render properly', function () {
this.view = this.createView();
expect(this.view.$('.js-button').length).toBe(1);
expect(this.view.$('.js-button').text()).toContain('pepe');
});
it('should render custom placeholder if provided', function () {
this.view = this.createView({
placeholder: 'quinoa',
keyAttr: 'latitude'
});
expect(this.view.$('.js-button').length).toBe(1);
expect(this.view.$('.js-button').text()).toContain('quinoa');
});
it('should pass searchPlaceholder to CustomListView if present', function () {
var text = 'Search Machine';
this.view = this.createView({
searchPlaceholder: text
});
expect(this.view._listView.options.searchPlaceholder).toEqual(text);
});
it('should disable the component if option is true', function () {
this.view = this.createView();
this.view.options.disabled = true;
this.view.render();
expect(this.view.$('.js-button').hasClass('is-disabled')).toBeTruthy();
});
it('should add is-empty class if there is no value selected', function () {
this.view = this.createView();
this.view.model.set({names: ''});
this.view.setValue('');
expect(this.view.$('.js-button').hasClass('is-empty')).toBeTruthy();
});
});
describe('bindings', function () {
beforeEach(function () {
this.view = this.createView();
spyOn(this.view._listView, 'hide');
});
it('should close list view if ESC is pressed', function () {
dispatchDocumentEvent('keydown', { which: 27 });
expect(this.view._listView.hide).toHaveBeenCalled();
});
it('should close list view if user clicks out the select', function () {
dispatchDocumentEvent('click', { target: 'body' });
expect(this.view._listView.hide).toHaveBeenCalled();
});
afterEach(function () {
this.view.remove();
});
});
describe('on ENTER pressed', function () {
beforeEach(function () {
this.view = this.createView();
spyOn(this.view._listView, 'toggle');
this._event = $.Event('keydown');
this._event.which = 13;
});
it('should open custom list', function () {
this.view.$('.js-button').trigger(this._event);
expect(this.view._listView.toggle).toHaveBeenCalled();
});
it('should not open custom list if it is already visible', function () {
this.view._listView.show();
this.view.$('.js-button').trigger(this._event);
expect(this.view._listView.toggle).not.toHaveBeenCalled();
});
afterEach(function () {
this.view.remove();
});
});
it('should change button value and hide list when a new item is selected', function () {
this.view = this.createView();
spyOn(this.view._listView, 'hide');
var mdl = this.view.searchCollection.where({ val: 'carto' });
mdl[0].set('selected', true);
expect(this.view.$('.js-button').text()).toContain('carto');
expect(this.view.$('.js-button').hasClass('is-empty')).toBeFalsy();
expect(this.view._listView.hide).toHaveBeenCalled();
});
it('should open list view if "button" is clicked', function () {
this.view = this.createView();
spyOn(this.view._listView, 'toggle');
this.view.$('.js-button').trigger('click');
expect(this.view._listView.toggle).toHaveBeenCalled();
});
describe('placeholder', function () {
it('empty and no value', function () {
this.view = this.createView({
keyAttr: 'latitude',
schema: {
options: []
}
});
var placeholder = $.trim(this.view.$('.js-button').text());
expect(placeholder).toBe('components.backbone-forms.select.empty');
});
it('no value', function () {
this.view = this.createView({
keyAttr: 'latitude'
});
var placeholder = $.trim(this.view.$('.js-button').text());
expect(placeholder).toBe('components.backbone-forms.select.placeholder');
});
});
});
@@ -0,0 +1,278 @@
var Backbone = require('backbone');
var _ = require('underscore');
// Required for affected specs, because we use backbone-forms through a global namespace
require('builder/components/form-components/editors/list/list-item');
describe('components/form-components/editors/list/list-item', function () {
var view;
var createViewFn = function (options) {
var defaultOptions = {
schema: {},
list: {}
};
return new Backbone.Form.editors.List.Item(_.extend(defaultOptions, options));
};
describe('.render', function () {
beforeEach(function () {
view = createViewFn();
});
it('should render properly', function () {
spyOn(view, '_removeTooltip');
spyOn(view, 'setElement').and.callThrough();
view.render();
expect(view.$('[data-editor]').length).toBe(1);
expect(view.setElement).toHaveBeenCalled();
});
it('should render a custom template', function () {
var customTemplate = '<div>My custom Template</div>';
view = createViewFn({
template: _.template(customTemplate)
});
view.render();
expect(view.el.outerHTML).toContain(customTemplate);
});
});
describe('legend-list-item template', function () {
beforeEach(function () {
view = createViewFn({
template: _.template('<div><div data-editor></div><button class="js-remove-help" type="button" data-action="remove">Remove</button></div>')
});
});
describe('.render', function () {
it('should render properly', function () {
spyOn(view, '_removeTooltip');
spyOn(view, 'setElement').and.callThrough();
view.render();
expect(view._removeTooltip).toHaveBeenCalled();
expect(view._tooltip).toBeDefined();
});
});
describe('._removeTooltip', function () {
it('should destroy tooltip', function () {
view.render();
spyOn(view._tooltip, 'clean');
view._removeTooltip();
expect(view._tooltip.clean).toHaveBeenCalled();
});
});
});
describe('.getValue', function () {
it('should call editor.getValue', function () {
view.render();
spyOn(view.editor, 'getValue');
view.getValue();
expect(view.editor.getValue).toHaveBeenCalled();
});
});
describe('.setValue', function () {
it('should call editor.setValue', function () {
view = createViewFn();
view.render();
spyOn(view.editor, 'setValue');
view.setValue('test');
expect(view.editor.setValue).toHaveBeenCalledWith('test');
});
});
describe('.focus', function () {
it('should call editor.focus', function () {
view = createViewFn();
view.render();
spyOn(view.editor, 'focus');
view.focus();
expect(view.editor.focus).toHaveBeenCalled();
});
});
describe('.blur', function () {
it('should call editor.blur', function () {
view = createViewFn();
view.render();
spyOn(view.editor, 'blur');
view.blur();
expect(view.editor.blur).toHaveBeenCalled();
});
});
describe('.validate', function () {
it('should return null', function () {
view = createViewFn();
view.render();
expect(view.validate()).toBeNull();
});
describe('with validators', function () {
beforeEach(function () {
view = createViewFn({
schema: {
validators: ['test']
}
});
view.render();
});
describe('when validation fails', function () {
var error = 'This is an error';
beforeEach(function () {
view.getValidator = function () {
return function () {
return error;
};
};
});
it('should call setError', function () {
spyOn(view, 'setError');
view.validate();
expect(view.setError).toHaveBeenCalled();
});
it('should return the error', function () {
expect(view.validate()).toEqual(error);
});
});
describe('when validation succeds', function () {
beforeEach(function () {
view.getValidator = function () {
return function () {
return false;
};
};
});
it('should call clearError', function () {
spyOn(view, 'clearError');
view.validate();
expect(view.clearError).toHaveBeenCalled();
});
it('should return null', function () {
expect(view.validate()).toBeNull();
});
});
});
});
describe('.setError', function () {
var error = 'This is an error';
beforeEach(function () {
view = createViewFn();
view.render();
view.setError({
message: error
});
});
it('should add the error class to the element', function () {
expect(view.$el.hasClass('error')).toBe(true);
});
it('should set the error to the title attribute', function () {
expect(view.$el.attr('title')).toEqual(error);
});
});
describe('with custom error class', function () {
var errorClass = 'myCustomError';
var errorMessage = 'This is an error';
beforeEach(function () {
view = createViewFn({
errorClassName: errorClass
});
view.render();
view.setError({
message: errorMessage
});
});
describe('.setError', function () {
it('should add the error class to the element', function () {
expect(view.$el.hasClass(errorClass)).toBe(true);
});
});
describe('.clearError', function () {
it('should remove the error class from the element', function () {
expect(view.$el.hasClass(errorClass)).toBe(true);
view.clearError();
expect(view.$el.hasClass(errorClass)).toBe(false);
});
it('should remove the error from the title attribute', function () {
view.clearError();
expect(view.$el.attr('title')).toBeUndefined();
});
});
});
describe('.clearError', function () {
beforeEach(function () {
view = createViewFn();
view.render();
view.setError({
message: 'error'
});
});
it('should add the error class to the element', function () {
expect(view.$el.hasClass('error')).toBe(true);
view.clearError();
expect(view.$el.hasClass('error')).toBe(false);
});
it('should set the error to the title attribute', function () {
view.clearError();
expect(view.$el.attr('title')).toBeUndefined();
});
});
describe('.remove', function () {
it('should call _removeTooltip', function () {
spyOn(view, '_removeTooltip');
view.remove();
expect(view._removeTooltip).toHaveBeenCalled();
});
it('should call editor.remove', function () {
spyOn(view.editor, 'remove');
view.remove();
expect(view.editor.remove).toHaveBeenCalled();
});
});
it('should have no leaks', function () {
view = createViewFn();
view.render();
expect(view).toHaveNoLeaks();
});
afterEach(function () {
view.remove();
});
});
@@ -0,0 +1,151 @@
var Backbone = require('backbone');
describe('components/form-components/editors/list/list', function () {
beforeEach(function () {
this.validator = jasmine.createSpy('validator').and.returnValue({
error: true,
message: 'Foo'
});
this.view = new Backbone.Form.editors.List({
trackingClass: 'Foo-trackingClass',
value: ['wadus', 'foodie'],
schema: {
validators: [ this.validator ]
}
});
spyOn(this.view, 'addItem').and.callThrough();
this.view.render();
});
afterEach(function () {
this.view.remove();
});
describe('render', function () {
it('addItem', function () {
var n = this.view.value.length;
expect(this.view.addItem).toHaveBeenCalledTimes(n);
});
it('tracking class', function () {
var n = this.view.value.length;
expect(this.view.$('.Foo-trackingClass').length).toBe(n);
});
});
describe('validation', function () {
it('should happen on render', function () {
var n = this.view.value.length;
expect(this.view.errors.length).toBe(n);
});
describe('add item button', function () {
it('without validation error', function () {
this.validator.and.returnValue(null);
this.view.validate();
var button = this.view.$('[data-action="add"]');
expect(button.hasClass('is-disabled')).toBe(false);
});
it('with validation error', function () {
this.validator.and.returnValue({
error: true,
message: 'Important error'
});
this.view.validate();
var n = this.view.value.length;
var button = this.view.$('[data-action="add"]');
expect(button.hasClass('is-disabled')).toBe(true);
expect(this.view.errors.length).toBe(n);
});
it('error presenter', function () {
this.validator.and.returnValue({
error: true,
message: 'Foo'
});
this.view.validate();
var error = this.view._errorPresenter();
expect(error).toBe('Foo');
});
});
});
describe('maxItems', function () {
var view;
beforeEach(function () {
spyOn(Backbone.Form.editors.List.prototype, '_setAddButtonState').and.callThrough();
view = new Backbone.Form.editors.List({
trackingClass: 'Foo-trackingClass',
value: ['wadus', 'foodie'],
schema: {
maxItems: 4,
validators: ['required']
}
});
view.render();
});
it('should check if add-button has to be visible or not', function () {
expect(Backbone.Form.editors.List.prototype._setAddButtonState).toHaveBeenCalled();
});
it('should hide add-button when maxItems is reached', function () {
Backbone.Form.editors.List.prototype._setAddButtonState.calls.reset();
view._getAddButtonElement().click();
expect(Backbone.Form.editors.List.prototype._setAddButtonState).toHaveBeenCalled();
expect(view._getAddButtonElement().css('display')).not.toBe('none'); // 3 items, you can add a new one
view._getAddButtonElement().click();
expect(view._getAddButtonElement().css('display')).toBe('none');
});
it('should show add-button when maxItems is not reached', function () {
Backbone.Form.editors.List.prototype._setAddButtonState.calls.reset();
view.removeItem(view.items[0]);
expect(Backbone.Form.editors.List.prototype._setAddButtonState).toHaveBeenCalled();
expect(view._getAddButtonElement().css('display')).not.toBe('none');
});
it('should provide a custom error when maxItems is reached after validating it', function () {
view.options.maxItems = 1;
view.validate();
expect(view.errors.length > 0).toBeTruthy();
expect(view.errors[0]).toBe('form-components.editors.list.max-items');
});
});
describe('_canAddNewItems', function () {
it('should be falsy if there is any validation error', function () {
this.view.errors = ['error'];
expect(this.view._canAddNewItems()).toBeFalsy();
});
it('should be truthy if maxItems is not defined and no errors', function () {
this.view.errors = [];
delete this.view.options.maxItems; // JUst in case
expect(this.view._canAddNewItems()).toBeTruthy();
});
it('should be truthy if maxItems has not been reached and no errors', function () {
this.view.errors = [];
this.view.options.maxItems = 3;
expect(this.view._canAddNewItems()).toBeTruthy();
});
it('should be falsy if maxItems is defined and limit is reached', function () {
this.view.errors = [];
this.view.options.maxItems = 2;
expect(this.view._canAddNewItems()).toBeFalsy();
});
});
});
@@ -0,0 +1,256 @@
var $ = require('jquery');
var _ = require('underscore');
var Backbone = require('backbone');
// Required for affected specs, because we use backbone-forms through a global namespace
require('builder/components/form-components/editors/number/number.js');
var ARROW_UP_KEY = 38;
var ARROW_DOWN_KEY = 40;
describe('components/form-components/editors/number', function () {
var createViewFn = function (options) {
var defaultOptions = {
schema: {}
};
var view = new Backbone.Form.editors.Number(_.extend(defaultOptions, options));
view.render();
return view;
};
beforeEach(function () {
this.view = createViewFn();
this.view.render();
this.$input = this.view.$('.js-input');
});
afterEach(function () {
this.view.remove();
});
it('should render properly', function () {
expect(this.$input.length).toBe(1);
expect(this.view.$('.js-slider').length).toBe(1);
});
it('should not create the horizontal slider if not desired', function () {
var view = createViewFn({
showSlider: false
});
view.render();
expect(view.$('.js-slider').length).toBe(0);
});
describe('max and min', function () {
it('should get values by default', function () {
expect(this.view.options.min).toBe(0);
expect(this.view.options.max).toBe(10);
});
it('should accept max and min accross validators', function () {
var view = createViewFn({
schema: {
validators: ['required', {
type: 'interval',
min: 5,
max: 30
}]
}
});
expect(view.options.min).toBe(5);
expect(view.options.max).toBe(30);
});
});
describe('change value', function () {
beforeEach(function () {
this.onChanged = jasmine.createSpy('onChanged');
this.view.bind('change', this.onChanged);
});
describe('when slider changes', function () {
beforeEach(function () {
var $slider = this.view.$('.js-slider');
$slider.slider('option', 'slide').call($slider, {}, { value: 5 });
$slider.slider('option', 'stop').call($slider);
});
it('should trigger change after debounce time', function (done) {
var self = this;
setTimeout(function () {
expect(self.onChanged).toHaveBeenCalled();
done();
}, 334);
});
it('should update input', function () {
expect(this.$input.val()).toBe('5');
});
});
describe('when input changes', function () {
beforeEach(function () {
this.$input.val(6).trigger('keyup');
});
it('should trigger change', function (done) {
var self = this;
setTimeout(function () {
expect(self.onChanged).toHaveBeenCalled();
done();
}, 334);
});
it('should update input', function () {
expect(this.view.$('.js-slider').slider('value')).toBe(6);
});
describe('when pressing the UP key', function () {
it('should increase the value', function () {
this.view.setValue(7);
var event = $.Event('keydown');
event.keyCode = event.which = ARROW_UP_KEY;
this.$input.trigger(event);
this.$input.trigger(event);
this.$input.trigger(event);
expect(this.$input.val()).toBe('10');
});
it('should increase the value when pressing shift', function () {
this.view.setValue(0);
var event = $.Event('keydown');
event.keyCode = event.which = ARROW_UP_KEY;
event.shiftKey = true;
this.$input.trigger(event);
expect(this.$input.val()).toBe('10');
});
it('should not increase the value if it exceeds the max allowed', function () {
this.view.setValue(10);
var event = $.Event('keydown');
event.keyCode = event.which = ARROW_UP_KEY;
this.$input.trigger(event);
this.$input.trigger(event);
this.$input.trigger(event);
expect(this.$input.val()).toBe('10');
});
});
describe('when pressing the DOWN key', function () {
it('should decrease the value', function () {
this.view.setValue(7);
var event = $.Event('keydown');
event.keyCode = event.which = ARROW_DOWN_KEY;
this.$input.trigger(event);
this.$input.trigger(event);
this.$input.trigger(event);
expect(this.$input.val()).toBe('4');
});
it('should decrease the value when pressing shift', function () {
this.view.setValue(10);
var event = $.Event('keydown');
event.keyCode = event.which = ARROW_DOWN_KEY;
event.shiftKey = true;
this.$input.trigger(event);
expect(this.$input.val()).toBe('0');
});
it('should not decrease the value if it exceeds the max allowed', function () {
this.view.setValue(0);
var event = $.Event('keydown');
event.keyCode = event.which = ARROW_DOWN_KEY;
this.$input.trigger(event);
this.$input.trigger(event);
this.$input.trigger(event);
expect(this.$input.val()).toBe('0');
});
it('should work with negative min value', function () {
var view = createViewFn({
schema: {
validators: ['required', {
type: 'interval',
min: -5,
max: 10
}]
}
});
var $input = view.$('.js-input');
view.setValue(0);
var event = $.Event('keydown');
event.keyCode = event.which = ARROW_DOWN_KEY;
$input.trigger(event);
$input.trigger(event);
$input.trigger(event);
expect($input.val()).toBe('-3');
});
});
});
});
it('should destroy horizontal slider and tooltip when element is removed', function () {
spyOn(this.view, '_destroySlider');
spyOn(this.view, '_removeTooltip');
this.view.remove();
expect(this.view._destroySlider).toHaveBeenCalled();
expect(this.view._removeTooltip).toHaveBeenCalled();
});
describe('with help', function () {
var view;
beforeEach(function () {
view = createViewFn({
editorAttrs: {
help: 'help'
}
});
});
describe('.render', function () {
it('should render properly', function () {
view.render();
expect(view.$('.js-help').attr('data-tooltip')).toContain('help');
});
});
describe('._removeTooltip', function () {
it('should destroy tooltip', function () {
spyOn(view._helpTooltip, 'clean');
view._removeTooltip();
expect(view._helpTooltip.clean).toHaveBeenCalled();
});
});
});
it('should not have leaks', function () {
expect(this.view).toHaveNoLeaks();
});
});
@@ -0,0 +1,40 @@
var OperatorsListModel = require('builder/components/form-components/editors/operators/operators-list-model');
describe('components/form-components/operators/operators-list-model', function () {
beforeEach(function () {
this.model = new OperatorsListModel({
operator: 'count',
attribute: ''
});
});
describe('.isValidOperator', function () {
it('should be true when operator is count', function () {
expect(this.model.isValidOperator()).toBeTruthy();
});
it('should be valid when operator is different than count and there is an attribute', function () {
this.model.attributes = {
operator: 'sum',
attribute: '$'
};
expect(this.model.isValidOperator()).toBeTruthy();
});
it('should be unvalid when operator is different than count and there is no an attribute', function () {
this.model.attributes = {
operator: 'sum',
attribute: ''
};
expect(this.model.isValidOperator()).toBeFalsy();
});
it('should be unvalid when operator is empty and there is an attribute', function () {
this.model.attributes = {
operator: '',
attribute: '$'
};
expect(this.model.isValidOperator()).toBeFalsy();
});
});
});
@@ -0,0 +1,101 @@
var _ = require('underscore');
var $ = require('jquery');
var OperatorsListView = require('builder/components/form-components/editors/operators/operators-list-view');
var CustomListCollection = require('builder/components/form-components/editors/operators/operators-list-collection');
describe('components/form-components/operators/operators-list-view', function () {
var view, collection;
var createViewFn = function () {
collection = new CustomListCollection([
{
val: '$',
type: 'number'
}, {
val: '€',
type: 'number'
}, {
val: '¥',
type: 'number'
}
]);
var view = new OperatorsListView({
attribute: '',
operator: 'count',
collection: collection
});
return view;
};
beforeEach(function () {
spyOn(_, 'debounce').and.callFake(function (func) {
return function () {
func.apply(this, arguments);
};
});
view = createViewFn();
view.render();
});
afterEach(function () {
view.clean();
});
it('should generate an internal model with the options', function () {
expect(view.model).toBeDefined();
var attrs = view.model.attributes;
expect(attrs.operator).toBe('count');
expect(attrs.attribute).toBe('');
});
it('should destroy list if hidden', function () {
spyOn(view, '_destroyList');
spyOn(view, 'remove');
// To force a change
view.model.unset('visible');
view.model.set('visible', false);
expect(view._destroyList).toHaveBeenCalled();
expect(view.remove).not.toHaveBeenCalled();
});
describe('.render', function () {
it('should render properly', function () {
expect(view.$('.Editor-dropdownCalculations').length).toBe(1);
expect(view.$('.Editor-dropdownCalculationsElement').length).toBe(5);
expect(view.$('[name="operator"]').val()).toBe('count');
expect($('.CDB-Box-modalOverlay').length).toBe(1);
expect(_.size(view._subviews)).toBe(1);
expect(view._hasList()).toBeFalsy();
});
it('should render list when operator is different than count', function () {
view.$('[value="avg"]').click().trigger('change');
expect(view._hasList()).toBeTruthy();
view.$('[value="count"]').click().trigger('change');
expect(view._hasList()).toBeFalsy();
});
});
describe('._onModelChange', function () {
it('should trigger change when new value is selected and is valid', function () {
spyOn(view, 'trigger');
view.model.set({ operator: 'avg', attribute: '¥' });
expect(view.trigger).toHaveBeenCalled();
});
it('should not trigger change when new value is selected and is not valid', function () {
spyOn(view, 'trigger');
view.model.set({ operator: 'avg', attribute: '' });
expect(view.trigger).not.toHaveBeenCalled();
});
});
it('should destroy list view when it is removed', function () {
view.remove();
expect(view._hasList()).toBeFalsy();
});
});
@@ -0,0 +1,159 @@
var $ = require('jquery');
var Backbone = require('backbone');
var dispatchDocumentEvent = function (type, opts) {
var e = document.createEvent('HTMLEvents');
e.initEvent(type, false, true);
if (opts.which) {
e.which = opts.which;
}
document.dispatchEvent(e, opts);
};
describe('components/form-components/operators/operators-view', function () {
beforeEach(function () {
this.model = new Backbone.Model({
currency: {
operator: 'count',
attribute: ''
}
});
this.view = new Backbone.Form.editors.Operators({
key: 'currency',
schema: {
options: ['$', '€', '¥']
},
model: this.model
});
this.view.render();
this.listView = this.view._operatorsListView;
});
it('should genereate an options collection', function () {
expect(this.view.collection).toBeDefined();
expect(this.view.collection.size()).toBe(3);
});
describe('render', function () {
it('should render properly', function () {
expect(this.view.$('.js-operator').length).toBe(1);
expect(this.view.$('.js-button').length).toBe(1);
expect(this.view.$('.js-button').text().toLowerCase()).toContain('count');
});
it('should disable the component if option is true', function () {
this.view.options.disabled = true;
spyOn(this.view, 'undelegateEvents').and.callThrough();
this.view._initViews();
expect(this.view.$('.js-button').hasClass('is-disabled')).toBeTruthy();
expect(this.view.undelegateEvents).toHaveBeenCalled();
});
it('should add is-empty class if there is no value selected', function () {
this.model.set('currency', '');
this.view._initViews();
expect(this.view.$('.js-button').hasClass('is-empty')).toBeTruthy();
});
});
describe('bindings', function () {
beforeEach(function () {
spyOn(this.listView, 'hide');
});
it('should close list view if ESC is pressed', function () {
dispatchDocumentEvent('keydown', { which: 27 });
expect(this.listView.hide).toHaveBeenCalled();
});
it('should close list view if user clicks out the select', function () {
dispatchDocumentEvent('click', { target: 'body' });
expect(this.listView.hide).toHaveBeenCalled();
});
});
describe('on ENTER pressed', function () {
beforeEach(function () {
spyOn(this.listView, 'toggle');
this._event = $.Event('keydown');
this._event.which = 13;
});
it('should open custom list', function () {
this.view.$('.js-button').trigger(this._event);
expect(this.listView.toggle).toHaveBeenCalled();
});
it('should not open custom list if it is already visible', function () {
this.listView.show();
this.view.$('.js-button').trigger(this._event);
expect(this.listView.toggle).not.toHaveBeenCalled();
});
});
it('should change button value when a new values are selected', function () {
var values = {
operator: 'sum',
attribute: '¥'
};
this.listView.trigger('change', values);
expect(this.view.$('.js-button').text().toLowerCase()).toContain('sum(¥)');
expect(this.view.$('.js-button').hasClass('is-empty')).toBeFalsy();
});
it('should open list view if "button" is clicked', function () {
spyOn(this.listView, 'toggle');
this.view.$('.js-button').trigger('click');
expect(this.listView.toggle).toHaveBeenCalled();
});
it('should destroy custom list and tooltip when element is removed', function () {
spyOn(this.listView, 'clean');
spyOn(this.view, '_removeTooltip');
this.view.remove();
expect(this.listView.clean).toHaveBeenCalled();
expect(this.view._removeTooltip).toHaveBeenCalled();
});
describe('with help', function () {
beforeEach(function () {
this.view = new Backbone.Form.editors.Operators({
key: 'currency',
schema: {
options: ['$', '€', '¥']
},
model: this.model,
editorAttrs: {
help: 'help'
}
});
});
it('should render correctly', function () {
this.view.render();
expect(this.view.$('.js-help').attr('data-tooltip')).toContain('help');
});
describe('._removeTooltip', function () {
it('should destroy tooltip', function () {
spyOn(this.view._helpTooltip, 'clean');
this.view._removeTooltip();
expect(this.view._helpTooltip.clean).toHaveBeenCalled();
});
});
});
it('should not have any leaks', function () {
expect(this.view).toHaveNoLeaks();
});
afterEach(function () {
this.view.remove();
this.listView.remove();
});
});
@@ -0,0 +1,58 @@
var _ = require('underscore');
var $ = require('jquery');
var Backbone = require('backbone');
var OPTIONS = [{
type: 'jpg',
label: '.jpg',
className: 'firstClass'
}, {
type: 'png',
label: '.png',
className: 'secondClass'
}];
describe('components/form-components/editors/radio', function () {
beforeEach(function () {
this.model = new Backbone.Model({ what: true });
this.form = new Backbone.Form({
model: this.model
});
this.view = new Backbone.Form.editors.Radio({
key: 'what',
form: this.form,
schema: {
options: _.map(OPTIONS, function (d) {
return {
val: d.type,
label: d.label,
className: d.className
};
}, this)
}
});
this.view.render();
});
it('should render the radio buttons', function () {
expect(this.view.$('.CDB-Radio').length).toBe(2);
expect($(this.view.$('.CDB-Radio').get(0)).val('jpg')).toBeTruthy();
});
it('should add the classes', function () {
expect($(this.view.$('.CDB-Radio').get(0)).hasClass('firstClass')).toBeTruthy();
expect($(this.view.$('.CDB-Radio').get(1)).hasClass('secondClass')).toBeTruthy();
});
it('should return the right value', function () {
$(this.view.$('.CDB-Radio').get(0)).click();
expect(this.view.getValue()).toBe('jpg');
});
afterEach(function () {
this.view.remove();
});
});
@@ -0,0 +1,77 @@
var _ = require('underscore');
var Backbone = require('backbone');
var SelectListView = require('builder/components/form-components/editors/select/select-list-view');
var ItemTemplate = require('builder/components/custom-list/custom-list-item.tpl');
var CustomListItemView = require('builder/components/custom-list/custom-list-item-view');
var CustomListCollection = require('builder/components/custom-list/custom-list-collection');
describe('components/form-components/editors/select-list-view', function () {
var mouseOverAction;
var mouseOutAction;
var createViewFn = function (options) {
mouseOverAction = jasmine.createSpy('mouseOverAction');
mouseOutAction = jasmine.createSpy('mouseOutAction');
var collection = new CustomListCollection();
collection.stateModel = new Backbone.Model({
state: 'fetching'
});
collection.isAsync = function () { return true; };
var defaultOptions = {
itemTemplate: ItemTemplate,
itemView: CustomListItemView,
collection: collection,
mouseOverAction: mouseOverAction,
mouseOutAction: mouseOutAction
};
var view = new SelectListView(_.extend(defaultOptions, options));
return view;
};
describe('.render', function () {
it('should render properly', function () {
var view = createViewFn();
spyOn(view, '_renderListSection');
view.render();
expect(view._renderListSection).toHaveBeenCalled();
});
});
describe('mouseOverAction', function () {
describe('._onMouseOver', function () {
it('should trigger mouseOverAction', function () {
var view = createViewFn();
view.render();
view._onMouseOver();
expect(mouseOverAction).toHaveBeenCalled();
});
});
});
describe('mouseOutAction', function () {
describe('._onMouseOut', function () {
it('should trigger mouseOutAction', function () {
var view = createViewFn();
view.render();
view._onMouseOut();
expect(mouseOutAction).toHaveBeenCalled();
});
});
});
it('should have no leaks', function () {
var view = createViewFn();
expect(view).toHaveNoLeaks();
});
});
@@ -0,0 +1,74 @@
var Backbone = require('backbone');
var _ = require('underscore');
// Required for affected specs, because we use backbone-forms through a global namespace
require('builder/components/form-components/editors/select/multi-select-view.js');
function viewFactory (model) {
return new Backbone.Form.editors.MultiSelect({
key: 'names',
schema: {
options: ['pepe', 'paco', 'juan', 'rm_rick', 'rm_morty', 'rm_summer', 'rm_jerry', 'rm_beth', 'rm_mr meeseeks']
},
model: model
});
}
describe('components/form-components/editors/select/multi-select-view', function () {
beforeEach(function () {
this.model = new Backbone.Model({
names: 'pepe'
});
this.view = viewFactory(this.model);
this.view.render();
});
describe('render', function () {
it('should render properly', function () {
expect(this.view.$('.js-button').length).toBe(1);
expect(this.view.$('.js-button').text()).toContain('components.backbone-forms.select.selected');
});
});
it('should trigger change event on select item', function () {
var onChange = jasmine.createSpy('onChange');
spyOn(_, 'debounce').and.callFake(function () {
return onChange;
});
var aView = viewFactory(this.model);
aView.render();
aView.on('change', onChange);
aView.collection.at(1).set({selected: true});
expect(onChange).toHaveBeenCalled();
aView.remove();
});
describe('all/none buttons', function () {
it('should use _.debounce to prevent multiple change events firing', function () {
var mockbounce = spyOn(_, 'debounce').and.callThrough();
var aView = viewFactory(this.model);
aView._selectAll();
expect(mockbounce).toHaveBeenCalled();
});
it('selects and deselects all', function () {
this.view._selectAll();
expect(this.view.collection.every(function (model) {
return model.get('selected');
})).toBe(true);
this.view._deselectAll();
expect(this.view.collection.every(function (model) {
return !model.get('selected');
})).toBe(true);
});
});
afterEach(function () {
this.view.remove();
});
});
@@ -0,0 +1,56 @@
var Backbone = require('backbone');
var SelectListView = require('builder/components/form-components/editors/select/select-list-view');
var itemListTemplate = require('builder/components/custom-list/custom-list-item.tpl');
var CustomListCollection = require('builder/components/custom-list/custom-list-collection');
var CustomListItemView = require('builder/components/custom-list/custom-list-item-view');
describe('components/form-components/editors/select/select-list-view', function () {
var view;
var createViewFn = function (options) {
var collection = new CustomListCollection([], {});
var itemView = new CustomListItemView({
model: new Backbone.Model()
});
var selectListView = new SelectListView({
collection: collection,
itemTemplate: itemListTemplate,
itemView: itemView
});
return selectListView;
};
beforeEach(function () {
view = createViewFn();
view.render();
});
afterEach(function () {
view.clean();
});
it('should not have leaks', function () {
expect(view).toHaveNoLeaks();
});
describe('_toggleVisibility', function () {
it('should render the overlay when visibility changes to true', function () {
view.show();
var dropdownOverlay = document.querySelector('.CDB-Box-modalOverlay');
expect(dropdownOverlay).not.toBeNull();
expect(window.getComputedStyle(dropdownOverlay).display).toBe('block');
});
it('should remove the overlay when visibility changes to false', function () {
view.show();
view.hide();
var dropdownOverlay = document.querySelector('.CDB-Box-modalOverlay');
expect(dropdownOverlay).toBeNull();
});
});
});
@@ -0,0 +1,67 @@
var Backbone = require('backbone');
var _ = require('underscore');
describe('components/form-components/editors/select', function () {
var view;
var mouseOverAction;
var mouseOutAction;
mouseOverAction = jasmine.createSpy('mouseOverAction');
mouseOutAction = jasmine.createSpy('mouseOutAction');
var createViewFn = function (options) {
var model = new Backbone.Model({
names: 'pepe',
latitude: undefined
});
var defaultOptions = {
key: 'names',
schema: {
options: ['pepe', 'paco', 'juan']
},
model: model,
mouseOverAction: mouseOverAction,
mouseOutAction: mouseOutAction,
placeholder: 'gruntbuggly'
};
view = new Backbone.Form.editors.SelectPlaceholder(_.extend(defaultOptions, options));
view.render();
return view;
};
beforeEach(function () {
this.createView = createViewFn.bind(this);
});
afterEach(function () {
view && view.remove();
});
it('should force is-empty if provided forcePlaceholder', function () {
view = this.createView({
forcePlaceholder: true
});
var btn = view.$el.find('.js-button');
expect(btn.hasClass('is-empty')).toBe(true);
expect(btn.text()).toContain('gruntbuggly');
});
it('should force is-empty if provided forcePlaceholder', function () {
view = this.createView({
forcePlaceholder: false
});
var btn = view.$el.find('.js-button');
expect(btn.hasClass('is-empty')).toBe(false);
expect(btn.text()).not.toContain('gruntbuggly');
expect(btn.text()).toContain('pepe');
});
});
@@ -0,0 +1,292 @@
var $ = require('jquery');
var Backbone = require('backbone');
var _ = require('underscore');
var CustomListCollection = require('builder/components/custom-list/custom-list-collection');
describe('components/form-components/editors/select', function () {
var view;
var mouseOverAction;
var mouseOutAction;
var dispatchDocumentEvent = function (type, opts) {
var e = document.createEvent('HTMLEvents');
e.initEvent(type, false, true);
if (opts.which) {
e.which = opts.which;
}
document.dispatchEvent(e, opts);
};
mouseOverAction = jasmine.createSpy('mouseOverAction');
mouseOutAction = jasmine.createSpy('mouseOutAction');
var createViewFn = function (options) {
var model = new Backbone.Model({
names: 'pepe',
latitude: undefined
});
var defaultOptions = {
key: 'names',
schema: {
options: ['pepe', 'paco', 'juan']
},
model: model,
mouseOverAction: mouseOverAction,
mouseOutAction: mouseOutAction
};
view = new Backbone.Form.editors.Select(_.extend(defaultOptions, options));
view.render();
return view;
};
beforeEach(function () {
this.createView = createViewFn.bind(this);
});
afterEach(function () {
view && view.remove();
});
it('should genereate an options collection', function () {
view = this.createView();
expect(view.collection).toBeDefined();
expect(view.collection.size()).toBe(3);
});
describe('render', function () {
it('should render properly', function () {
view = this.createView();
expect(view.$('.js-button').length).toBe(1);
expect(view.$('.js-button').text()).toContain('pepe');
});
it('should render custom placeholder if provided', function () {
view = this.createView({
placeholder: 'quinoa',
keyAttr: 'latitude'
});
expect(view.$('.js-button').length).toBe(1);
expect(view.$('.js-button').text()).toContain('quinoa');
});
it('should pass searchPlaceholder to CustomListView if present', function () {
var text = 'Search Machine';
view = this.createView({
searchPlaceholder: text
});
expect(view._listView.options.searchPlaceholder).toEqual(text);
});
it('should disable the component if option is true', function () {
view = this.createView();
view.options.disabled = true;
view.render();
expect(view.$('.js-button').hasClass('is-disabled')).toBeTruthy();
});
it('should add is-empty class if there is no value selected', function () {
view = this.createView();
view.model.set({names: ''});
view.setValue('');
expect(view.$('.js-button').hasClass('is-empty')).toBeTruthy();
});
});
describe('bindings', function () {
beforeEach(function () {
view = this.createView();
spyOn(view._listView, 'hide');
});
it('should close list view if ESC is pressed', function () {
dispatchDocumentEvent('keydown', { which: 27 });
expect(view._listView.hide).toHaveBeenCalled();
});
});
describe('on ENTER pressed', function () {
beforeEach(function () {
view = this.createView();
spyOn(view._listView, 'toggle');
this._event = $.Event('keydown');
this._event.which = 13;
});
it('should open custom list', function () {
view.$('.js-button').trigger(this._event);
expect(view._listView.toggle).toHaveBeenCalled();
});
it('should not open custom list if it is already visible', function () {
view._listView.show();
view.$('.js-button').trigger(this._event);
expect(view._listView.toggle).not.toHaveBeenCalled();
});
});
it('should change button value and hide list when a new item is selected', function () {
view = this.createView();
spyOn(view._listView, 'hide');
var mdl = view.collection.where({ val: 'juan' });
mdl[0].set('selected', true);
expect(view.$('.js-button').text()).toContain('juan');
expect(view.$('.js-button').hasClass('is-empty')).toBeFalsy();
expect(view._listView.hide).toHaveBeenCalled();
});
it('should open list view if "button" is clicked', function () {
view = this.createView();
spyOn(view._listView, 'toggle');
view.$('.js-button').trigger('click');
expect(view._listView.toggle).toHaveBeenCalled();
});
it('should destroy custom list, and tooltip when element is removed', function () {
view = this.createView();
spyOn(view._listView, 'clean');
spyOn(view, '_removeTooltip');
view.remove();
expect(view._listView.clean).toHaveBeenCalled();
expect(view._removeTooltip).toHaveBeenCalled();
});
describe('placeholder', function () {
it('empty and no value', function () {
view = this.createView({
keyAttr: 'latitude',
schema: {
options: []
}
});
var placeholder = $.trim(view.$('.js-button').text());
expect(placeholder).toBe('components.backbone-forms.select.empty');
});
it('disabled and no value', function () {
view = this.createView({
keyAttr: 'latitude',
disabled: true
});
var placeholder = $.trim(view.$('.js-button').text());
expect(placeholder).toBe('components.backbone-forms.select.disabled-placeholder');
});
it('no value', function () {
view = this.createView({
keyAttr: 'latitude'
});
var placeholder = $.trim(view.$('.js-button').text());
expect(placeholder).toBe('components.backbone-forms.select.placeholder');
});
});
describe('async collection', function () {
beforeEach(function () {
var collection = new CustomListCollection();
collection.stateModel = new Backbone.Model({
state: 'fetching'
});
collection.isAsync = function () { return true; };
view = this.createView({
schema: {
collection: collection
}
});
});
it('should show loading if collection is fetching', function () {
expect(view.$('.js-button .CDB-LoaderIcon').length).toBe(1);
});
it('should show list once collection is fetched', function () {
view.collection.reset([{
label: 'pepe',
val: 'pepe'
}, {
label: 'paco',
val: 'paco'
}, {
label: 'juan',
val: 'juan'
}]);
view.collection.stateModel.set({
state: 'fetched'
});
expect(view.$('.CustomList--inner').length).toBe(1);
expect(view.$('.js-button').text()).toContain('pepe');
});
});
describe('with help', function () {
beforeEach(function () {
view = this.createView({
editorAttrs: {
help: 'help'
}
});
});
describe('.render', function () {
it('should render properly', function () {
expect(view.$('.js-help').attr('data-tooltip')).toContain('help');
});
});
describe('._removeTooltip', function () {
it('should destroy tooltip', function () {
spyOn(view._helpTooltip, 'clean');
view._removeTooltip();
expect(view._helpTooltip.clean).toHaveBeenCalled();
});
});
});
describe('mouseOverAction', function () {
describe('._onMouseOver', function () {
it('should trigger mouseOverAction', function () {
view = this.createView();
view._onMouseOver();
expect(mouseOverAction).toHaveBeenCalled();
});
});
});
describe('mouseOutAction', function () {
describe('._onMouseOut', function () {
it('should trigger mouseOutAction', function () {
view = this.createView();
view._onMouseOut();
expect(mouseOutAction).toHaveBeenCalled();
});
});
});
it('should not have leaks', function () {
view = this.createView();
expect(view).toHaveNoLeaks();
});
});
@@ -0,0 +1,180 @@
var Backbone = require('backbone');
var View = require('builder/components/form-components/editors/size/size-by-value-content-view');
describe('components/form-components/editors/size/size-by-value-content-view', function () {
var view;
function createView (model, opts) {
model = model || new Backbone.Model({
bins: 7,
attribute: 'price',
quantification: 'jenks'
});
opts = opts || {};
if (opts.fixed) {
model.set('fixed', opts.fixed);
}
if (opts.range) {
model.set('range', opts.range);
}
var options = {
model: model,
min: 1,
max: 50
};
return new View(options);
}
describe('render', function () {
it('should render template and call _initForm', function () {
view = createView();
spyOn(view, '_initForm');
view.render();
expect(view.$('.js-back').length).toBe(1);
expect(view.$('.test-quantification')[0].textContent.trim()).toContain('jenks');
expect(view.$('.test-bins')[0].textContent.trim().indexOf('7')).toBe(0);
expect(view.$('.test-attribute')[0].textContent.trim()).toEqual('price');
expect(view._initForm).toHaveBeenCalled();
});
});
describe('_initForm', function () {
it('should calculate range and create formView', function () {
view = createView();
spyOn(view, '_getRangeOrCalculateItIfNeeded').and.returnValue(808);
spyOn(view, '_createFormView').and.returnValue('a_formview');
spyOn(view, '_renderFormView');
view._initForm();
expect(view._getRangeOrCalculateItIfNeeded).toHaveBeenCalled();
expect(view._createFormView).toHaveBeenCalledWith(808);
expect(view._renderFormView).toHaveBeenCalled();
});
});
describe('_getRangeOrCalculateItIfNeeded', function () {
it('should calculate range from fixed', function () {
view = createView(null, { fixed: 18 });
var range = view._getRangeOrCalculateItIfNeeded();
expect(range[0]).toBe(6);
expect(range[1]).toBe(29);
expect(view.model.get('fixed')).not.toBeDefined();
expect(view.model.get('range')).toBeDefined();
expect(view.model.get('range')[0]).toBe(6);
expect(view.model.get('range')[1]).toBe(29);
});
it('should return range if exists', function () {
view = createView(null, { range: [45, 57] });
var range = view._getRangeOrCalculateItIfNeeded();
expect(range[0]).toBe(45);
expect(range[1]).toBe(57);
});
});
describe('_createFormView', function () {
it('should create the form view', function () {
view = createView();
var formView = view._createFormView([45, 47]);
expect(formView.model.get('min')).toBe(45);
expect(formView.model.get('max')).toBe(47);
expect(formView.model.schema).toEqual(jasmine.objectContaining({
min: {
type: 'Number',
validators: [
'required',
{
type: 'interval',
min: 1,
max: 50
}
]
},
max: {
type: 'Number',
validators: [
'required',
{
type: 'interval',
min: 1,
max: 50
}
]
}
}));
});
it('change bindings sets model and commits form', function () {
view = createView(null, { range: [15, 35] });
view.render();
var $input1 = view.$('.js-input').first();
var $input2 = view.$('.js-input').last();
$input1.val(10);
$input2.val(40);
view._formView.trigger('change');
expect(view.model.get('range')[0]).toEqual(10);
expect(view.model.get('range')[1]).toEqual(40);
});
});
describe('events', function () {
it('should hook up js-back with _onClickBack', function (done) {
view = createView(null, { range: [15, 35] });
view.render();
view.on('back', function () {
expect(true).toBe(true);
done();
});
view.$('.js-back').click();
});
it('should hook up js-quantification with _onClickQuantification', function (done) {
view = createView(null, { range: [15, 35] });
view.render();
view.on('selectQuantification', function () {
expect(true).toBe(true);
done();
});
view.$('.js-quantification').click();
});
it('should hook up js-bins with _onClickBins', function (done) {
view = createView(null, { range: [15, 35] });
view.render();
view.on('selectBins', function () {
expect(true).toBe(true);
done();
});
view.$('.js-bins').click();
});
});
describe('clean', function () {
it('clean removes form', function () {
view = createView();
view.render();
expect(view.$('form').length).toBe(1);
view.clean();
expect(view.$('form').length).toBe(0);
});
});
});
@@ -0,0 +1,162 @@
var Backbone = require('backbone');
var _ = require('underscore');
var SizeByValueView = require('builder/components/form-components/editors/size/size-by-value-view');
var FillConstants = require('builder/components/form-components/_constants/_fill');
describe('components/form-components/editors/size/size-by-value-view', function () {
var view;
var defaultSettings = FillConstants.Settings.NUMBER;
function createView (options) {
options = options || {
model: new Backbone.Model({}),
columns: {},
popupConfig: {}
};
return new SizeByValueView(options);
}
describe('initialize', function () {
it('model is set with default options', function () {
view = createView();
expect(view.model.get('quantification')).toEqual(defaultSettings.quantifications.items[defaultSettings.quantifications.defaultIndex]);
expect(view.model.get('bins')).toBe(defaultSettings.bins.items[defaultSettings.bins.defaultIndex]);
});
it('model is initialized with options', function () {
view = createView({
model: new Backbone.Model({
quantification: 'jenks',
bins: 7
}),
columns: {},
popupConfig: {}
});
expect(view.model.get('quantification')).toEqual('jenks');
expect(view.model.get('bins')).toBe(7);
});
it('model bins get limited by settings', function () {
view = createView({
model: new Backbone.Model({
bins: _.last(defaultSettings.bins.items) + 1
}),
columns: {},
popupConfig: {}
});
expect(view.model.get('bins')).toBe(_.last(defaultSettings.bins.items));
});
it('attribute change triggers render', function () {
view = createView({
model: new Backbone.Model({
attribute: 'an_attribute'
}),
columns: {},
popupConfig: {}
});
expect(view.el.children.length).toBe(0);
view.model.set('attribute', 'another_attribute');
expect(view.el.children.length).not.toBe(0);
});
it('range change triggers render', function () {
view = createView({
model: new Backbone.Model({
range: [0, 5]
}),
columns: {},
popupConfig: {}
});
expect(view.el.children.length).toBe(0);
view.model.set('range', [3, 7]);
expect(view.el.children.length).not.toBe(0);
});
});
describe('render', function () {
it('calls to _initViews', function () {
view = createView();
spyOn(view, '_initDialog');
spyOn(view, '_initPopup');
spyOn(view, '_initInputColumn');
view.render();
expect(view._initDialog).toHaveBeenCalled();
expect(view._initPopup).toHaveBeenCalled();
expect(view._initInputColumn).toHaveBeenCalled();
});
it('renders the column info', function () {
view = createView({
model: new Backbone.Model({
attribute: 'price',
range: [3, 9]
}),
columns: {},
popupConfig: {
cid: 357,
$el: 'an_element'
}
});
view.render();
expect(view.$('.by-column-name').text().trim()).toEqual('price');
expect(view.$('.by-column-range').text().trim()).toEqual('3 - 9');
});
});
describe('_initDialog', function () {
it('creates the dialog view and binds destroy', function () {
view = createView();
expect(view._dialogView).not.toBeDefined();
view._initDialog();
expect(view._dialogView).toBeDefined();
view._dialogView.model.trigger('destroy');
expect(view._dialogView).toBeNull();
});
});
describe('_initPopup', function () {
it('popupmanager gets created', function () {
view = createView({
model: new Backbone.Model({}),
columns: {},
popupConfig: {
cid: 357,
$el: 'an_element'
}
});
expect(view._popupManager).not.toBeDefined();
view._initDialog();
view._initPopup();
expect(view._popupManager.id).toBe(357);
expect(view._popupManager.reference).toEqual('an_element');
expect(view._popupManager.popup).toBe(view._dialogView.$el);
});
});
describe('events', function () {
it('should hookup selectors with functions', function () {
view = createView();
expect(view.events['click .js-button']).toEqual('_showByValueDialog');
expect(view.events['click .js-back']).toEqual('_onClickBack');
});
});
});
@@ -0,0 +1,67 @@
var Backbone = require('backbone');
var SizeFixedView = require('builder/components/form-components/editors/size/size-fixed-view');
describe('components/form-components/editors/size/size-fixed-view', function () {
var sizeFixedView;
function createView (options) {
sizeFixedView = new SizeFixedView({
model: new Backbone.Model({
fixed: 5
}),
min: 1,
max: 15,
step: 2
});
}
beforeEach(function () {
createView();
});
afterEach(function () {
sizeFixedView.clean();
});
it('renders with the expected schema', function () {
sizeFixedView.render();
// Schema
var schema = sizeFixedView._formModel.schema.value;
expect(schema).toBeDefined();
expect(schema.type).toEqual('Number');
expect(schema.title).toEqual('');
expect(schema.validators.length).toBe(2);
expect(schema.validators[0]).toEqual('required');
expect(schema.validators[1]).toEqual(jasmine.objectContaining({
type: 'interval',
min: 1,
max: 15,
step: 2
}));
// Render
expect(sizeFixedView.$('form').length).toBe(1);
var input = sizeFixedView.$('.js-input');
expect(input[0].value).toEqual('5');
});
it('change binding sets model and commit form', function () {
sizeFixedView.render();
var $input = sizeFixedView.$('.js-input').first();
$input.val(10);
sizeFixedView._formView.trigger('change');
expect(sizeFixedView.model.get('fixed')).toEqual(10);
});
it('clean removes form', function () {
sizeFixedView.render();
expect(sizeFixedView.$('form').length).toBe(1);
sizeFixedView.clean();
expect(sizeFixedView.$('form').length).toBe(0);
});
});
@@ -0,0 +1,95 @@
var Backbone = require('backbone');
var SizeByValueView = require('builder/components/form-components/editors/size/size-by-value-view');
describe('/components/form-components/editors/size/size', function () {
var size;
function createSize (opts) {
opts = opts || {};
var modelOptions = {};
if (opts.fillSize) {
modelOptions.fillSize = {
fixed: opts.fillSize
};
}
var options = {
model: new Backbone.Model(modelOptions),
key: 'fillSize',
schema: {
validators: [ 'required' ],
editorAttrs: {
geometryName: 'point',
hidePanes: []
}
}
};
if (opts.hidePanes) {
options.schema.editorAttrs.hidePanes = opts.hidePanes;
}
if (opts.columns) {
options.schema.options = opts.columns;
}
return new Backbone.Form.editors.Size(options);
}
describe('render', function () {
afterEach(function () {
size.remove();
});
it('both fixed and value if no options passed about it', function () {
size = createSize();
expect(size.$('.js-menu').children().length).toBe(2);
var labels = size.$('.js-menu > li label');
expect(labels.length).toBe(2);
expect(labels[0].textContent.trim()).toContain('form-components.editors.fill.input-number.fixed');
expect(labels[1].textContent.trim()).toContain('form-components.editors.fill.input-number.by-value');
});
it('only fixed if hidePanes set with `value`', function () {
size = createSize({
hidePanes: ['value'],
fillSize: 7
});
// Menu
expect(size.$('.js-menu').children().length).toBe(1);
var labels = size.$('.js-menu > li label');
expect(labels.length).toBe(1);
expect(labels[0].textContent.trim()).toContain('form-components.editors.fill.input-number.fixed');
// Form content
expect(size.$('.js-content form').length).toBe(1);
expect(size.$('.js-content form .js-input').val()).toEqual('7');
});
describe('by value', function () {
beforeEach(function () {
spyOn(SizeByValueView.prototype, 'initialize');
spyOn(SizeByValueView.prototype, 'removeDialog');
spyOn(SizeByValueView.prototype, 'removePopupManager');
spyOn(SizeByValueView.prototype, '_showByValueDialog');
spyOn(SizeByValueView.prototype, 'render').and.returnValue('<div class="fake-by-value"></div>');
});
it('only by value if hidePanes set with `fixed`', function () {
size = createSize({
hidePanes: ['fixed']
});
// Menu
expect(size.$('.js-menu').children().length).toBe(1);
var labels = size.$('.js-menu > li label');
expect(labels.length).toBe(1);
expect(labels[0].textContent.trim()).toContain('form-components.editors.fill.input-number.by-value');
// Form content
expect(SizeByValueView.prototype.render).toHaveBeenCalled();
size.remove();
});
});
});
});
@@ -0,0 +1,169 @@
var $ = require('jquery');
var _ = require('underscore');
var Backbone = require('backbone');
describe('components/form-components/editors/slider', function () {
var labels = ['Huckepack', 'Naseweis', 'Packe', 'Pick', 'Puck', 'Purzelbaum', 'Rumpelbold'];
var values = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];
var createViewFn = function (options) {
var defaultOptions = {
labels: labels,
schema: {}
};
var view = new Backbone.Form.editors.Slider(_.extend(defaultOptions, options));
view.render();
return view;
};
beforeEach(function () {
this.view = createViewFn();
this.viewWithValues = createViewFn({
values: values,
value: 'f'
});
this.view.render();
this.viewWithValues.render();
});
describe('render', function () {
it('should render properly', function () {
expect(this.view.$('.js-slider').length).toBe(1);
expect(this.view.$('.js-tick').length).toBe(labels.length);
expect(this.view.$('.js-label').text()).toBe('Huckepack');
expect($(this.view.$('.js-tick').get(0)).hasClass('is-highlighted')).toBeTruthy();
expect(this.viewWithValues.$('.js-slider').length).toBe(1);
expect(this.viewWithValues.$('.js-tick').length).toBe(labels.length);
expect(this.viewWithValues.$('.js-label').text()).toBe('Purzelbaum');
expect($(this.viewWithValues.$('.js-tick').get(5)).hasClass('is-highlighted')).toBeTruthy();
});
it('should display neither the ticks nor the slider when there is only one value', function (done) {
var self = this;
this.view._values = ['1'];
document.body.appendChild(this.view.el);
this.view.render();
setTimeout(function () {
expect(self.view.$('.js-slider').css('display')).toBe('none');
expect(self.view.$('.js-ticks').css('display')).toBe('none');
done();
}, 0);
});
});
describe('data', function () {
it('should get a value by default', function () {
expect(this.view.$('.js-label').text()).toBe('Huckepack');
expect(this.viewWithValues.$('.js-label').text()).toBe('Purzelbaum');
});
describe('change value', function () {
beforeEach(function () {
this.onChanged = jasmine.createSpy('onChanged');
this.view.bind('change', this.onChanged);
this.viewWithValues.bind('change', this.onChanged);
});
describe('when slider changes', function () {
beforeEach(function () {
var $slider = this.view.$('.js-slider');
$slider.val(4).change();
var $sliderWithValues = this.viewWithValues.$('.js-slider');
$sliderWithValues.val(4).change();
});
it('should trigger change', function () {
expect(this.onChanged).toHaveBeenCalled();
});
it('should update label', function () {
expect(this.view.$('.js-label').text()).toBe('Puck');
expect(this.viewWithValues.$('.js-label').text()).toBe('Puck');
});
it('should highlight tick', function () {
expect($(this.view.$('.js-tick').get(4)).hasClass('is-highlighted')).toBeTruthy();
expect($(this.viewWithValues.$('.js-tick').get(4)).hasClass('is-highlighted')).toBeTruthy();
});
it('should return value', function () {
expect(this.view.getValue()).toBe(4);
expect(this.viewWithValues.getValue()).toBe('e');
});
});
});
describe('initial selection', function () {
it('initial value', function () {
this.view = createViewFn({
values: [1, 2, 3, 4],
labels: ['a', 'b', 'c', 'd'],
schema: {},
value: 2
});
expect(this.view.getValue()).toBe(2);
});
it('should start selecting the lowest value by default', function () {
this.view = createViewFn({
values: [1, 2, 3, 4],
labels: ['a', 'b', 'c', 'd'],
schema: {}
});
expect(this.view.getValue()).toBe(1);
});
it('should accept option to start selecting the highest value', function () {
this.view = createViewFn({
values: [1, 2, 3, 4],
labels: ['a', 'b', 'c', 'd'],
initial: 'highest',
schema: {}
});
expect(this.view.getValue()).toBe(4);
});
});
describe('exceptions', function () {
it('should throw exception when the values and labels differ', function () {
var wrapper = function () {
createViewFn({
values: [1, 2, 3, 4],
labels: ['a', 'b'],
schema: {}
});
};
expect(wrapper).toThrow();
});
it('should throw exception when there are no labels', function () {
var wrapper = function () {
createViewFn({
values: [1, 2, 3, 4],
schema: {}
});
};
expect(wrapper).toThrow();
});
});
it('should destroy horizontal slider when element is removed', function () {
spyOn(this.view, '_destroySlider');
this.view.remove();
expect(this.view._destroySlider).toHaveBeenCalled();
});
});
afterEach(function () {
this.view.remove();
this.viewWithValues.remove();
});
});
@@ -0,0 +1,154 @@
var $ = require('jquery');
var Backbone = require('backbone');
var dispatchDocumentEvent = function (type, opts) {
var e = document.createEvent('HTMLEvents');
e.initEvent(type, false, true);
if (opts.which) {
e.which = opts.which;
}
document.dispatchEvent(e, opts);
};
describe('components/form-components/editors/suggest', function () {
beforeEach(function () {
this.model = new Backbone.Model({
names: 'carlos'
});
this.view = new Backbone.Form.editors.Suggest({
key: 'names',
schema: {
options: []
},
model: this.model,
editorAttrs: {
showSearch: true,
allowFreeTextInput: true,
collectionData: ['pepe', 'paco', 'juan']
}
});
this.view.render();
this.listView = this.view._listView;
});
describe('when there are values not null', function () {
it('should render properly', function () {
expect(this.view.$('.js-button').length).toBe(1);
expect(this.view.$('.js-button').text()).toContain('carlos');
});
it('should disable the component if option is true', function () {
this.view.options.disabled = true;
this.view.render();
expect(this.view.$('.js-button').hasClass('is-disabled')).toBeTruthy();
});
it('should add is-empty class if null value is selected', function () {
this.model.set('names', '');
this.view.collection.removeSelected();
this.view.render();
expect(this.view.$('.js-button').hasClass('is-empty')).toBeTruthy();
});
});
describe('when all column row values are null but selected value is not null', function () {
// ColumnRowData only fetches 40 rows
beforeEach(function () {
this.model = new Backbone.Model({
names: 'carlos'
});
this.view = new Backbone.Form.editors.Suggest({
key: 'names',
schema: {
options: []
},
model: this.model,
editorAttrs: {
showSearch: true,
allowFreeTextInput: true,
collectionData: [null, null, null]
}
});
this.view.render();
this.listView = this.view._listView;
});
it('should render properly', function () {
expect(this.view.$('.js-button').length).toBe(1);
expect(this.view.$('.js-button').text()).toContain('carlos');
});
it('should add is-empty class if null value is selected', function () {
this.model.set('names', '');
this.view.collection.removeSelected();
this.view.render();
expect(this.view.$('.js-button').hasClass('is-empty')).toBeTruthy();
});
});
describe('when all column row values are null', function () {
// TODO: replace Text editor
});
describe('bindings', function () {
beforeEach(function () {
spyOn(this.listView, 'hide');
});
it('should close list view if ESC is pressed', function () {
dispatchDocumentEvent('keydown', { which: 27 });
expect(this.listView.hide).toHaveBeenCalled();
});
it('should close list view if user clicks out the select', function () {
dispatchDocumentEvent('click', { target: 'body' });
expect(this.listView.hide).toHaveBeenCalled();
});
});
describe('on ENTER pressed', function () {
beforeEach(function () {
spyOn(this.listView, 'toggle');
this._event = $.Event('keydown');
this._event.which = 13;
});
it('should open custom list', function () {
this.view.$('.js-button').trigger(this._event);
expect(this.listView.toggle).toHaveBeenCalled();
});
it('should not open custom list if it is already visible', function () {
this.listView.show();
this.view.$('.js-button').trigger(this._event);
expect(this.listView.toggle).not.toHaveBeenCalled();
});
});
it('should change button value and hide list when a new item is selected', function () {
spyOn(this.listView, 'hide');
var mdl = this.view.collection.where({ val: 'juan' });
mdl[0].set('selected', true);
expect(this.view.$('.js-button').text()).toContain('juan');
expect(this.view.$('.js-button').hasClass('is-empty')).toBeFalsy();
expect(this.listView.hide).toHaveBeenCalled();
});
it('should open list view if "button" is clicked', function () {
spyOn(this.listView, 'toggle');
this.view.$('.js-button').trigger('click');
expect(this.listView.toggle).toHaveBeenCalled();
});
it('should destroy custom list when element is removed', function () {
spyOn(this.view._listView, 'clean');
this.view.remove();
expect(this.view._listView.clean).toHaveBeenCalled();
});
afterEach(function () {
this.view.remove();
});
});
@@ -0,0 +1,54 @@
var Backbone = require('backbone');
describe('components/form-components/editors/taglist', function () {
beforeEach(function () {
this.view = new Backbone.Form.editors.Taglist({
key: 'foo',
schema: {
options: {
tags: ['foo', 'bar', 'lol'],
isEditable: true
}
}
});
this.view.render();
this.view.$el.appendTo(document.body);
});
afterEach(function () {
var parent = this.view.el.parentNode;
parent && parent.removeChild(this.view.el);
this.view.remove();
});
it('should render properly', function () {
expect(this.view.$('.tagit-choice').length).toBe(3);
expect(this.view.$('.tagit-new').length).toBe(1);
expect(this.view.$('.tagit-choice').eq(0).text()).toContain('foo');
expect(this.view.$('.tagit-choice').eq(1).text()).toContain('bar');
expect(this.view.$('.tagit-choice').eq(2).text()).toContain('lol');
});
it('should setValue', function () {
this.view.setValue(['vamos', 'neno']);
expect(this.view.$('.tagit-choice').length).toBe(2);
expect(this.view.$('.tagit-choice').eq(0).text()).toContain('vamos');
expect(this.view.$('.tagit-choice').eq(1).text()).toContain('neno');
});
it('should getValue', function () {
this.view.setValue(['vamos', 'neno']);
expect(this.view.getValue().length).toBe(2);
});
it('should blur and focus properly', function () {
this.view.$('.tagit-new input').trigger('focus');
expect(this.view.$el.hasClass('is-focus')).toBe(true);
this.view.$('.tagit-new input').trigger('blur');
expect(this.view.$el.hasClass('is-focus')).toBe(false);
});
it('should not have any leaks', function () {
expect(this.view).toHaveNoLeaks();
});
});
@@ -0,0 +1,143 @@
var _ = require('underscore');
var Backbone = require('backbone');
describe('components/form-components/editors/text', function () {
var createViewFn = function (options) {
var defaultOptions = {
schema: {}
};
var view = new Backbone.Form.editors.Text(_.extend(defaultOptions, options));
view.render();
return view;
};
it('should render properly', function () {
var view = createViewFn();
expect(view.$el.attr('type')).toBe('text');
view.remove();
});
it('should be possible to create another text type', function () {
var view = createViewFn({
schema: {
editorAttrs: {
type: 'email'
}
}
});
expect(view.$el.attr('type')).toBe('email');
view.remove();
});
it('should return the value', function () {
var view = createViewFn({
value: 'Hello',
schema: {}
});
expect(view.options.value).toBe('Hello');
view.render();
expect(view.getValue()).toBe('Hello');
view.remove();
});
describe('change value', function () {
beforeEach(function () {
this.view = createViewFn();
this.onChanged = jasmine.createSpy('onChanged');
this.view.bind('change', this.onChanged);
});
describe('when input changes', function () {
beforeEach(function () {
this.view.$el
.val(6)
.trigger('keyup');
});
it('should trigger change', function () {
expect(this.onChanged).toHaveBeenCalled();
});
it('should update input', function () {
expect(this.view.$el.val()).toBe('6');
});
});
afterEach(function () {
this.view.remove();
});
});
it('should render custom placeholder if provided', function () {
var view = createViewFn({
placeholder: 'wadus'
});
expect(view.$el.prop('placeholder')).toContain('wadus');
view.remove();
});
it('should be disabled if provided', function () {
var view = createViewFn({
disabled: true
});
expect(view.$el.prop('readonly')).toBe(true);
expect(view.$el.hasClass('is-disabled')).toBe(true);
view.remove();
});
it('should destroy custom list, and tooltip when element is removed', function () {
var view = createViewFn();
spyOn(view, '_removeTooltip');
view.remove();
expect(view._removeTooltip).toHaveBeenCalled();
});
describe('with help', function () {
var view;
beforeEach(function () {
view = createViewFn({
editorAttrs: {
help: 'help'
}
});
});
describe('.render', function () {
it('should render properly', function () {
view.render();
expect(view._help).toEqual('help');
expect(view._helpTooltip).toBeDefined();
});
});
describe('._removeTooltip', function () {
it('should destroy tooltip', function () {
spyOn(view._helpTooltip, 'clean');
view._removeTooltip();
expect(view._helpTooltip.clean).toHaveBeenCalled();
});
});
});
it('should not have leaks', function () {
var view = createViewFn();
expect(view).toHaveNoLeaks();
});
});
@@ -0,0 +1,78 @@
var _ = require('underscore');
var Backbone = require('backbone');
describe('components/form-components/editors/textarea', function () {
var createViewFn = function (options) {
var model = new Backbone.Model({
street_address_column: ''
});
var defaultOptions = {
schema: {},
model: model,
key: 'street_address_column'
};
var view = new Backbone.Form.editors.TextArea(_.extend(defaultOptions, options));
view.render();
return view;
};
beforeEach(function () {
this.createView = createViewFn.bind(this);
});
it('set key variable', function () {
var view = this.createView();
expect(view.key).toBe('street_address_column');
view.remove();
});
it('should render properly', function () {
var view = this.createView();
expect(view.$el.prop('tagName').toLowerCase()).toBe('textarea');
view.remove();
});
it('should return the value', function () {
var model = new Backbone.Model({
street_address_column: 'Hello'
});
var view = this.createView({
model: model
});
expect(view.getValue()).toBe('Hello');
view.remove();
});
describe('change value', function () {
beforeEach(function () {
this.view = this.createView();
this.onChanged = jasmine.createSpy('onChanged');
this.view.bind('change', this.onChanged);
});
describe('when input changes', function () {
beforeEach(function () {
this.view.$el
.val(6)
.trigger('keyup');
});
it('should trigger change', function () {
expect(this.onChanged).toHaveBeenCalled();
});
it('should update input', function () {
expect(this.view.$el.val()).toBe('6');
});
});
afterEach(function () {
this.view.remove();
});
});
});
@@ -0,0 +1,59 @@
var _ = require('underscore');
var $ = require('jquery');
var Backbone = require('backbone');
var OPTIONS = [{
type: 'normal',
label: 'normal',
selected: true
}, {
type: 'advance',
label: 'advance',
selected: false
}];
describe('components/form-components/editors/toggle', function () {
beforeEach(function () {
this.model = new Backbone.Model({ context: 'normal' });
this.form = new Backbone.Form({
model: this.model
});
this.view = new Backbone.Form.editors.Toggle({
key: 'context',
form: this.form,
schema: {
options: _.map(OPTIONS, function (d) {
return {
val: d.type,
label: d.label,
selected: d.selected
};
}, this)
}
});
this.view.render();
});
it('should render the toggle links for the options that are not selected', function () {
expect(this.view.$('label').length).toBe(1);
});
it('should render the radios', function () {
expect(this.view.$('input[type="radio"]').length).toBe(2);
expect($(this.view.$('input[type="radio"]').get(0)).val()).toBe('normal');
});
it('should return the right value', function () {
// trigger click in the radius despite it is hidden,
// actually you have to click the label in the UI
$(this.view.$('input[type="radio"]').get(1)).click();
expect(this.view.getValue()).toBe('advance');
});
afterEach(function () {
this.view.remove();
});
});
@@ -0,0 +1,170 @@
var _ = require('underscore');
var Backbone = require('backbone');
var editorsWithoutTrackClass = ['Base', 'Object', 'NestedModel'];
var editorsNotInCARTO = ['Checkbox', 'Checkboxes', 'Date'];
var DialogConstants = require('builder/components/form-components/_constants/_dialogs');
var OPTIONS_BY_TYPE = {
'EnablerEditor': {
editor: {
type: 'Text'
}
},
'Slider': {
labels: ['hello', 'hey']
},
'Size': {
schema: {
editorAttrs: {}
}
},
'Fill': {
model: new Backbone.Model({
names: 'pepe',
stroke: {
size: {
range: [1, 30],
attribute: 'the_geom',
quantification: 'Quantile'
},
color: {
bins: 5,
range: ['#FFFFFF', '#FABADA', '#00FF00', '#000000', '#999999'],
attribute: 'column1',
quantification: 'Jenks',
opacity: 0.5
}
}
}),
schema: {
configModel: {},
query: 'SELECT * from table',
options: [
{ label: 'column1', type: 'number' },
{ label: 'column2', type: 'number' },
{ label: 'column3', type: 'number' }
]
}
},
'FillColor': {
model: new Backbone.Model({
names: 'pepe',
key: 'color',
size: {
range: [1, 30],
attribute: 'the_geom',
quantification: 'Quantile',
editorAttrs: {
geometryName: 'point'
}
},
fillColor: {
bins: 5,
fixed: '#FABADA',
attribute: 'column1',
quantification: 'Jenks',
opacity: 0.5,
editorAttrs: {
geometryName: 'point'
}
},
help: {
color: {
colorAttributes: {}
}
}
}),
schema: {
configModel: {},
userModel: {},
editorAttrs: {},
modals: {},
dialogMode: DialogConstants.Mode.FLOAT,
query: 'SELECT * from table',
options: [
{ label: 'column1', type: 'number' },
{ label: 'column2', type: 'number' },
{ label: 'column3', type: 'number' }
]
}
},
'TagList': {
schema: {
options: {
tags: ['foo', 'bar', 'lol'],
isEditable: true
}
}
},
'DataObservatoryDropdown': {
measurementModel: {},
measurements: [],
filters: [],
configModel: new Backbone.Model({
base_url: '/u/foo',
user_name: 'foo',
sql_api_template: 'foo',
api_key: 'foo'
}),
nodeDefModel: {},
region: 'wadus'
},
'LazySelect': {
configModel: new Backbone.Model({
base_url: '/u/foo',
user_name: 'foo',
sql_api_template: 'foo',
api_key: 'foo'
}),
nodeDefModel: {
querySchemaModel: new Backbone.Model({
query: ''
})
},
column: 'foo',
model: new Backbone.Model({
foo: 'bar'
})
}
};
describe('components/form-components/editors/track-class', function () {
describe('trackingClass for', function () {
_.each(Backbone.Form.editors, function (_class, key) {
if (_.contains(editorsWithoutTrackClass, key) || _.contains(editorsNotInCARTO, key)) {
return false;
}
var options = _.extend(
{
key: 'color',
schema: {
options: []
},
model: new Backbone.Model({ color: 'a' })
},
OPTIONS_BY_TYPE[key] || {}
);
describe(key, function () {
it('should not add the class if it not is specified', function () {
var view = new _class(options);
expect(view.$el.hasClass('track-class-whatever')).toBeFalsy();
expect(view.options.trackingClass).toBeUndefined();
view.remove();
});
it('should add the class if it is specified', function () {
var view = new _class(
_.extend(options, {
trackingClass: 'track-class-whatever'
})
);
expect(view.$el.hasClass('track-class-whatever')).toBeTruthy();
view.remove();
});
});
});
});
});
@@ -0,0 +1,25 @@
var Backbone = require('backbone');
var ValidatorClass = require('builder/components/form-components/validators/column-type');
var Validator = ValidatorClass({
type: 'columnType',
columnsCollection: new Backbone.Collection([
{ name: 'cartodb_id', type: 'number' },
{ name: 'title', type: 'string' },
{ name: 'created_at', type: 'date' }
]),
columnType: 'number'
});
var error = { type: 'columnType', message: 'components.backbone-forms.column-type-error' };
describe('components/form-components/validators/column-type', function () {
it('returns an error if there is no column with that name or the column doesnt match the type', function () {
expect(Validator('this_column_does_not_exist')).toEqual(error);
expect(Validator('title')).toEqual(error);
});
it('returns undefined if the column matches the type', function () {
expect(Validator('cartodb_id')).toBe(undefined);
});
});
@@ -0,0 +1,83 @@
var $ = require('jquery');
var Backbone = require('backbone');
require('backbone-forms');
Backbone.$ = $;
require('builder/components/form-components/field.js');
describe('components/form-components/field', function () {
beforeEach(function () {
this.model = new Backbone.Model({
test: true
});
this.model.schema = {
test: {
type: 'Text'
}
};
this.form = new Backbone.Form({
model: this.model
});
this.view = this.form.fields.test;
});
describe('render', function () {
it('should add help tooltip when it is defined', function () {
spyOn(this.view, '_createTooltip').and.callThrough();
expect(this.view._helpTooltip).toBeUndefined();
this.view.schema.help = 'hello';
this.view.render();
expect(this.view._createTooltip).toHaveBeenCalled();
expect(this.view._helpTooltip).toBeDefined();
});
it('should add a custom class for the field', function () {
this.view.render();
expect(this.view.$el.hasClass('Editor-formInner--Text')).toBeTruthy();
});
});
describe('on error', function () {
beforeEach(function () {
spyOn(this.view, '_createTooltip').and.callThrough();
this.view.setError('oh error!');
spyOn(this.view._errorTooltip, 'hideTipsy').and.callThrough();
spyOn(this.view._errorTooltip, 'destroyTipsy').and.callThrough();
});
it('should add error tooltip', function () {
expect(this.view._createTooltip).toHaveBeenCalled();
expect(this.view._errorTooltip).toBeDefined();
});
it('should clean error tooltip when error is gone', function () {
this.view.clearError();
expect(this.view._errorTooltip.hideTipsy).toHaveBeenCalled();
expect(this.view._errorTooltip.destroyTipsy).toHaveBeenCalled();
});
afterEach(function () {
this.view.clearError();
});
});
it('should provide more info with templateData function', function () {
var templateData = this.view.templateData();
expect('hasNestedForm' in templateData).toBeDefined();
});
describe('remove', function () {
it('should delete tooltip views', function () {
spyOn(this.view, '_destroyHelpTooltip');
spyOn(this.view, '_destroyErrorTooltip');
this.view.remove();
expect(this.view._destroyHelpTooltip).toHaveBeenCalled();
expect(this.view._destroyErrorTooltip).toHaveBeenCalled();
});
});
afterEach(function () {
this.form.remove();
});
});