Initial commit
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
var Backbone = require('backbone');
|
||||
var ApplyButtonView = require('builder/components/apply-button/apply-button-view');
|
||||
var ApplyButtonTemplate = require('builder/components/apply-button/apply-button.tpl');
|
||||
|
||||
describe('components/apply-button-view', function () {
|
||||
var view, overlayModel, onApplyClick;
|
||||
|
||||
var createViewFn = function (options) {
|
||||
overlayModel = new Backbone.Model({
|
||||
visible: options.visible
|
||||
});
|
||||
|
||||
onApplyClick = jasmine.createSpy();
|
||||
|
||||
var view = new ApplyButtonView({
|
||||
onApplyClick: onApplyClick,
|
||||
overlayModel: overlayModel
|
||||
});
|
||||
|
||||
spyOn(view, '_onClick').and.callThrough();
|
||||
|
||||
return view;
|
||||
};
|
||||
|
||||
beforeEach(function () {
|
||||
view = createViewFn({
|
||||
visible: false
|
||||
});
|
||||
view.render();
|
||||
});
|
||||
|
||||
describe('.render', function () {
|
||||
it('should have no leaks', function () {
|
||||
expect(view).toHaveNoLeaks();
|
||||
});
|
||||
|
||||
it('should render apply button', function () {
|
||||
expect(view.$el.html()).toBe(ApplyButtonTemplate({ disabled: overlayModel.get('visible') }));
|
||||
});
|
||||
});
|
||||
|
||||
describe('._initBinds', function () {
|
||||
it('should listen to _overlayModel:visible and call .render()', function () {
|
||||
spyOn(view, 'render');
|
||||
|
||||
view._initBinds();
|
||||
overlayModel.trigger('change:visible');
|
||||
|
||||
expect(view.render).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('._onClick', function () {
|
||||
beforeEach(function () {
|
||||
onApplyClick.calls.reset();
|
||||
});
|
||||
|
||||
it('should execute callback if not disabled', function () {
|
||||
view = createViewFn({
|
||||
visible: false
|
||||
});
|
||||
|
||||
view._onClick();
|
||||
|
||||
expect(onApplyClick).toHaveBeenCalled();
|
||||
expect(view._onClick).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not execute callback if disabled', function () {
|
||||
view = createViewFn({
|
||||
visible: true
|
||||
});
|
||||
|
||||
view._onClick();
|
||||
|
||||
expect(view._onClick).toHaveBeenCalled();
|
||||
expect(onApplyClick).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
var UserModel = require('builder/data/user-model');
|
||||
var ConfigModel = require('builder/data/config-model');
|
||||
var ImportsModel = require('builder/data/background-importer/imports-model');
|
||||
var BackgroundImportItemView = require('builder/components/background-importer/background-import-item-view');
|
||||
var FactoryModals = require('../../factories/modals');
|
||||
|
||||
describe('editor/components/background-importer/background-import-item', function () {
|
||||
beforeEach(function () {
|
||||
this.userModel = new UserModel({
|
||||
username: 'pepe',
|
||||
actions: {
|
||||
private_tables: true
|
||||
}
|
||||
}, {
|
||||
configModel: 'c'
|
||||
});
|
||||
|
||||
this.configModel = new ConfigModel({
|
||||
base_url: '/u/pepe'
|
||||
});
|
||||
|
||||
this.model = new ImportsModel({}, {
|
||||
userModel: this.userModel,
|
||||
configModel: this.configModel
|
||||
});
|
||||
|
||||
spyOn(this.model, 'bind').and.callThrough();
|
||||
spyOn(BackgroundImportItemView.prototype, 'updateNotification').and.callThrough();
|
||||
spyOn(BackgroundImportItemView.prototype, 'clean').and.callThrough();
|
||||
|
||||
this.importerView = new BackgroundImportItemView({
|
||||
modals: FactoryModals.createModalService(),
|
||||
createVis: false,
|
||||
importModel: this.model,
|
||||
userModel: this.userModel,
|
||||
configModel: this.configModel
|
||||
});
|
||||
|
||||
spyOn(this.importerView, '_getStatus').and.returnValue('success');
|
||||
});
|
||||
|
||||
it('should create notification properly', function () {
|
||||
expect(this.importerView._notification).toBeDefined();
|
||||
});
|
||||
|
||||
it('should bind model changes', function () {
|
||||
this.model.set('state', 'failed');
|
||||
expect(BackgroundImportItemView.prototype.updateNotification).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should stop upload and remove it when upload is aborted', function () {
|
||||
this.model.set('state', 'uploading');
|
||||
this.importerView._notification.trigger('notification:close');
|
||||
expect(BackgroundImportItemView.prototype.clean).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should show display_name when it is available from import model', function () {
|
||||
this.model._importModel.set({ item_queue_id: 'hello-id', type: '' });
|
||||
this.model.set('state', 'importing');
|
||||
expect(this.importerView._notification.get('info')).toContain('hello-id');
|
||||
this.model._importModel.set('display_name', 'table_name_test');
|
||||
this.model.set('state', 'geocoding');
|
||||
expect(this.importerView._notification.get('info')).toContain('table_name_test');
|
||||
expect(this.importerView._notification.get('info')).not.toContain('hello-id');
|
||||
});
|
||||
});
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
var Backbone = require('backbone');
|
||||
var cdb = require('internal-carto.js');
|
||||
var _ = require('underscore');
|
||||
var ImportsModel = require('builder/data/background-importer/imports-model');
|
||||
var BackgroundImporter = require('builder/components/background-importer/background-importer');
|
||||
var BackgroundPollingModel = require('builder/data/background-importer/background-polling-model');
|
||||
var ImportsCollection = require('builder/data/background-importer/background-importer-imports-collection');
|
||||
var UserModel = require('builder/data/user-model');
|
||||
var ConfigModel = require('builder/data/config-model');
|
||||
var FactoryModals = require('../../factories/modals');
|
||||
|
||||
describe('editor/components/background-importer/background-importer', function () {
|
||||
beforeEach(function () {
|
||||
this.userModel = new UserModel({
|
||||
username: 'pepe',
|
||||
actions: {
|
||||
private_tables: true
|
||||
}
|
||||
}, {
|
||||
configModel: 'c'
|
||||
});
|
||||
|
||||
this.configModel = new ConfigModel({
|
||||
base_url: '/u/pepe'
|
||||
});
|
||||
|
||||
cdb.god = new Backbone.Model();
|
||||
spyOn(cdb.god, 'bind').and.callThrough();
|
||||
|
||||
this.importsCollection = new ImportsCollection(undefined, {
|
||||
userModel: this.userModel,
|
||||
configModel: this.configModel
|
||||
});
|
||||
|
||||
this.model = new BackgroundPollingModel({}, {
|
||||
vis: {},
|
||||
userModel: this.userModel,
|
||||
configModel: this.configModel,
|
||||
importsCollection: this.importsCollection
|
||||
});
|
||||
|
||||
this.importer = BackgroundImporter.init({
|
||||
modals: FactoryModals.createModalService(),
|
||||
pollingModel: this.model,
|
||||
createVis: {},
|
||||
userModel: this.userModel,
|
||||
configModel: this.configModel
|
||||
});
|
||||
});
|
||||
|
||||
it('should add importers properly', function () {
|
||||
var mdl = new ImportsModel({}, {
|
||||
userModel: this.userModel,
|
||||
configModel: {}
|
||||
});
|
||||
|
||||
this.model.addImportItem(mdl);
|
||||
expect(_.keys(this.importer._importers).length).toBe(1);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,50 @@
|
||||
var _ = require('underscore');
|
||||
var CarouselFormView = require('builder/components/carousel-form-view');
|
||||
var CustomCarouselCollection = require('builder/components/custom-carousel/custom-carousel-collection');
|
||||
|
||||
describe('components/carousel-form-view', function () {
|
||||
beforeEach(function () {
|
||||
this.collection = new CustomCarouselCollection([
|
||||
{ val: 'hello', selected: true },
|
||||
{ val: 'howdy' },
|
||||
{ val: 'hi' }
|
||||
]);
|
||||
this.view = new CarouselFormView({
|
||||
collection: this.collection,
|
||||
template: _.template('<div class="js-highlight"><%- name %></div><div class="js-selector"></div>')
|
||||
});
|
||||
|
||||
this.view.render();
|
||||
});
|
||||
|
||||
describe('render', function () {
|
||||
it('should render properly', function () {
|
||||
expect(this.view.$('.Carousel').length).toBe(1);
|
||||
});
|
||||
|
||||
it('should allow to add a className', function () {
|
||||
var view = new CarouselFormView({
|
||||
collection: this.collection,
|
||||
template: _.template('<div class="js-highlight"><%- name %></div><div class="js-selector"></div>'),
|
||||
itemOptions: {
|
||||
className: 'MyFabolousClassName'
|
||||
}
|
||||
});
|
||||
|
||||
view.render();
|
||||
expect(view.$('button').hasClass('MyFabolousClassName')).toBeTruthy();
|
||||
view.clean();
|
||||
});
|
||||
|
||||
it('should require js-selector class', function () {
|
||||
this.view.template = _.template('<div></div>');
|
||||
expect(this.view.render).toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
it('should update selector when item is highlighted if element exists', function () {
|
||||
expect(this.view.$('.js-highlight').text()).toBe('hello');
|
||||
this.collection.at(2).set('highlighted', true);
|
||||
expect(this.view.$('.js-highlight').text()).toBe('hi');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,228 @@
|
||||
var _ = require('underscore');
|
||||
var Backbone = require('backbone');
|
||||
var CodeMirror = require('codemirror');
|
||||
var CodeMirrorView = require('builder/components/code-mirror/code-mirror-view');
|
||||
var DATA_SERVICES = require('builder/components/code-mirror/data-services.js');
|
||||
var SPACE_KEYCODE = 32;
|
||||
|
||||
var Pos = CodeMirror.Pos;
|
||||
|
||||
// fakeCodeMirrorKey(this.view.editor, "U", {shiftKey: true, ctrlKey: true, altKey: true});
|
||||
// fakeCodeMirrorKey(this.view.editor, 32, {ctrlKey: true});
|
||||
function fakeCodeMirrorKey (cm, type, code, props) {
|
||||
if (typeof code === 'string') code = code.charCodeAt(0);
|
||||
var e = {type: type, keyCode: code, preventDefault: function () {}, stopPropagation: function () {}};
|
||||
if (props) for (var n in props) e[n] = props[n];
|
||||
if (type === 'keydown') {
|
||||
cm.triggerOnKeyDown(e);
|
||||
}
|
||||
if (type === 'keyup') {
|
||||
cm.triggerOnKeyUp(e);
|
||||
}
|
||||
if (type === 'keypress') {
|
||||
cm.triggerOnKeyPress(e);
|
||||
}
|
||||
}
|
||||
|
||||
describe('components/code-mirror/code-mirror-view', function () {
|
||||
var createViewFn = function (options) {
|
||||
this.model = new Backbone.Model({
|
||||
content: 'Foo',
|
||||
readonly: false
|
||||
});
|
||||
|
||||
var sqlKeywords = 'alter and as asc between by count create delete desc distinct drop from group having in insert into is join like not on or order select set table union update values where limit';
|
||||
|
||||
this.hints = sqlKeywords.split(' ').map(function (item) {
|
||||
return {
|
||||
text: item
|
||||
};
|
||||
});
|
||||
|
||||
var defaultOptions = {
|
||||
model: this.model,
|
||||
hints: this.hints,
|
||||
addons: ['color-picker'],
|
||||
mode: 'text/x-pgsql',
|
||||
tips: [
|
||||
_t('editor.data.code-mirror.tip')
|
||||
],
|
||||
placeholder: 'placeholder'
|
||||
};
|
||||
|
||||
this.view = new CodeMirrorView(_.extend(defaultOptions, options));
|
||||
spyOn(this.view, '_showAutocomplete');
|
||||
spyOn(this.view, '_toggleReadOnly').and.callThrough();
|
||||
|
||||
this.view.render();
|
||||
|
||||
document.body.appendChild(this.view.el);
|
||||
};
|
||||
|
||||
beforeEach(function () {
|
||||
this.createView = createViewFn.bind(this);
|
||||
|
||||
jasmine.clock().install();
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
jasmine.clock().uninstall();
|
||||
});
|
||||
|
||||
it('should render properly', function () {
|
||||
this.createView();
|
||||
|
||||
expect(this.view.$('.CodeMirror-editor').length).toBe(1);
|
||||
expect(this.view.$('.CodeMirror-console').length).toBe(1);
|
||||
expect(this.view.$('.js-editor').html()).toContain('Foo');
|
||||
expect(this.view.$('.js-console').html()).toContain('editor.data.code-mirror.tip');
|
||||
});
|
||||
|
||||
it('should bind change:content properly', function () {
|
||||
this.createView();
|
||||
spyOn(this.view, 'setContent').and.callThrough();
|
||||
|
||||
this.model.set('content', 'Bar');
|
||||
|
||||
expect(this.view.setContent).toHaveBeenCalledWith('Bar');
|
||||
});
|
||||
|
||||
it('should bind change:readonly properly', function () {
|
||||
this.createView();
|
||||
|
||||
this.model.set('readonly', true);
|
||||
|
||||
expect(this.view._toggleReadOnly).toHaveBeenCalled();
|
||||
expect(this.view.$('.js-console').attr('style')).toContain('display: none');
|
||||
expect(this.view.editor.getOption('theme')).toBe('');
|
||||
expect(this.view.editor.getOption('readOnly')).toBe(true);
|
||||
});
|
||||
|
||||
it('should show autocomplete', function () {
|
||||
this.createView();
|
||||
|
||||
this.view.editor.setValue('se');
|
||||
fakeCodeMirrorKey(this.view.editor, 'keyup', 'l');
|
||||
this.view.editor.setCursor(Pos(0, 2));
|
||||
jasmine.clock().tick(200);
|
||||
|
||||
expect(this.view._showAutocomplete).not.toHaveBeenCalled();
|
||||
|
||||
this.view.editor.setValue('sel');
|
||||
fakeCodeMirrorKey(this.view.editor, 'keyup', 'e');
|
||||
this.view.editor.setCursor(Pos(0, 3));
|
||||
jasmine.clock().tick(200);
|
||||
|
||||
expect(this.view._showAutocomplete).toHaveBeenCalledWith(this.view.editor, {});
|
||||
});
|
||||
|
||||
it('should show autocomplete on demand', function () {
|
||||
this.createView();
|
||||
|
||||
this.view.editor.setValue('');
|
||||
fakeCodeMirrorKey(this.view.editor, 'keydown', SPACE_KEYCODE, { ctrlKey: true });
|
||||
|
||||
expect(this.view._showAutocomplete).toHaveBeenCalledWith(this.view.editor, {});
|
||||
});
|
||||
|
||||
describe('autocompleteChars', function () {
|
||||
it('should show autocomplete', function () {
|
||||
this.createView({
|
||||
autocompleteChars: 2
|
||||
});
|
||||
|
||||
this.view.editor.setValue('s');
|
||||
fakeCodeMirrorKey(this.view.editor, 'keyup', 'e');
|
||||
this.view.editor.setCursor(Pos(0, 1));
|
||||
jasmine.clock().tick(200);
|
||||
|
||||
expect(this.view._showAutocomplete).not.toHaveBeenCalled();
|
||||
|
||||
this.view.editor.setValue('se');
|
||||
fakeCodeMirrorKey(this.view.editor, 'keyup', 'l');
|
||||
this.view.editor.setCursor(Pos(0, 2));
|
||||
jasmine.clock().tick(200);
|
||||
|
||||
expect(this.view._showAutocomplete).toHaveBeenCalledWith(this.view.editor, {});
|
||||
});
|
||||
});
|
||||
|
||||
describe('autocompletePrefix', function () {
|
||||
beforeEach(function () {
|
||||
this.createView({
|
||||
autocompleteChars: 2,
|
||||
autocompletePrefix: '{{',
|
||||
mode: 'text/mustache'
|
||||
});
|
||||
});
|
||||
|
||||
describe('._showAutocomplete', function () {
|
||||
it('should show autocomplete', function () {
|
||||
this.view.editor.setValue('{');
|
||||
fakeCodeMirrorKey(this.view.editor, 'keyup', '{');
|
||||
this.view.editor.setCursor(Pos(0, 1));
|
||||
jasmine.clock().tick(200);
|
||||
|
||||
expect(this.view._showAutocomplete).not.toHaveBeenCalled();
|
||||
|
||||
this.view.editor.setValue('{{');
|
||||
fakeCodeMirrorKey(this.view.editor, 'keyup', 'c');
|
||||
this.view.editor.setCursor(Pos(0, 2));
|
||||
jasmine.clock().tick(200);
|
||||
|
||||
expect(this.view._showAutocomplete).toHaveBeenCalledWith(this.view.editor, {});
|
||||
});
|
||||
});
|
||||
|
||||
describe('._completeIfAfterCtrlSpace', function () {
|
||||
it('should show autocomplete on demand', function () {
|
||||
this.view.editor.setValue('');
|
||||
this.view.editor.setCursor(Pos(0, 0));
|
||||
|
||||
this.view._completeIfAfterCtrlSpace(this.view.editor);
|
||||
|
||||
expect(this.view._showAutocomplete).toHaveBeenCalledWith(this.view.editor, { autocompletePrefix: '{{' });
|
||||
|
||||
this.view.editor.setValue('{{');
|
||||
this.view.editor.setCursor(Pos(0, 2));
|
||||
|
||||
this.view._completeIfAfterCtrlSpace(this.view.editor);
|
||||
|
||||
expect(this.view._showAutocomplete).toHaveBeenCalledWith(this.view.editor, {});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Data Services warning', function () {
|
||||
beforeEach(function () {
|
||||
this.createView();
|
||||
});
|
||||
|
||||
it('should show the data services warning if any data services function is present in the editor content', function () {
|
||||
this.view.editor.setValue(DATA_SERVICES[0]);
|
||||
expect(this.view.$('.CodeMirror-warning').length).toBe(1);
|
||||
});
|
||||
|
||||
it('should hide the data services warning if the content changes', function () {
|
||||
this.view.editor.setValue(DATA_SERVICES[0]);
|
||||
expect(this.view.$('.CodeMirror-warning').length).toBe(1);
|
||||
|
||||
this.view.editor.setValue('empty');
|
||||
expect(this.view.$('.CodeMirror-warning').length).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
it('should show placeholder', function () {
|
||||
this.createView();
|
||||
|
||||
this.view.editor.setValue('');
|
||||
|
||||
expect(this.view.$('.CodeMirror-placeholder').html()).toContain('placeholder');
|
||||
});
|
||||
|
||||
it('should not have any leaks', function () {
|
||||
this.createView();
|
||||
|
||||
expect(this.view).toHaveNoLeaks();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,78 @@
|
||||
var _ = require('underscore');
|
||||
var CodeMirror = require('codemirror');
|
||||
require('builder/components/code-mirror/cartocss.code-mirror')(CodeMirror);
|
||||
var ColorpickerView = require('builder/components/code-mirror/colorpicker.code-mirror');
|
||||
var Pos = CodeMirror.Pos;
|
||||
|
||||
function fireMouseEvent (obj, evtName) {
|
||||
var event = document.createEvent('MouseEvents');
|
||||
event.initMouseEvent(evtName, true, true, window,
|
||||
0, 0, 0, 0, 0, false, false, false, false, 0, null);
|
||||
obj.dispatchEvent(event);
|
||||
}
|
||||
|
||||
describe('components/code-mirror/colorpicker.code-view', function () {
|
||||
beforeEach(function () {
|
||||
spyOn(_, 'debounce').and.callFake(function (func) {
|
||||
return function () {
|
||||
func.apply(this, arguments);
|
||||
};
|
||||
});
|
||||
|
||||
jasmine.clock().install();
|
||||
|
||||
this.editor = CodeMirror(document.body, {
|
||||
mode: 'cartocss',
|
||||
theme: 'material'
|
||||
});
|
||||
|
||||
this.view = new ColorpickerView({
|
||||
editor: this.editor
|
||||
});
|
||||
|
||||
spyOn(this.view, '_createPicker');
|
||||
|
||||
this.view.render();
|
||||
document.body.appendChild(this.view.el);
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
jasmine.clock().uninstall();
|
||||
|
||||
var el = this.editor.getWrapperElement();
|
||||
el.parentNode.removeChild(el);
|
||||
|
||||
var parent = this.view.el.parentNode;
|
||||
parent && parent.removeChild(this.view.el);
|
||||
this.view.clean();
|
||||
});
|
||||
|
||||
it('should update colors on editor update', function () {
|
||||
this.editor.setValue('#foo{marker-fill: #fabada;}');
|
||||
|
||||
expect(document.querySelector('.cm-color')).toBeTruthy();
|
||||
expect(document.querySelector('.cm-color').style.borderBottom).toBe('1px solid rgb(250, 186, 218)');
|
||||
});
|
||||
|
||||
it('should show colorpicker on click', function () {
|
||||
this.editor.setValue('#foo{marker-fill: #fabada;}');
|
||||
fireMouseEvent(this.editor.display.scroller, 'mousedown');
|
||||
// The cursor is put on top of the color artificially
|
||||
this.editor.setCursor(Pos(0, 21));
|
||||
jasmine.clock().tick(60);
|
||||
|
||||
expect(this.view._createPicker).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should update color', function () {
|
||||
this.editor.replaceRange('#fbdaaa', {line: 0, ch: 18}, {line: 0, ch: 22});
|
||||
jasmine.clock().tick(400);
|
||||
|
||||
expect(document.querySelector('.cm-color').textContent).toBe('#fbdaaa');
|
||||
expect(document.querySelector('.cm-color').style.borderBottom).toBe('1px solid rgb(251, 218, 170)');
|
||||
});
|
||||
|
||||
it('should not have any leaks', function () {
|
||||
expect(this.view).toHaveNoLeaks();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,176 @@
|
||||
var $ = require('jquery');
|
||||
var _ = require('underscore');
|
||||
var CustomListCollection = require('builder/components/custom-list/custom-list-collection');
|
||||
var ContextMenuView = require('builder/components/context-menu/context-menu-view');
|
||||
|
||||
var ESCAPE_KEY_CODE = 27;
|
||||
|
||||
var simulateEscapeKeyPress = function () {
|
||||
var e = $.Event('keydown');
|
||||
e.keyCode = e.which = ESCAPE_KEY_CODE;
|
||||
$(document).trigger(e);
|
||||
};
|
||||
|
||||
describe('components/context-menu/context-menu-view', function () {
|
||||
var view, collection, triggerElement, button;
|
||||
|
||||
var createViewFn = function () {
|
||||
collection = new CustomListCollection([
|
||||
{
|
||||
label: 'Label 1',
|
||||
val: 'value-1'
|
||||
}, {
|
||||
label: 'Label 2',
|
||||
val: 'value-2'
|
||||
}
|
||||
]);
|
||||
|
||||
triggerElement = $('<div id="something"></div>');
|
||||
button = $('<button class="js-toggle-menu"></button>');
|
||||
triggerElement.append(button);
|
||||
|
||||
$('body').append(triggerElement);
|
||||
|
||||
var view = new ContextMenuView({
|
||||
collection: collection,
|
||||
triggerElementID: triggerElement[0].id,
|
||||
position: {
|
||||
x: 300,
|
||||
y: 400
|
||||
},
|
||||
offset: {
|
||||
x: 100,
|
||||
y: 200
|
||||
}
|
||||
});
|
||||
|
||||
triggerElement.on('click', function (ev) {
|
||||
view.toggle();
|
||||
});
|
||||
|
||||
return view;
|
||||
};
|
||||
|
||||
beforeEach(function () {
|
||||
view = createViewFn();
|
||||
view.render();
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
var el = triggerElement.get(0);
|
||||
var parent = el.parentNode;
|
||||
parent && parent.removeChild(el);
|
||||
triggerElement.remove();
|
||||
view.clean();
|
||||
});
|
||||
|
||||
it('should render properly', function () {
|
||||
expect(_.size(view._subviews)).toBe(2);
|
||||
});
|
||||
|
||||
it('should render a list with the given items', function () {
|
||||
expect(view.$el.find('button[title="Label 1"]')).toBeDefined();
|
||||
expect(view.$el.find('button[title="Label 2"]')).toBeDefined();
|
||||
});
|
||||
|
||||
it('should be toggled when clicking on the triggerElement', function () {
|
||||
expect(view.$el.css('display')).toEqual('none');
|
||||
|
||||
triggerElement.click();
|
||||
expect(view.$el.css('display')).toEqual('block');
|
||||
|
||||
triggerElement.click();
|
||||
expect(view.$el.css('display')).toEqual('none');
|
||||
});
|
||||
|
||||
it('should be toggled when clicking on an element inside of the triggerElement', function () {
|
||||
expect(view.$el.css('display')).toEqual('none');
|
||||
|
||||
button.click();
|
||||
expect(view.$el.css('display')).toEqual('block');
|
||||
|
||||
button.click();
|
||||
expect(view.$el.css('display')).toEqual('none');
|
||||
});
|
||||
|
||||
it('should be hidden when clicking on the overlay', function () {
|
||||
triggerElement.click();
|
||||
|
||||
expect(view.$el.css('display')).toEqual('block');
|
||||
|
||||
$('.CDB-Box-modalOverlay').trigger('click');
|
||||
|
||||
spyOn(view, 'hide').and.callThrough();
|
||||
|
||||
expect(view.$el.css('display')).toEqual('none');
|
||||
});
|
||||
|
||||
it('should be hidden when hitting ESCAPE', function () {
|
||||
triggerElement.click();
|
||||
|
||||
expect(view.$el.css('display')).toEqual('block');
|
||||
|
||||
simulateEscapeKeyPress();
|
||||
|
||||
expect(view.$el.css('display')).toEqual('none');
|
||||
});
|
||||
|
||||
it('should be hidden when clicking on one of the items', function () {
|
||||
triggerElement.click();
|
||||
|
||||
expect(view.$el.css('display')).toEqual('block');
|
||||
expect(collection.at(0).get('selected')).toBe(false);
|
||||
expect(collection.at(1).get('selected')).toBe(false);
|
||||
|
||||
view.$el.find('button[title="Label 1"]').click();
|
||||
expect(collection.at(0).get('selected')).toBe(true);
|
||||
expect(collection.at(1).get('selected')).toBe(false);
|
||||
|
||||
expect(view.$el.css('display')).toEqual('none');
|
||||
});
|
||||
|
||||
it('should not try to hide the context menu when clicking somewhere else', function () {
|
||||
spyOn(view, 'hide');
|
||||
|
||||
$('.CDB-Box-modalOverlay').trigger('click');
|
||||
expect(view.hide).not.toHaveBeenCalled();
|
||||
|
||||
view.show();
|
||||
|
||||
$('.CDB-Box-modalOverlay').trigger('click');
|
||||
expect(view.hide).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not try to hide the context menu when ESC key is pressed', function () {
|
||||
spyOn(view, 'hide').and.callThrough();
|
||||
|
||||
simulateEscapeKeyPress();
|
||||
expect(view.hide).not.toHaveBeenCalled();
|
||||
|
||||
view.show();
|
||||
|
||||
simulateEscapeKeyPress();
|
||||
expect(view.hide).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
describe('.clean', function () {
|
||||
beforeEach(function () {
|
||||
view.show();
|
||||
});
|
||||
|
||||
it('should unbind ESC key', function () {
|
||||
spyOn(view, 'hide');
|
||||
|
||||
simulateEscapeKeyPress();
|
||||
|
||||
expect(view.hide).toHaveBeenCalled();
|
||||
view.hide.calls.reset();
|
||||
|
||||
view.clean();
|
||||
|
||||
simulateEscapeKeyPress();
|
||||
|
||||
expect(view.hide).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
var CustomCarouselItemModel = require('builder/components/custom-carousel/custom-carousel-item-model');
|
||||
var CustomCarouselCollection = require('builder/components/custom-carousel/custom-carousel-collection');
|
||||
|
||||
describe('components/custom-carousel/custom-carousel-collection', function () {
|
||||
beforeEach(function () {
|
||||
this.collection = new CustomCarouselCollection([
|
||||
new CustomCarouselItemModel({ val: 'hi' }),
|
||||
new CustomCarouselItemModel({ val: 'howdy' }),
|
||||
new CustomCarouselItemModel({ val: 'hello' })
|
||||
]);
|
||||
});
|
||||
|
||||
it('should remove previous selected item when a new one is chosen', function () {
|
||||
this.collection.at(1).set('selected', true);
|
||||
expect(this.collection.where({ selected: true }).length).toBe(1);
|
||||
this.collection.at(0).set('selected', true);
|
||||
expect(this.collection.where({ selected: true }).length).toBe(1);
|
||||
expect(this.collection.at(1).get('selected')).toBeFalsy();
|
||||
});
|
||||
});
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
var _ = require('underscore');
|
||||
var CustomCarouselItemModel = require('builder/components/custom-carousel/custom-carousel-item-model');
|
||||
var CustomCarouselItemView = require('builder/components/custom-carousel/custom-carousel-item-view');
|
||||
|
||||
describe('components/custom-carousel/custom-carousel-item-view', function () {
|
||||
beforeEach(function () {
|
||||
this.model = new CustomCarouselItemModel({
|
||||
val: 'hello'
|
||||
});
|
||||
|
||||
this.view = new CustomCarouselItemView({
|
||||
model: this.model
|
||||
});
|
||||
|
||||
this.view.render();
|
||||
});
|
||||
|
||||
it('should render properly', function () {
|
||||
expect(this.view.$('button').length).toBe(1);
|
||||
});
|
||||
|
||||
it('should allow to add a className', function () {
|
||||
var view = new CustomCarouselItemView({
|
||||
model: this.model,
|
||||
itemOptions: {
|
||||
className: 'MyFabolousClassName'
|
||||
}
|
||||
});
|
||||
|
||||
view.render();
|
||||
|
||||
expect(view.$('button').hasClass('MyFabolousClassName')).toBeTruthy();
|
||||
|
||||
view.clean();
|
||||
});
|
||||
|
||||
describe('hover', function () {
|
||||
beforeEach(function () {
|
||||
this.view.$el.trigger('mouseenter');
|
||||
});
|
||||
|
||||
it('should add class when it is hovered', function () {
|
||||
expect(this.model.get('highlighted')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should remove class when it is unhovered', function () {
|
||||
this.view.$el.trigger('mouseleave');
|
||||
expect(this.model.get('highlighted')).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('with tooltip', function () {
|
||||
describe('.render', function () {
|
||||
it('should render properly', function () {
|
||||
expect(this.model.set('tooltip', 'help'));
|
||||
|
||||
this.view.render();
|
||||
|
||||
expect(_.size(this.view._subviews)).toBe(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should set selected when it is clicked', function () {
|
||||
expect(this.model.get('selected')).toBeFalsy();
|
||||
this.view.$el.trigger('click');
|
||||
expect(this.model.get('selected')).toBeTruthy();
|
||||
expect(this.view.$el.hasClass('is-selected')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should not have any leaks', function () {
|
||||
expect(this.view).toHaveNoLeaks();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,76 @@
|
||||
var CustomCarouselView = require('builder/components/custom-carousel/custom-carousel-view');
|
||||
|
||||
describe('components/custom-carousel/custom-carousel-view', function () {
|
||||
beforeEach(function () {
|
||||
this.view = new CustomCarouselView({
|
||||
options: [
|
||||
{ val: 'hello', selected: true },
|
||||
{ val: 'howdy' },
|
||||
{ val: 'hi' }
|
||||
]
|
||||
});
|
||||
spyOn(this.view, '_bindScroll');
|
||||
spyOn(this.view, '_checkShadows');
|
||||
spyOn(this.view, '_checkScroll');
|
||||
jasmine.clock().install();
|
||||
this.view.render();
|
||||
this.view.initScroll();
|
||||
jasmine.clock().tick(100);
|
||||
});
|
||||
|
||||
it('should allow to add a className for every list item', function () {
|
||||
var view = new CustomCarouselView({
|
||||
options: [
|
||||
{ val: 'hello', selected: true },
|
||||
{ val: 'howdy' },
|
||||
{ val: 'hi' }
|
||||
],
|
||||
listItemOptions: {
|
||||
className: 'MyFabolousClassName'
|
||||
}
|
||||
});
|
||||
|
||||
view.render();
|
||||
expect(view.$('li').hasClass('MyFabolousClassName')).toBeTruthy();
|
||||
view.clean();
|
||||
});
|
||||
|
||||
it('should render properly', function () {
|
||||
expect(this.view.$('li').length).toBe(3);
|
||||
expect(this.view.$('.Carousel-shadow').length).toBe(2);
|
||||
});
|
||||
|
||||
it('should bind scroll', function () {
|
||||
expect(this.view._bindScroll).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should check shadows', function () {
|
||||
expect(this.view._checkShadows).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
jasmine.clock().uninstall();
|
||||
});
|
||||
|
||||
describe('bind', function () {
|
||||
it('should check scroll when selected item changes', function () {
|
||||
this.view.collection.at(1).set('selected', true);
|
||||
expect(this.view._checkScroll).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('unbind', function () {
|
||||
it('should not check shadows after unbind', function () {
|
||||
this.view._checkShadows.calls.reset();
|
||||
this.view._unbindScroll();
|
||||
this.view._listContainer().trigger('ps-scroll-x');
|
||||
expect(this.view._checkShadows).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
it('should destroy custom scroll when view is removed', function () {
|
||||
spyOn(this.view, '_destroyCustomScroll');
|
||||
this.view.clean();
|
||||
expect(this.view._destroyCustomScroll).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,58 @@
|
||||
var CustomListItemModel = require('builder/components/custom-list/custom-list-item-model');
|
||||
var CustomListCollection = require('builder/components/custom-list/custom-list-collection');
|
||||
|
||||
describe('components/custom-list/custom-list-collection', function () {
|
||||
beforeEach(function () {
|
||||
this.collection = new CustomListCollection([
|
||||
new CustomListItemModel({ val: 'hi' }),
|
||||
new CustomListItemModel({ val: 'howdy' }),
|
||||
new CustomListItemModel({ val: 'hello' })
|
||||
]);
|
||||
});
|
||||
|
||||
it('should search properly', function () {
|
||||
expect(this.collection.search('+').size()).toBe(0);
|
||||
expect(this.collection.search('h').size()).toBe(3);
|
||||
expect(this.collection.search('he').size()).toBe(1);
|
||||
expect(this.collection.search('/').size()).toBe(0);
|
||||
});
|
||||
|
||||
it('should remove previous selected item when a new one is chosen', function () {
|
||||
this.collection.at(1).set('selected', true);
|
||||
expect(this.collection.where({ selected: true }).length).toBe(1);
|
||||
this.collection.at(0).set('selected', true);
|
||||
expect(this.collection.where({ selected: true }).length).toBe(1);
|
||||
expect(this.collection.at(1).get('selected')).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should remove any selected item', function () {
|
||||
this.collection.at(1).set('selected', true);
|
||||
this.collection.removeSelected();
|
||||
expect(this.collection.where({ selected: true }).length).toBe(0);
|
||||
});
|
||||
|
||||
describe('sort', function () {
|
||||
it('should sort the collection by value', function () {
|
||||
this.collection.sortByKey('val');
|
||||
expect(this.collection.at(0).get('val')).toBe('hello');
|
||||
expect(this.collection.at(1).get('val')).toBe('hi');
|
||||
expect(this.collection.at(2).get('val')).toBe('howdy');
|
||||
});
|
||||
|
||||
it('should sort the collection correctly if there is a null or an undefined value', function () {
|
||||
var collection = new CustomListCollection([
|
||||
{ val: 'hi' },
|
||||
{ val: 'howdy' },
|
||||
{ val: 'hello' },
|
||||
{ val: 'hola' },
|
||||
{ val: null },
|
||||
{ val: undefined }
|
||||
]);
|
||||
collection.sortByKey('val');
|
||||
|
||||
expect(collection.at(2).get('val')).toBe('hola');
|
||||
expect(collection.at(4).get('val')).toBeNull();
|
||||
expect(collection.at(5).get('val')).toBeUndefined();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,58 @@
|
||||
var CustomListItemModel = require('builder/components/custom-list/custom-list-item-model');
|
||||
var CustomListItemView = require('builder/components/custom-list/custom-list-item-view');
|
||||
|
||||
describe('components/custom-list/custom-list-item-view', function () {
|
||||
beforeEach(function () {
|
||||
this.model = new CustomListItemModel({
|
||||
val: 'hello'
|
||||
});
|
||||
|
||||
this.view = new CustomListItemView({
|
||||
model: this.model,
|
||||
typeLabel: 'column'
|
||||
});
|
||||
|
||||
this.view.render();
|
||||
});
|
||||
|
||||
it('should render properly', function () {
|
||||
expect(this.view.$el.data('val')).not.toBeUndefined();
|
||||
expect(this.view.$('button').length).toBe(1);
|
||||
expect(this.view.$('button').attr('title')).toBe(this.model.getName());
|
||||
});
|
||||
|
||||
it('should add disabled class if it has disabled property', function () {
|
||||
expect(this.view.$el.hasClass('is-disabled')).toBeFalsy();
|
||||
this.model.set('disabled', true);
|
||||
this.view.render();
|
||||
expect(this.view.$el.hasClass('is-disabled')).toBeTruthy();
|
||||
});
|
||||
|
||||
describe('hover', function () {
|
||||
beforeEach(function () {
|
||||
this.view.$el.trigger('mouseenter');
|
||||
});
|
||||
|
||||
it('should add class when it is hovered', function () {
|
||||
expect(this.view.$el.hasClass('is-highlighted')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should remove class when it is unhovered', function () {
|
||||
this.view.$el.trigger('mouseleave');
|
||||
expect(this.view.$el.hasClass('is-highlighted')).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
it('should set selected when it is clicked', function () {
|
||||
expect(this.model.get('selected')).toBeFalsy();
|
||||
this.view.$el.trigger('click');
|
||||
expect(this.model.get('selected')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('shouldn\'t toggle by default when clicking', function () {
|
||||
expect(this.model.get('selected')).toBeFalsy();
|
||||
this.view.$el.trigger('click');
|
||||
this.view.$el.trigger('click');
|
||||
expect(this.model.get('selected')).toBeTruthy();
|
||||
});
|
||||
});
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
var CustomListItemModel = require('builder/components/custom-list/custom-list-item-model');
|
||||
var CustomListCollection = require('builder/components/custom-list/custom-list-multi-collection');
|
||||
|
||||
describe('components/custom-list/custom-list-multi-collection', function () {
|
||||
beforeEach(function () {
|
||||
this.collection = new CustomListCollection([
|
||||
new CustomListItemModel({ val: 'hi' }),
|
||||
new CustomListItemModel({ val: 'howdy' }),
|
||||
new CustomListItemModel({ val: 'hello' })
|
||||
]);
|
||||
});
|
||||
|
||||
it('shouldn\'t remove previous selected item when a new one is chosen', function () {
|
||||
this.collection.at(1).set('selected', true);
|
||||
expect(this.collection.where({ selected: true }).length).toBe(1);
|
||||
this.collection.at(0).set('selected', true);
|
||||
expect(this.collection.where({ selected: true }).length).toBe(2);
|
||||
expect(this.collection.at(0).get('selected')).toBeTruthy();
|
||||
expect(this.collection.at(1).get('selected')).toBeTruthy();
|
||||
});
|
||||
});
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
var CustomListItemModel = require('builder/components/custom-list/custom-list-item-model');
|
||||
var CustomListItemView = require('builder/components/custom-list/custom-list-multi-item-view');
|
||||
|
||||
describe('components/custom-list/custom-list-item-view', function () {
|
||||
beforeEach(function () {
|
||||
this.model = new CustomListItemModel({
|
||||
val: 'hello'
|
||||
});
|
||||
|
||||
this.view = new CustomListItemView({
|
||||
model: this.model,
|
||||
typeLabel: 'column'
|
||||
});
|
||||
|
||||
this.view.render();
|
||||
});
|
||||
|
||||
it('should toggle when clicking', function () {
|
||||
expect(this.model.get('selected')).toBeFalsy();
|
||||
this.view.$el.trigger('click');
|
||||
expect(this.model.get('selected')).toBeTruthy();
|
||||
this.view.$el.trigger('click');
|
||||
expect(this.model.get('selected')).toBeFalsy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,70 @@
|
||||
var Backbone = require('backbone');
|
||||
var _ = require('underscore');
|
||||
var CustomListSearchView = require('builder/components/custom-list/custom-list-search-view');
|
||||
|
||||
describe('components/custom-list/custom-list-search-view', function () {
|
||||
var createViewFn = function (options) {
|
||||
this.model = new Backbone.Model({ visible: true, query: '' });
|
||||
var defaultOptions = {
|
||||
model: this.model,
|
||||
typeLabel: 'column'
|
||||
};
|
||||
|
||||
spyOn(CustomListSearchView.prototype, '_checkButtons').and.callThrough();
|
||||
this.view = new CustomListSearchView(_.extend(defaultOptions, options));
|
||||
|
||||
this.view.render();
|
||||
};
|
||||
|
||||
beforeEach(function () {
|
||||
this.createView = createViewFn.bind(this);
|
||||
});
|
||||
|
||||
describe('render', function () {
|
||||
it('should render properly', function () {
|
||||
this.createView();
|
||||
|
||||
expect(this.view.$('input[type="text"]').length).toBe(1);
|
||||
expect(this.view.$('button[type="button"]').length).toBe(1);
|
||||
expect(this.view.$('input').attr('placeholder')).toEqual('components.custom-list.placeholder');
|
||||
});
|
||||
|
||||
it('should render custom placeholder if provided', function () {
|
||||
var customSearchPlaceholder = 'search by column';
|
||||
this.createView({
|
||||
searchPlaceholder: customSearchPlaceholder
|
||||
});
|
||||
|
||||
expect(this.view.$('input').attr('placeholder')).toEqual(customSearchPlaceholder);
|
||||
});
|
||||
});
|
||||
|
||||
describe('.binds', function () {
|
||||
beforeEach(function () {
|
||||
this.createView();
|
||||
});
|
||||
|
||||
it('should submit form on key pressed in the text input', function () {
|
||||
spyOn(this.view, '_submit');
|
||||
this.view.$('input').trigger('keyup');
|
||||
expect(this.view._submit).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should check buttons when query changes', function () {
|
||||
var $button = this.view.$('button[type="button"]');
|
||||
expect($button.hasClass('u-transparent')).toBe(true);
|
||||
this.model.set('query', 'h');
|
||||
expect(this.view._checkButtons).toHaveBeenCalled();
|
||||
expect($button.hasClass('u-transparent')).toBe(false);
|
||||
});
|
||||
|
||||
it('should remove query when clear is pressed', function () {
|
||||
spyOn(this.view, 'focus');
|
||||
var $button = this.view.$('button[type="button"]');
|
||||
this.model.set('query', 'h');
|
||||
$button.click();
|
||||
expect(this.model.get('query')).toBe('');
|
||||
expect(this.view.focus).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,188 @@
|
||||
var Backbone = require('backbone');
|
||||
var _ = require('underscore');
|
||||
var CustomListView = require('builder/components/custom-list/custom-list-view');
|
||||
var CustomCollection = require('builder/components/custom-list/custom-list-collection');
|
||||
var itemTemplate = require('builder/components/custom-list/custom-list-item.tpl');
|
||||
var CustomListItemView = require('builder/components/custom-list/custom-list-item-view');
|
||||
|
||||
describe('components/custom-list/custom-list-view', function () {
|
||||
var mouseOverAction;
|
||||
var mouseOutAction;
|
||||
|
||||
beforeEach(function () {
|
||||
this.collection = new CustomCollection([
|
||||
{
|
||||
val: 'hello'
|
||||
}, {
|
||||
label: 'Hi',
|
||||
val: 'hi'
|
||||
}, {
|
||||
label: null,
|
||||
val: 'howdy'
|
||||
}, {
|
||||
label: 0,
|
||||
val: 'holi'
|
||||
}
|
||||
]);
|
||||
|
||||
mouseOverAction = jasmine.createSpy('mouseOverAction');
|
||||
mouseOutAction = jasmine.createSpy('mouseOutAction');
|
||||
|
||||
this.view = new CustomListView({
|
||||
model: new Backbone.Model({ visible: true, query: '' }),
|
||||
collection: this.collection,
|
||||
typeLabel: 'column',
|
||||
itemView: CustomListItemView,
|
||||
itemTemplate: itemTemplate,
|
||||
mouseOverAction: mouseOverAction,
|
||||
mouseOutAction: mouseOutAction
|
||||
});
|
||||
});
|
||||
|
||||
describe('with free text input', function () {
|
||||
beforeEach(function () {
|
||||
this.viewWithFreeText = new CustomListView({
|
||||
model: new Backbone.Model({ visible: true, query: 'tomato' }),
|
||||
collection: this.collection,
|
||||
typeLabel: 'column',
|
||||
itemView: CustomListItemView,
|
||||
itemTemplate: itemTemplate,
|
||||
allowFreeTextInput: true
|
||||
});
|
||||
spyOn(this.viewWithFreeText, '_applyCustomScroll');
|
||||
spyOn(this.viewWithFreeText, '_applyArrowBinds');
|
||||
spyOn(this.collection, 'search').and.callThrough();
|
||||
this.viewWithFreeText.render();
|
||||
});
|
||||
|
||||
it('should render the add message when there are no items', function () {
|
||||
spyOn(this.collection, 'size').and.returnValue(0);
|
||||
this.viewWithFreeText.render();
|
||||
expect(this.viewWithFreeText.$el.text()).toContain('tomato');
|
||||
expect(this.viewWithFreeText.$el.text()).toContain('components.custom-list.add-custom-result');
|
||||
});
|
||||
});
|
||||
|
||||
describe('render', function () {
|
||||
beforeEach(function () {
|
||||
jasmine.clock().install();
|
||||
spyOn(this.view, '_applyCustomScroll');
|
||||
spyOn(this.view, '_applyArrowBinds');
|
||||
spyOn(this.collection, 'search').and.callThrough();
|
||||
this.view.render();
|
||||
});
|
||||
|
||||
it('should render empty message when there are no items', function () {
|
||||
spyOn(this.collection, 'size').and.returnValue(0);
|
||||
this.view.render();
|
||||
expect(this.view.$('.CustomList-message').length).toBe(1);
|
||||
});
|
||||
|
||||
it('should render collection items', function () {
|
||||
expect(this.view.$('.js-list').length).toBe(1);
|
||||
expect(this.view.$('li').length).toBe(4);
|
||||
expect(this.view.$('li:eq(0)').text()).toContain('hello');
|
||||
expect(this.view.$('li:eq(1)').text()).toContain('Hi');
|
||||
expect(this.view.$('li:eq(2)').text()).toContain('howdy');
|
||||
expect(this.view.$('li:eq(3)').text()).toContain('0');
|
||||
expect(this.collection.search).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should apply the custom scroll and the arrows binding', function () {
|
||||
jasmine.clock().tick(100);
|
||||
expect(this.view._applyCustomScroll).toHaveBeenCalled();
|
||||
expect(this.view._applyArrowBinds).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
jasmine.clock().uninstall();
|
||||
});
|
||||
});
|
||||
|
||||
describe('arrow + ENTER bindings', function () {
|
||||
beforeEach(function () {
|
||||
this.view.render();
|
||||
});
|
||||
|
||||
it('should highlight next (first) item when arrow key is pressed', function () {
|
||||
dispatchDocumentEvent('keydown', { which: 40 });
|
||||
expect(this.view.$('.is-highlighted').length).toBe(1);
|
||||
expect(this.view.$('li:eq(0)').hasClass('is-highlighted')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should highlight prev (last) item when arrow key is pressed', function () {
|
||||
for (var i = 0, l = 3; i<l; i++) { // eslint-disable-line
|
||||
dispatchDocumentEvent('keydown', { which: 40 });
|
||||
}
|
||||
dispatchDocumentEvent('keydown', { which: 38 });
|
||||
expect(this.view.$('.is-highlighted').length).toBe(1);
|
||||
expect(this.view.$('li:eq(1)').hasClass('is-highlighted')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should select current highlighed item when ENTER is pressed', function () {
|
||||
for (var i = 0, l = 2; i<l; i++) { // eslint-disable-line
|
||||
dispatchDocumentEvent('keydown', { which: 40 });
|
||||
}
|
||||
expect(this.view.$('li:eq(1)').hasClass('is-highlighted')).toBeTruthy();
|
||||
var selectedItem = _.first(this.collection.where({ val: this.view.$('li:eq(1)').data('val') }));
|
||||
expect(selectedItem.get('selected')).toBeFalsy();
|
||||
dispatchDocumentEvent('keydown', { which: 13 });
|
||||
expect(selectedItem.get('selected')).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
it('should remove bindings when view is cleaned', function () {
|
||||
spyOn(this.view, '_removeArrowBinds');
|
||||
spyOn(this.view, '_destroyCustomScroll');
|
||||
this.view.clean();
|
||||
expect(this.view._removeArrowBinds).toHaveBeenCalled();
|
||||
expect(this.view._destroyCustomScroll).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should remove bindings properly', function () {
|
||||
spyOn(this.view, 'render');
|
||||
this.view.clean();
|
||||
dispatchDocumentEvent('keydown', { which: 40 });
|
||||
expect(this.view.render).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should highlight selected value on show', function () {
|
||||
this.collection.at(2).set({ selected: true });
|
||||
this.view.render();
|
||||
this.view.highlight();
|
||||
expect(this.view.$('li:eq(2)').hasClass('is-highlighted')).toBeTruthy();
|
||||
});
|
||||
|
||||
describe('mouseOverAction', function () {
|
||||
describe('._onMouseOver', function () {
|
||||
it('should trigger mouseOverAction', function () {
|
||||
this.view.render();
|
||||
|
||||
this.view._onMouseOver();
|
||||
|
||||
expect(mouseOverAction).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('mouseOutAction', function () {
|
||||
describe('._onMouseOut', function () {
|
||||
it('should trigger mouseOutAction', function () {
|
||||
this.view.render();
|
||||
|
||||
this.view._onMouseOut();
|
||||
|
||||
expect(mouseOutAction).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
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);
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,171 @@
|
||||
var Backbone = require('backbone');
|
||||
var CustomView = require('builder/components/custom-list/custom-view');
|
||||
|
||||
describe('components/custom-list/custom-view', function () {
|
||||
var mouseOverAction;
|
||||
var mouseOutAction;
|
||||
|
||||
beforeEach(function () {
|
||||
this.searchPlaceholderText = 'a search placeholder';
|
||||
|
||||
mouseOverAction = jasmine.createSpy('mouseOverAction');
|
||||
mouseOutAction = jasmine.createSpy('mouseOutAction');
|
||||
|
||||
this.view = new CustomView({
|
||||
searchPlaceholder: this.searchPlaceholderText,
|
||||
options: [
|
||||
{
|
||||
val: 'hello'
|
||||
}, {
|
||||
val: 'hi'
|
||||
}, {
|
||||
val: 'howdy'
|
||||
}
|
||||
],
|
||||
mouseOverAction: mouseOverAction,
|
||||
mouseOutAction: mouseOutAction
|
||||
});
|
||||
});
|
||||
|
||||
it('should generate internal collection and model', function () {
|
||||
expect(this.view.model).toBeDefined();
|
||||
expect(this.view.collection).toBeDefined();
|
||||
});
|
||||
|
||||
describe('render', function () {
|
||||
beforeEach(function () {
|
||||
spyOn(this.view, '_renderHeader').and.callThrough();
|
||||
spyOn(this.view, '_renderSearch').and.callThrough();
|
||||
spyOn(this.view, '_renderActions').and.callThrough();
|
||||
spyOn(this.view, '_renderList');
|
||||
this.view.render();
|
||||
});
|
||||
|
||||
it('should render list and search view by default', function () {
|
||||
expect(this.view._renderHeader).toHaveBeenCalled();
|
||||
expect(this.view._renderSearch).toHaveBeenCalled();
|
||||
expect(this.view._renderList).toHaveBeenCalled();
|
||||
expect(this.view._renderActions).not.toHaveBeenCalled();
|
||||
expect(this.view._searchView.options.searchPlaceholder).toEqual(this.searchPlaceholderText);
|
||||
});
|
||||
|
||||
it('should not render search view if showSearch is disabled', function () {
|
||||
expect(this.view._renderSearch.calls.count()).toBe(1);
|
||||
expect(this.view._renderList.calls.count()).toBe(1);
|
||||
this.view.options.showSearch = false;
|
||||
this.view.render();
|
||||
expect(this.view._renderSearch.calls.count()).toBe(1);
|
||||
expect(this.view._renderList.calls.count()).toBe(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('with actions', function () {
|
||||
beforeEach(function () {
|
||||
this.actions = [
|
||||
{ label: 'All', action: function () {} },
|
||||
{ label: 'None', action: function () {} }
|
||||
];
|
||||
this.viewWithActions = new CustomView({
|
||||
searchPlaceholder: this.searchPlaceholderText,
|
||||
options: [
|
||||
{ val: 'hello' },
|
||||
{ val: 'hi' },
|
||||
{ val: 'howdy' }
|
||||
],
|
||||
actions: this.actions
|
||||
});
|
||||
spyOn(this.viewWithActions, '_renderActions').and.callThrough();
|
||||
spyOn(this.actions[0], 'action');
|
||||
spyOn(this.actions[1], 'action');
|
||||
this.viewWithActions.render();
|
||||
});
|
||||
|
||||
it('should render the actions', function () {
|
||||
expect(this.viewWithActions._renderActions).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should call the provided action', function () {
|
||||
expect(this.actions[0].action).not.toHaveBeenCalled();
|
||||
expect(this.actions[1].action).not.toHaveBeenCalled();
|
||||
this.viewWithActions.$('.js-header button').each(function (i, button) {
|
||||
button.click();
|
||||
});
|
||||
expect(this.actions[0].action).toHaveBeenCalled();
|
||||
expect(this.actions[1].action).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should hide the actions if there is a search query', function () {
|
||||
this.viewWithActions.model.set('query', 'rick');
|
||||
expect(this.viewWithActions.$('.js-actions').hasClass('u-hide')).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('on change visibility', function () {
|
||||
beforeEach(function () {
|
||||
spyOn(this.view, '_toggleVisibility');
|
||||
spyOn(this.view, 'clearSubViews');
|
||||
spyOn(this.view, 'render');
|
||||
|
||||
this.view.model.set({
|
||||
visible: true,
|
||||
query: 'hello'
|
||||
});
|
||||
});
|
||||
|
||||
it('should reset query attribute, toggle the visibility and render', function () {
|
||||
expect(this.view._toggleVisibility).toHaveBeenCalled();
|
||||
expect(this.view.model.get('query')).toBe('');
|
||||
expect(this.view.render).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should clear subviews when visibility changes to false', function () {
|
||||
this.view.render.calls.reset();
|
||||
|
||||
this.view.model.set({
|
||||
visible: false
|
||||
});
|
||||
|
||||
expect(this.view.clearSubViews).toHaveBeenCalled();
|
||||
expect(this.view.render).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should set default value to query if _selectModel is present', function () {
|
||||
this.viewWithSelectModel = new CustomView({
|
||||
searchPlaceholder: this.searchPlaceholderText,
|
||||
options: [
|
||||
{ val: 'hello' },
|
||||
{ val: 'hi' },
|
||||
{ val: 'howdy' }
|
||||
],
|
||||
typeLabel: 'test',
|
||||
selectModel: new Backbone.Model({ test: 'Morty' })
|
||||
});
|
||||
this.viewWithSelectModel._resetQuery();
|
||||
expect(this.viewWithSelectModel.model.get('query')).toEqual('Morty');
|
||||
});
|
||||
});
|
||||
|
||||
describe('mouseOverAction', function () {
|
||||
describe('._onMouseOver', function () {
|
||||
it('should trigger mouseOverAction', function () {
|
||||
this.view.render();
|
||||
|
||||
this.view._onMouseOver();
|
||||
|
||||
expect(mouseOverAction).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('mouseOutAction', function () {
|
||||
describe('._onMouseOut', function () {
|
||||
it('should trigger mouseOutAction', function () {
|
||||
this.view.render();
|
||||
|
||||
this.view._onMouseOut();
|
||||
|
||||
expect(mouseOutAction).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
var $ = require('jquery');
|
||||
var _ = require('underscore');
|
||||
var DatePickerRangeView = require('builder/components/date-picker-range/date-picker-range-view');
|
||||
|
||||
describe('components/date-picker-range/date-picker-range-view', function () {
|
||||
beforeEach(function () {
|
||||
this.createView = function (opts) {
|
||||
var custom = opts || {};
|
||||
var defaults = {el: $('<div></div>')};
|
||||
return new DatePickerRangeView(_.extend(defaults, custom));
|
||||
};
|
||||
this.view = this.createView();
|
||||
});
|
||||
|
||||
it('should be enabled by default', function () {
|
||||
expect(this.view.model.get('disabled')).toBe(false);
|
||||
});
|
||||
|
||||
it('can be created disabled or enabled', function () {
|
||||
var v = this.createView({disabled: true});
|
||||
expect(v.model.get('disabled')).toBe(true);
|
||||
|
||||
v = this.createView({disabled: false});
|
||||
expect(v.model.get('disabled')).toBe(false);
|
||||
});
|
||||
|
||||
describe('render', function () {
|
||||
beforeEach(function () {
|
||||
this.view.render();
|
||||
});
|
||||
|
||||
it('should render properly', function () {
|
||||
expect(this.view.$('button.DatePicker-dates').length).toBe(1);
|
||||
});
|
||||
|
||||
it('can be rendered disabled or enabled', function () {
|
||||
expect(this.view.model.get('disabled')).toBe(false);
|
||||
expect(this.view.$('button.DatePicker-dates').prop('disabled')).toBe(false);
|
||||
|
||||
this.view.model.set('disabled', true);
|
||||
this.view.render();
|
||||
expect(this.view.$('button.DatePicker-dates').prop('disabled')).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,78 @@
|
||||
var $ = require('jquery');
|
||||
var DropdownOverlayView = require('builder/components/dropdown-overlay/dropdown-overlay-view');
|
||||
|
||||
describe('components/dropdown-overlay/dropdown-overlay', function () {
|
||||
beforeEach(function () {
|
||||
this.onClickAction = jasmine.createSpy('onClickAction');
|
||||
this.view = new DropdownOverlayView({
|
||||
onClickAction: this.onClickAction
|
||||
});
|
||||
this.view.render();
|
||||
});
|
||||
|
||||
it('should append itself to document body when rendered', function () {
|
||||
expect($('body').find('.CDB-Box-modalOverlay').length).toEqual(1);
|
||||
});
|
||||
|
||||
it('should be appended inside container if any', function () {
|
||||
var modalElement = $('<div class="Dialog"></div>');
|
||||
var dropdownInsideModalOverlay = new DropdownOverlayView({
|
||||
container: modalElement
|
||||
});
|
||||
dropdownInsideModalOverlay.render();
|
||||
|
||||
expect(modalElement.find('.CDB-Box-modalOverlay').length).toBe(1);
|
||||
});
|
||||
|
||||
it('should be hidden when visible is false in initialization', function () {
|
||||
var dropdownOverlay = new DropdownOverlayView({
|
||||
visible: false
|
||||
});
|
||||
dropdownOverlay.render();
|
||||
|
||||
expect(dropdownOverlay.$el.css('display')).toBe('none');
|
||||
|
||||
dropdownOverlay.clean();
|
||||
});
|
||||
|
||||
it('should hide overlay when clicked', function () {
|
||||
spyOn(this.view, 'hide').and.callThrough();
|
||||
$('.CDB-Box-modalOverlay').click();
|
||||
expect(this.view.hide).toHaveBeenCalled();
|
||||
expect($('.CDB-Box-modalOverlay').css('display')).toBe('none');
|
||||
});
|
||||
|
||||
it('should invoke onClickAction when clicked', function () {
|
||||
$('.CDB-Box-modalOverlay').click();
|
||||
expect(this.onClickAction).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should be hidden when hide is invoked', function () {
|
||||
this.view.hide();
|
||||
expect($('.CDB-Box-modalOverlay').css('display')).toBe('none');
|
||||
});
|
||||
|
||||
it('should be shown when show is invoked', function () {
|
||||
this.view.hide();
|
||||
expect($('.CDB-Box-modalOverlay').css('display')).toBe('none');
|
||||
this.view.show();
|
||||
expect($('.CDB-Box-modalOverlay').css('display')).toBe('block');
|
||||
});
|
||||
|
||||
it('should apply new visibility state when toggle is invoked', function () {
|
||||
this.view.toggle();
|
||||
expect($('.CDB-Box-modalOverlay').css('display')).toBe('block');
|
||||
this.view.toggle();
|
||||
expect($('.CDB-Box-modalOverlay').css('display')).toBe('none');
|
||||
});
|
||||
|
||||
it('should remove overlay node from body when view is removed', function () {
|
||||
this.view.remove();
|
||||
expect($('body').find('.CDB-Box-modalOverlay').length).toEqual(0);
|
||||
});
|
||||
|
||||
it('should remove overlay node from body when view is cleaned', function () {
|
||||
this.view.clean();
|
||||
expect($('body').find('.CDB-Box-modalOverlay').length).toEqual(0);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,37 @@
|
||||
var ErrorView = require('builder/components/error/error-view');
|
||||
|
||||
describe('components/error/error-view', function () {
|
||||
beforeEach(function () {
|
||||
this.view = new ErrorView();
|
||||
this.view.render();
|
||||
});
|
||||
|
||||
it('should have no leaks', function () {
|
||||
expect(this.view).toHaveNoLeaks();
|
||||
});
|
||||
|
||||
it('should render default texts', function () {
|
||||
var html = this.view.$el.html();
|
||||
expect(html).toContain('default-title');
|
||||
expect(html).toContain('default-desc');
|
||||
});
|
||||
|
||||
describe('when given custom title and desc', function () {
|
||||
beforeEach(function () {
|
||||
this.view.clean();
|
||||
this.view = new ErrorView({
|
||||
title: 'custom title',
|
||||
desc: 'custom desc'
|
||||
});
|
||||
this.view.render();
|
||||
});
|
||||
|
||||
it('should render custom texts instead', function () {
|
||||
var html = this.view.$el.html();
|
||||
expect(html).not.toContain('default-title');
|
||||
expect(html).not.toContain('default-desc');
|
||||
expect(html).toContain('custom title');
|
||||
expect(html).toContain('custom desc');
|
||||
});
|
||||
});
|
||||
});
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
var Backbone = require('backbone');
|
||||
require('backbone-forms');
|
||||
var ExportImageFormModel = require('builder/editor/export-image-pane/export-image-form-model');
|
||||
|
||||
describe('editor/layers/layer-content-views/analyses/analysis-form-models/centroid-form-model', function () {
|
||||
beforeEach(function () {
|
||||
this.model = new ExportImageFormModel({
|
||||
userModel: new Backbone.Model(),
|
||||
hasGoogleBasemap: false,
|
||||
format: '.png',
|
||||
x: 10,
|
||||
y: 100,
|
||||
width: 300,
|
||||
height: 200
|
||||
});
|
||||
});
|
||||
|
||||
it('should generate schema', function () {
|
||||
expect(this.model.schema).toBeDefined();
|
||||
});
|
||||
|
||||
it('should show a validation error when width is too big', function () {
|
||||
this.model.set({ width: 200000 });
|
||||
|
||||
var form = new Backbone.Form({
|
||||
model: this.model
|
||||
});
|
||||
|
||||
var validation = form.getEditor('width').validate();
|
||||
expect(validation.message).toBe('editor.export-image.invalid-dimension');
|
||||
});
|
||||
|
||||
it('should show a validation error when height is too big', function () {
|
||||
this.model.set({ height: 200000 });
|
||||
|
||||
var form = new Backbone.Form({
|
||||
model: this.model
|
||||
});
|
||||
|
||||
var validation = form.getEditor('height').validate();
|
||||
expect(validation.message).toBe('editor.export-image.invalid-dimension');
|
||||
});
|
||||
|
||||
it('should have generated form fields', function () {
|
||||
expect(Object.keys(this.model.schema).length).toBe(3);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,409 @@
|
||||
var $ = require('jquery');
|
||||
var Backbone = require('backbone');
|
||||
var _ = require('underscore');
|
||||
var ConfigModel = require('builder/data/config-model');
|
||||
var UserModel = require('builder/data/user-model');
|
||||
var ExportImagePane = require('builder/editor/export-image-pane/export-image-pane');
|
||||
var MapDefinitionModel = require('builder/data/map-definition-model');
|
||||
var Notifier = require('builder/components/notifier/notifier');
|
||||
var EditorModel = require('builder/data/editor-model');
|
||||
|
||||
var GMAPS_DIMENSION_LIMIT = 640;
|
||||
var GMAPS_DIMENSION_LIMIT_PREMIUM = 2048;
|
||||
|
||||
describe('editor/export-image-pane/export-image-pane', function () {
|
||||
beforeEach(function () {
|
||||
var style = '[{ "stylers": [ { "saturation": -100 } ] },{ "featureType": "water", "stylers": [ { "gamma": 1.67 }, { "lightness": 27 } ] },{ "elementType": "geometry", "stylers": [ { "gamma": 1.31 }, { "lightness": 12 } ] },{ "featureType": "administrative", "elementType": "labels", "stylers": [ { "lightness": 51 }, { "gamma": 0.94 } ] },{ },{ "featureType": "road", "elementType": "labels", "stylers": [ { "lightness": 57 } ] },{ "featureType": "poi", "elementType": "labels", "stylers": [ { "lightness": 42 } ] }]';
|
||||
|
||||
this.imageExportMetadata = {
|
||||
zoom: 10,
|
||||
mapType: 'roadmap',
|
||||
style: style,
|
||||
attribution: 'CARTO',
|
||||
provider: 'no-googlemaps',
|
||||
title: 'wadus'
|
||||
};
|
||||
|
||||
this.settingsCollection = new Backbone.Collection([{
|
||||
setting: 'logo',
|
||||
label: _t('editor.settings.options.logo'),
|
||||
enabled: true,
|
||||
default: false,
|
||||
enabler: false
|
||||
}]);
|
||||
|
||||
this.getStaticImageURL = jasmine.createSpy('getStaticImageURL');
|
||||
|
||||
this.visDefinitionModel = new Backbone.Model({
|
||||
name: 'foo'
|
||||
});
|
||||
|
||||
Notifier.init({
|
||||
editorModel: new EditorModel(),
|
||||
visDefinitionModel: new Backbone.Model()
|
||||
});
|
||||
|
||||
this._configModel = new ConfigModel({
|
||||
base_url: '/u/pepe'
|
||||
});
|
||||
|
||||
this._userModel = new UserModel({
|
||||
username: 'perico',
|
||||
google_maps_api_key: '123456'
|
||||
}, {
|
||||
configModel: this._configModel
|
||||
});
|
||||
|
||||
this._userModel.set('actions', {
|
||||
remove_logo: false
|
||||
});
|
||||
|
||||
this.mapDefinitionModel = new MapDefinitionModel({
|
||||
scrollwheel: false
|
||||
}, {
|
||||
parse: true,
|
||||
configModel: this._configModel,
|
||||
userModel: this._userModel,
|
||||
layerDefinitionsCollection: new Backbone.Collection()
|
||||
});
|
||||
|
||||
this.mapDefinitionModel.setImageExportMetadata(this.imageExportMetadata);
|
||||
|
||||
spyOn(this.mapDefinitionModel, 'getStaticImageURLTemplate').and.returnValue(this.getStaticImageURL);
|
||||
spyOn(this.mapDefinitionModel, 'getMapViewSize').and.returnValue({
|
||||
x: 100,
|
||||
y: 100
|
||||
});
|
||||
|
||||
this.mapDefinitionModel.pixelToLatLng = function (x, y) {
|
||||
return { lat: 123, lng: 456 };
|
||||
};
|
||||
|
||||
this.mapDefinitionModel.latLngToPixel = function () {
|
||||
return { x: 100, y: 20 };
|
||||
};
|
||||
|
||||
this.view = new ExportImagePane({
|
||||
canvasClassName: 'CDB-Map',
|
||||
configModel: this._configModel,
|
||||
userModel: this._userModel,
|
||||
stackLayoutModel: new Backbone.Collection(),
|
||||
editorModel: new Backbone.Model(),
|
||||
privacyCollection: new Backbone.Collection(),
|
||||
widgetDefinitionsCollection: new Backbone.Collection(),
|
||||
mapcapsCollection: new Backbone.Collection(),
|
||||
mapStackLayoutModel: new Backbone.Model(),
|
||||
stateDefinitionModel: new Backbone.Model(),
|
||||
visDefinitionModel: this.visDefinitionModel,
|
||||
mapDefinitionModel: this.mapDefinitionModel,
|
||||
settingsCollection: this.settingsCollection
|
||||
});
|
||||
|
||||
// mocks
|
||||
this.view._loadAttribution = function () { return true; };
|
||||
|
||||
this.view.render();
|
||||
});
|
||||
|
||||
it('should render properly', function () {
|
||||
expect(this.view.$el.length).toBe(1);
|
||||
});
|
||||
|
||||
it('should disable button while exporting', function () {
|
||||
this.view.$('.js-ok').click();
|
||||
expect(this.view.$('.js-ok').attr('disabled')).toBe('disabled');
|
||||
});
|
||||
|
||||
it('should show a disclaimer', function () {
|
||||
expect(this.view.$el.text()).toContain('disclaimer.title');
|
||||
expect(this.view.$el.text()).toContain('disclaimer.body');
|
||||
});
|
||||
|
||||
it('should call the method to generate the image', function () {
|
||||
this.view._loadLogo = function () { return true; };
|
||||
|
||||
this.view.$('.js-ok').click();
|
||||
|
||||
expect(this.getStaticImageURL).toHaveBeenCalledWith({
|
||||
zoom: 10,
|
||||
width: 300,
|
||||
height: 200,
|
||||
lat: 123,
|
||||
lng: 456,
|
||||
format: 'png'
|
||||
});
|
||||
});
|
||||
|
||||
describe('validation', function () {
|
||||
it('should disable save button if validation error', function () {
|
||||
this.view._exportImageFormView._formView.fields.width.setValue(30000);
|
||||
this.view._exportImageFormView._formView.trigger('change');
|
||||
expect(this.view.$('.js-ok').attr('disabled')).toBe('disabled');
|
||||
|
||||
this.view._exportImageFormView._formView.fields.width.setValue(300);
|
||||
this.view._exportImageFormView._formView.trigger('change');
|
||||
expect(this.view.$('.js-ok').attr('disabled')).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should validate when dimensions change manually', function () {
|
||||
this.view._exportImageFormView._formView.fields.width.setValue(30000);
|
||||
this.view._exportImageFormView._formView.trigger('change');
|
||||
expect(this.view.$('.js-ok').attr('disabled')).toBe('disabled');
|
||||
|
||||
this.view._exportImageFormView._formModel.set('width', 315);
|
||||
expect(this.view.$('.js-ok').attr('disabled')).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('_loadLogo', function () {
|
||||
it('calls ._getImageFromUrl', function () {
|
||||
spyOn(this.view, '_getImageFromUrl').and.callThrough();
|
||||
|
||||
this.view.$('.js-ok').click();
|
||||
expect(this.view._getImageFromUrl).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('sets _logo to image and resolves the promise if there is no error', function () {
|
||||
// mocks
|
||||
this.view._getImageFromUrl = function () {
|
||||
var deferred = $.Deferred();
|
||||
deferred.resolve('this_is_my_logo');
|
||||
return deferred.promise();
|
||||
};
|
||||
|
||||
this.view.$('.js-ok').click();
|
||||
expect(this.view._logo).toEqual('this_is_my_logo');
|
||||
});
|
||||
|
||||
it('rejects the promise if there is an error', function () {
|
||||
spyOn(this.view, '_addErrorNotification');
|
||||
|
||||
// mocks
|
||||
this.view._getImageFromUrl = function () {
|
||||
var deferred = $.Deferred();
|
||||
deferred.reject();
|
||||
return deferred.promise();
|
||||
};
|
||||
|
||||
this.view.$('.js-ok').click();
|
||||
expect(this.view._addErrorNotification).toHaveBeenCalledWith('editor.maps.export-image.errors.error-image');
|
||||
});
|
||||
});
|
||||
|
||||
describe('disabled logo', function () {
|
||||
beforeEach(function () {
|
||||
spyOn(this.view, '_getImageFromUrl').and.callThrough();
|
||||
});
|
||||
|
||||
it('can\'t remove logo', function () {
|
||||
this._userModel.get('actions').remove_logo = false;
|
||||
|
||||
this.view.$('.js-ok').click();
|
||||
expect(this.view._getImageFromUrl).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('can remove logo and logo is active', function () {
|
||||
this._userModel.get('actions').remove_logo = true;
|
||||
this.settingsCollection.at(0).set('enabler', true);
|
||||
|
||||
this.view.$('.js-ok').click();
|
||||
expect(this.view._getImageFromUrl).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('can remove logo and logo is not active', function () {
|
||||
this._userModel.get('actions').remove_logo = true;
|
||||
this.settingsCollection.at(0).set('enabler', false);
|
||||
|
||||
this.view.$('.js-ok').click();
|
||||
expect(this.view._getImageFromUrl).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('_validGMapDimension', function () {
|
||||
it('should return false if dimension is bigger than limit', function () {
|
||||
this.view._exportImageFormView._formView.fields.width.setValue(641);
|
||||
this.view._exportImageFormView._formView.trigger('change');
|
||||
expect(this.view._validGMapDimension('test', GMAPS_DIMENSION_LIMIT)).toBe(false);
|
||||
|
||||
this.view._exportImageFormView._formView.fields.width.setValue(300);
|
||||
this.view._exportImageFormView._formView.trigger('change');
|
||||
expect(this.view._validGMapDimension('test', GMAPS_DIMENSION_LIMIT)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false if dimension is bigger than limit with premium user', function () {
|
||||
this.view._exportImageFormView._formView.fields.width.setValue(641);
|
||||
this.view._exportImageFormView._formView.trigger('change');
|
||||
expect(this.view._validGMapDimension('test', GMAPS_DIMENSION_LIMIT_PREMIUM)).toBe(true);
|
||||
|
||||
this.view._exportImageFormView._formView.fields.width.setValue(2049);
|
||||
this.view._exportImageFormView._formView.trigger('change');
|
||||
expect(this.view._validGMapDimension('test&signature=foo', GMAPS_DIMENSION_LIMIT_PREMIUM)).toBe(false);
|
||||
|
||||
this.view._exportImageFormView._formView.fields.width.setValue(300);
|
||||
this.view._exportImageFormView._formView.trigger('change');
|
||||
expect(this.view._validGMapDimension('test&signature=foo', GMAPS_DIMENSION_LIMIT_PREMIUM)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('with google maps', function () {
|
||||
beforeEach(function () {
|
||||
this.mapDefinitionModel.setImageExportMetadata(_.extend({}, this.imageExportMetadata, {
|
||||
provider: 'googlemaps'
|
||||
}));
|
||||
|
||||
this.view = new ExportImagePane({
|
||||
canvasClassName: 'CDB-Map',
|
||||
configModel: this._configModel,
|
||||
userModel: this._userModel,
|
||||
stackLayoutModel: new Backbone.Collection(),
|
||||
editorModel: new Backbone.Model(),
|
||||
privacyCollection: new Backbone.Collection(),
|
||||
widgetDefinitionsCollection: new Backbone.Collection(),
|
||||
mapcapsCollection: new Backbone.Collection(),
|
||||
mapStackLayoutModel: new Backbone.Model(),
|
||||
stateDefinitionModel: new Backbone.Model(),
|
||||
visDefinitionModel: this.visDefinitionModel,
|
||||
mapDefinitionModel: this.mapDefinitionModel,
|
||||
settingsCollection: this.settingsCollection
|
||||
});
|
||||
|
||||
// mocks
|
||||
this.view._loadLogo = function () { return true; };
|
||||
this.view._loadAttribution = function () { return true; };
|
||||
|
||||
this.view.render();
|
||||
});
|
||||
|
||||
describe('._loadGMapBasemap', function () {
|
||||
beforeEach(function () {
|
||||
jasmine.Ajax.install();
|
||||
});
|
||||
|
||||
it('should have been called', function () {
|
||||
spyOn(this.view, '_loadGMapBasemap');
|
||||
|
||||
this.view.$('.js-ok').click();
|
||||
expect(this.view._loadGMapBasemap).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
describe('when request succees', function () {
|
||||
beforeEach(function () {
|
||||
jasmine.Ajax.stubRequest(new RegExp('^/u/pepe')).andReturn({
|
||||
status: 200,
|
||||
contentType: 'application/json; charset=utf-8',
|
||||
responseText: '{ "url": "http://mockedgoogleurl.com/staticmap" }'
|
||||
});
|
||||
});
|
||||
|
||||
it('calls ._getImageFromUrl', function () {
|
||||
spyOn(this.view, '_getImageFromUrl');
|
||||
|
||||
this.view.$('.js-ok').click();
|
||||
expect(this.view._getImageFromUrl).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('sets _basemap to image and resolves the promise if there is no error', function () {
|
||||
// mocks
|
||||
this.view._getImageFromUrl = function () {
|
||||
var deferred = $.Deferred();
|
||||
deferred.resolve('this_is_a_static_map_url');
|
||||
return deferred.promise();
|
||||
};
|
||||
|
||||
this.view.$('.js-ok').click();
|
||||
expect(this.view._basemap).toEqual('this_is_a_static_map_url');
|
||||
});
|
||||
|
||||
it('rejects the promise if there is an error', function () {
|
||||
spyOn(this.view, '_addErrorNotification');
|
||||
|
||||
// mocks
|
||||
this.view._getImageFromUrl = function () {
|
||||
var deferred = $.Deferred();
|
||||
deferred.reject();
|
||||
return deferred.promise();
|
||||
};
|
||||
|
||||
this.view.$('.js-ok').click();
|
||||
expect(this.view._addErrorNotification).toHaveBeenCalledWith('editor.maps.export-image.errors.error-basemap');
|
||||
});
|
||||
|
||||
it('rejects the promise if validation fails', function () {
|
||||
spyOn(this.view, '_addErrorNotification');
|
||||
this.view._exportImageFormView._formView.fields.width.setValue(646);
|
||||
this.view._exportImageFormView._formView.trigger('change');
|
||||
|
||||
this.view.$('.js-ok').click();
|
||||
expect(this.view._addErrorNotification).toHaveBeenCalledWith('editor.export-image.invalid-dimension');
|
||||
});
|
||||
});
|
||||
|
||||
describe('when request fails', function () {
|
||||
it('returns an error', function () {
|
||||
jasmine.Ajax.stubRequest(new RegExp('^/u/pepe')).andReturn({
|
||||
status: 400
|
||||
});
|
||||
spyOn(this.view, '_addErrorNotification');
|
||||
|
||||
this.view.$('.js-ok').click();
|
||||
expect(this.view._addErrorNotification).toHaveBeenCalledWith('editor.maps.export-image.errors.error-basemap');
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
jasmine.Ajax.uninstall();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('with errors', function () {
|
||||
beforeEach(function () {
|
||||
this.mapDefinitionModel.setImageExportMetadata(_.extend({}, this.imageExportMetadata, {
|
||||
provider: 'googlemaps'
|
||||
}));
|
||||
|
||||
this.view = new ExportImagePane({
|
||||
canvasClassName: 'CDB-Map',
|
||||
configModel: this._configModel,
|
||||
userModel: this._userModel,
|
||||
stackLayoutModel: new Backbone.Collection(),
|
||||
editorModel: new Backbone.Model(),
|
||||
privacyCollection: new Backbone.Collection(),
|
||||
widgetDefinitionsCollection: new Backbone.Collection(),
|
||||
mapcapsCollection: new Backbone.Collection(),
|
||||
mapStackLayoutModel: new Backbone.Model(),
|
||||
stateDefinitionModel: new Backbone.Model(),
|
||||
visDefinitionModel: this.visDefinitionModel,
|
||||
mapDefinitionModel: this.mapDefinitionModel,
|
||||
settingsCollection: this.settingsCollection
|
||||
});
|
||||
|
||||
// mocks
|
||||
this.view._loadLogo = function () {
|
||||
var deferred = $.Deferred();
|
||||
deferred.reject(_t('editor.maps.export-image.errors.error-attribution'));
|
||||
return deferred.promise();
|
||||
};
|
||||
|
||||
this.view.render();
|
||||
});
|
||||
|
||||
it('should show notification', function () {
|
||||
Notifier.getCollection().reset([]);
|
||||
this.view.$('.js-ok').click();
|
||||
expect(Notifier.getCollection().length).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
it('should turn © into ©', function () {
|
||||
var attr = this.view._parseAttribution(['© © memes should be above copyright law © ©']);
|
||||
|
||||
expect(attr).not.toContain('©');
|
||||
expect((attr.match(/©/g) || []).length).toBe(4);
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
Notifier.off();
|
||||
this.view.remove();
|
||||
});
|
||||
});
|
||||
+117
@@ -0,0 +1,117 @@
|
||||
var Backbone = require('backbone');
|
||||
var ConfigModel = require('builder/data/config-model');
|
||||
var UserModel = require('builder/data/user-model');
|
||||
var ExportImageWidget = require('builder/editor/export-image-pane/export-image-widget');
|
||||
var ExportImageFormModel = require('builder/editor/export-image-pane/export-image-form-model');
|
||||
var MapDefinitionModel = require('builder/data/map-definition-model');
|
||||
var TRACK_CONTEXT_CLASS = 'track-ImageExport';
|
||||
|
||||
describe('editor/export-image-pane/export-image-widget', function () {
|
||||
beforeEach(function () {
|
||||
this.configModel = new ConfigModel({
|
||||
base_url: '/u/wadus'
|
||||
});
|
||||
|
||||
this.userModel = new UserModel({
|
||||
username: 'foo',
|
||||
google_maps_api_key: 123456
|
||||
}, {
|
||||
configModel: this.configModel
|
||||
});
|
||||
|
||||
this.mapDefinitionModel = new MapDefinitionModel({
|
||||
scrollwheel: false
|
||||
}, {
|
||||
parse: true,
|
||||
configModel: this.configModel,
|
||||
userModel: this.userModel,
|
||||
layerDefinitionsCollection: new Backbone.Collection()
|
||||
});
|
||||
|
||||
spyOn(this.mapDefinitionModel, 'getMapViewSize').and.returnValue({
|
||||
x: 100,
|
||||
y: 100
|
||||
});
|
||||
|
||||
this.mapDefinitionModel.pixelToLatLng = function (x, y) {
|
||||
return { lat: 123, lng: 456 };
|
||||
};
|
||||
|
||||
this.mapDefinitionModel.latLngToPixel = function () {
|
||||
return { x: 100, y: 20 };
|
||||
};
|
||||
|
||||
this.stateDefinitionModel = new Backbone.Model({
|
||||
json: {
|
||||
map: {
|
||||
zoom: 10,
|
||||
center: [1, 55]
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this._exportImageFormModel = new ExportImageFormModel({
|
||||
userModel: new Backbone.Model(),
|
||||
hasGoogleBasemap: false,
|
||||
format: '.png',
|
||||
x: 10,
|
||||
y: 100,
|
||||
width: 300,
|
||||
height: 200
|
||||
});
|
||||
|
||||
this.view = new ExportImageWidget({
|
||||
model: this._exportImageFormModel,
|
||||
mapViewClass: 'CDB-Map-wrapper',
|
||||
dashboardCanvasClass: 'CDB-Dashboard-canvas',
|
||||
stateDefinitionModel: this.stateDefinitionModel,
|
||||
mapDefinitionModel: this.mapDefinitionModel
|
||||
});
|
||||
this.view.render();
|
||||
});
|
||||
|
||||
it('should render properly', function () {
|
||||
expect(this.view.$('.js-canvas').length).toBe(1);
|
||||
});
|
||||
|
||||
it('should setup the canvas', function () {
|
||||
expect(this.view.$('.js-canvas').css('width')).toBe('300px');
|
||||
expect(this.view.$('.js-canvas').css('height')).toBe('200px');
|
||||
expect(this.view.$('.js-canvas').css('top')).toBe('100px');
|
||||
expect(this.view.$('.js-canvas').css('left')).toBe('10px');
|
||||
});
|
||||
|
||||
it('should have tracking classes', function () {
|
||||
expect(this.view.$('.js-canvas .ui-resizable-nw').hasClass(TRACK_CONTEXT_CLASS + ' ' + 'track-nodeTopLeft')).toBeTruthy();
|
||||
expect(this.view.$('.js-canvas .ui-resizable-n').hasClass(TRACK_CONTEXT_CLASS + ' ' + 'track-nodeTopCenter')).toBeTruthy();
|
||||
expect(this.view.$('.js-canvas .ui-resizable-ne').hasClass(TRACK_CONTEXT_CLASS + ' ' + 'track-nodeTopRight')).toBeTruthy();
|
||||
expect(this.view.$('.js-canvas .ui-resizable-w').hasClass(TRACK_CONTEXT_CLASS + ' ' + 'track-nodeMiddleLeft')).toBeTruthy();
|
||||
expect(this.view.$('.js-canvas .ui-resizable-e').hasClass(TRACK_CONTEXT_CLASS + ' ' + 'track-nodeMiddleCenter')).toBeTruthy();
|
||||
expect(this.view.$('.js-canvas .ui-resizable-sw').hasClass(TRACK_CONTEXT_CLASS + ' ' + 'track-nodeBottomLeft')).toBeTruthy();
|
||||
expect(this.view.$('.js-canvas .ui-resizable-s').hasClass(TRACK_CONTEXT_CLASS + ' ' + 'track-nodeBottomCenter')).toBeTruthy();
|
||||
expect(this.view.$('.js-canvas .ui-resizable-se').hasClass(TRACK_CONTEXT_CLASS + ' ' + 'track-nodeBottomRight')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should update the coordinates', function () {
|
||||
this.view._updateCoordinates(5, 500, 40, 50);
|
||||
expect(this._exportImageFormModel.get('x')).toEqual(5);
|
||||
expect(this._exportImageFormModel.get('y')).toEqual(500);
|
||||
expect(this._exportImageFormModel.get('width')).toEqual(40);
|
||||
expect(this._exportImageFormModel.get('height')).toEqual(50);
|
||||
});
|
||||
|
||||
it('should update coordinates on state changes', function () {
|
||||
spyOn(this.view, '_calcCenter').and.callThrough();
|
||||
this.stateDefinitionModel.set('json', {
|
||||
map: {
|
||||
zoom: 4
|
||||
}
|
||||
});
|
||||
|
||||
expect(this.view._calcCenter).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
this.view.remove();
|
||||
});
|
||||
});
|
||||
@@ -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();
|
||||
});
|
||||
});
|
||||
});
|
||||
+209
@@ -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();
|
||||
});
|
||||
});
|
||||
+48
@@ -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();
|
||||
});
|
||||
});
|
||||
+183
@@ -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();
|
||||
});
|
||||
});
|
||||
+96
@@ -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();
|
||||
});
|
||||
});
|
||||
+85
@@ -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();
|
||||
});
|
||||
});
|
||||
+53
@@ -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();
|
||||
});
|
||||
});
|
||||
});
|
||||
+47
@@ -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();
|
||||
});
|
||||
});
|
||||
});
|
||||
+106
@@ -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();
|
||||
});
|
||||
});
|
||||
});
|
||||
+92
@@ -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');
|
||||
});
|
||||
});
|
||||
});
|
||||
+37
@@ -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();
|
||||
});
|
||||
});
|
||||
+66
@@ -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();
|
||||
});
|
||||
});
|
||||
+127
@@ -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();
|
||||
});
|
||||
});
|
||||
});
|
||||
+43
@@ -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);
|
||||
});
|
||||
});
|
||||
+342
@@ -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();
|
||||
});
|
||||
});
|
||||
+102
@@ -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();
|
||||
});
|
||||
});
|
||||
+118
@@ -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');
|
||||
});
|
||||
});
|
||||
});
|
||||
+327
@@ -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();
|
||||
});
|
||||
});
|
||||
+69
@@ -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();
|
||||
});
|
||||
});
|
||||
+101
@@ -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();
|
||||
});
|
||||
});
|
||||
+82
@@ -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();
|
||||
});
|
||||
});
|
||||
+48
@@ -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
|
||||
});
|
||||
+56
@@ -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();
|
||||
});
|
||||
});
|
||||
+189
@@ -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();
|
||||
});
|
||||
});
|
||||
+70
@@ -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();
|
||||
});
|
||||
});
|
||||
+47
@@ -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();
|
||||
});
|
||||
});
|
||||
+111
@@ -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();
|
||||
});
|
||||
});
|
||||
});
|
||||
+61
@@ -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();
|
||||
});
|
||||
});
|
||||
+156
@@ -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();
|
||||
});
|
||||
});
|
||||
+60
@@ -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();
|
||||
});
|
||||
});
|
||||
+296
@@ -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();
|
||||
});
|
||||
});
|
||||
});
|
||||
+79
@@ -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);
|
||||
});
|
||||
});
|
||||
+169
@@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
+170
@@ -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();
|
||||
});
|
||||
});
|
||||
+112
@@ -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();
|
||||
});
|
||||
});
|
||||
});
|
||||
+46
@@ -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();
|
||||
});
|
||||
});
|
||||
});
|
||||
+138
@@ -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();
|
||||
});
|
||||
});
|
||||
});
|
||||
+111
@@ -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();
|
||||
});
|
||||
});
|
||||
+61
@@ -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();
|
||||
});
|
||||
});
|
||||
});
|
||||
+35
@@ -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]);
|
||||
});
|
||||
});
|
||||
+109
@@ -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();
|
||||
});
|
||||
});
|
||||
});
|
||||
+84
@@ -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());
|
||||
});
|
||||
});
|
||||
+211
@@ -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');
|
||||
});
|
||||
});
|
||||
});
|
||||
+278
@@ -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();
|
||||
});
|
||||
});
|
||||
+40
@@ -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();
|
||||
});
|
||||
});
|
||||
});
|
||||
+101
@@ -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();
|
||||
});
|
||||
});
|
||||
+159
@@ -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();
|
||||
});
|
||||
});
|
||||
+77
@@ -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();
|
||||
});
|
||||
});
|
||||
+74
@@ -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();
|
||||
});
|
||||
});
|
||||
+56
@@ -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();
|
||||
});
|
||||
});
|
||||
});
|
||||
+67
@@ -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');
|
||||
});
|
||||
});
|
||||
+292
@@ -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();
|
||||
});
|
||||
});
|
||||
+180
@@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
+162
@@ -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');
|
||||
});
|
||||
});
|
||||
});
|
||||
+67
@@ -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();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
+25
@@ -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();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,44 @@
|
||||
var $ = require('jquery');
|
||||
var IconView = require('builder/components/icon/icon-view');
|
||||
var warningIconTemplate = require('builder/components/icon/templates/warning.tpl');
|
||||
|
||||
describe('components/icon', function () {
|
||||
var createViewFn = function (options) {
|
||||
var view = new IconView({
|
||||
icon: options ? options.icon : void 0,
|
||||
placeholder: options ? options.placeholder : void 0
|
||||
});
|
||||
|
||||
return view;
|
||||
};
|
||||
|
||||
it('should throw if no icon string is provided', function () {
|
||||
expect(createViewFn).toThrow();
|
||||
});
|
||||
|
||||
it('should throw if there is no template available for icon', function () {
|
||||
expect(function () {
|
||||
createViewFn({ icon: 'no-available-icon' });
|
||||
}).toThrow();
|
||||
});
|
||||
|
||||
it('should render the icon if template is available', function () {
|
||||
var iconView = createViewFn({ icon: 'warning' });
|
||||
iconView.render();
|
||||
|
||||
expect(iconView.el.innerHTML).toBe(warningIconTemplate());
|
||||
});
|
||||
|
||||
it('should replace the placeholder with the icon view', function () {
|
||||
var iconPlaceholderTemplate = $('<div><li class="icon-placeholder"></li></div>');
|
||||
var iconTemplateResult = $('<div><li class="icon-placeholder">' + warningIconTemplate() + '</li></div>');
|
||||
|
||||
var iconView = createViewFn({
|
||||
icon: 'warning',
|
||||
placeholder: iconPlaceholderTemplate.find('.icon-placeholder')
|
||||
});
|
||||
iconView.render();
|
||||
|
||||
expect(iconPlaceholderTemplate.html()).toBe(iconTemplateResult.html());
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,160 @@
|
||||
var ImgLoaderView = require('builder/components/img-loader-view');
|
||||
|
||||
describe('components/img-loader-view', 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><rect id="rfill"></rect><rect id="rnone" style="fill:none"></rect></svg>'
|
||||
};
|
||||
var svgUrl = 'http://image.io/logo.svg';
|
||||
var imgUrl = 'http://www.imageserver.com/image.png';
|
||||
var color = '#FF0000';
|
||||
|
||||
beforeEach(function () {
|
||||
jasmine.Ajax.install();
|
||||
jasmine.Ajax.stubRequest(new RegExp('^http(s)?.*/logo.svg.*'))
|
||||
.andReturn(svgResponse);
|
||||
|
||||
this.imageClass = 'Editor-fillImageAsset';
|
||||
this.view = new ImgLoaderView({
|
||||
imageClass: this.imageClass,
|
||||
imageUrl: imgUrl,
|
||||
color: color
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
jasmine.Ajax.uninstall();
|
||||
});
|
||||
|
||||
describe('.render', function () {
|
||||
it('should render resource if format is not SVG', function () {
|
||||
this.view.render();
|
||||
|
||||
var $img = this.view.$('img');
|
||||
var classes = $img.attr('class');
|
||||
var src = $img.attr('src');
|
||||
var crossOrigin = $img.attr('crossOrigin');
|
||||
$img.empty(); // To avoid DOM requests to the image file
|
||||
|
||||
expect(classes.indexOf('js-image') > -1).toBe(true);
|
||||
expect(classes.indexOf(this.imageClass) > -1).toBe(true);
|
||||
expect(src).toBe(imgUrl + '?req=markup');
|
||||
expect(crossOrigin).toBe('anonymous');
|
||||
});
|
||||
|
||||
it('should render SVG tag if resource is SVG file', function () {
|
||||
var color = '#cebada';
|
||||
|
||||
var view = new ImgLoaderView({
|
||||
imageClass: this.imageClass,
|
||||
imageUrl: svgUrl,
|
||||
color: color
|
||||
});
|
||||
|
||||
view.render();
|
||||
|
||||
var $svg = view.$('svg');
|
||||
var classes = $svg.attr('class');
|
||||
var svgFill = $svg.css('fill').toLowerCase();
|
||||
var pathFill = $svg.find('path')[0].style['fill'].toLowerCase();
|
||||
var rectFillFill = $svg.find('#rfill')[0].style['fill'].toLowerCase();
|
||||
var rectNoneFill = $svg.find('#rnone')[0].style['fill'].toLowerCase();
|
||||
|
||||
expect($svg.length).toBe(1);
|
||||
expect(classes.indexOf('js-image') > -1).toBe(true);
|
||||
expect(classes.indexOf(this.imageClass) > -1).toBe(true);
|
||||
expect(svgFill === 'rgb(206, 186, 218)' || svgFill === color).toBe(true);
|
||||
expect(pathFill).toBe('inherit');
|
||||
expect(rectFillFill).toBe('inherit');
|
||||
expect(rectNoneFill).toBe('none');
|
||||
|
||||
view.clean();
|
||||
});
|
||||
});
|
||||
|
||||
describe('._requestImageURL', function () {
|
||||
var obj = {
|
||||
callback: function () {}
|
||||
};
|
||||
|
||||
it('successful caches the response and calls the callback', function () {
|
||||
var expectedUrl = svgUrl + '?req=ajax';
|
||||
spyOn(obj, 'callback');
|
||||
this.view._lastImage.url = null;
|
||||
this.view._lastImage.content = null;
|
||||
jasmine.Ajax.requests.reset();
|
||||
|
||||
this.view._requestImageURL(svgUrl, obj.callback);
|
||||
|
||||
expect(jasmine.Ajax.requests.mostRecent().url).toBe(expectedUrl);
|
||||
expect(obj.callback).toHaveBeenCalled();
|
||||
expect(this.view._lastImage.url).toBe(expectedUrl);
|
||||
expect(this.view._lastImage.content).toBeDefined();
|
||||
});
|
||||
|
||||
it('_requestImageURL with cached response, does not make an Ajax call and it calls the callback', function () {
|
||||
var expectedUrl = svgUrl + '?req=ajax';
|
||||
spyOn(obj, 'callback');
|
||||
|
||||
this.view._requestImageURL(svgUrl, obj.callback);
|
||||
jasmine.Ajax.requests.reset();
|
||||
this.view._requestImageURL(svgUrl, obj.callback);
|
||||
|
||||
expect(jasmine.Ajax.requests.mostRecent()).toBeUndefined();
|
||||
expect(obj.callback).toHaveBeenCalled();
|
||||
expect(this.view._lastImage.url).toBe(expectedUrl);
|
||||
expect(this.view._lastImage.content).toBeDefined();
|
||||
});
|
||||
|
||||
it('should avoid requests if image url is null or undefined', function () {
|
||||
spyOn(this.view, '_requestImageURL');
|
||||
|
||||
this.view._imageURL = null;
|
||||
this.view.render();
|
||||
expect(this.view._requestImageURL).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('_requestImageURL with error response, throws an error', function () {
|
||||
this.view._lastImage.url = null;
|
||||
this.view._lastImage.content = null;
|
||||
jasmine.Ajax.stubRequest(new RegExp('^http(s)?.*/logo.svg.*'))
|
||||
.andReturn({ status: 500 });
|
||||
|
||||
var foo = function () {
|
||||
this.view._requestImageURL(svgUrl, obj.callback);
|
||||
};
|
||||
|
||||
expect(foo).toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe('.updateImageColor', function () {
|
||||
it('should update color style', function () {
|
||||
var view = new ImgLoaderView({
|
||||
imageClass: this.imageClass,
|
||||
imageUrl: svgUrl,
|
||||
color: '#c0ffee'
|
||||
});
|
||||
|
||||
view.render();
|
||||
|
||||
view.updateImageColor('#cebada');
|
||||
|
||||
var svgFill = view.$('svg').css('fill').toLowerCase();
|
||||
expect(svgFill === 'rgb(206, 186, 218)' || svgFill === '#cebada').toBe(true);
|
||||
|
||||
view.clean();
|
||||
});
|
||||
});
|
||||
|
||||
describe('._isSVG', function () {
|
||||
it('behaves properly', function () {
|
||||
expect(this.view._isSVG('http://image.io/image.svg')).toBe(true);
|
||||
expect(this.view._isSVG('http://image.io/image.svg?req=ajax')).toBe(true);
|
||||
expect(this.view._isSVG('http://image.io/image.png')).toBe(false);
|
||||
expect(this.view._isSVG('http://image.io/image.png?req=markup')).toBe(false);
|
||||
expect(this.view._isSVG('')).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,35 @@
|
||||
var InfoboxCollection = require('builder/components/infobox/infobox-collection');
|
||||
|
||||
describe('components/infobox/infobox-collection', function () {
|
||||
beforeEach(function () {
|
||||
this.collection = new InfoboxCollection([
|
||||
{
|
||||
state: 'idle',
|
||||
createContentView: function () {
|
||||
return 'foo';
|
||||
}
|
||||
},
|
||||
{
|
||||
state: 'error',
|
||||
createContentView: function () {
|
||||
return 'bar';
|
||||
}
|
||||
}
|
||||
]);
|
||||
});
|
||||
|
||||
it('should return the first if none selected', function () {
|
||||
var selected = this.collection.getSelected();
|
||||
var createContentView = selected.get('createContentView');
|
||||
expect(createContentView()).toBe('foo');
|
||||
expect(this.collection.at(0).get('selected')).toBe(true);
|
||||
});
|
||||
|
||||
it('should have only one selected', function () {
|
||||
this.collection.at(1).set('selected', true);
|
||||
expect(this.collection.where({ selected: true }).length).toBe(1);
|
||||
this.collection.at(0).set('selected', true);
|
||||
expect(this.collection.where({ selected: true }).length).toBe(1);
|
||||
expect(this.collection.at(1).get('selected')).toBeFalsy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,48 @@
|
||||
var Infobox = require('builder/components/infobox/infobox-factory');
|
||||
|
||||
describe('components/infobox/infobox-factory', function () {
|
||||
var view;
|
||||
|
||||
describe('createInfo', function () {
|
||||
it('no closable', function () {
|
||||
view = Infobox.createInfo({
|
||||
title: 'Info',
|
||||
body: 'Lorem ipsum dolor sit amet.',
|
||||
closable: false
|
||||
});
|
||||
view.render();
|
||||
|
||||
expect(view.$('button').length).toBe(0);
|
||||
});
|
||||
|
||||
it('closable', function () {
|
||||
view = Infobox.createInfo({
|
||||
title: 'Info',
|
||||
body: 'Lorem ipsum dolor sit amet.'
|
||||
});
|
||||
view.render();
|
||||
|
||||
expect(view.$('button').length).toBe(1);
|
||||
expect(view.$('button').eq(0).html()).toContain('editor.messages.common.cancel');
|
||||
});
|
||||
});
|
||||
|
||||
describe('createWithActions', function () {
|
||||
it('main action', function () {
|
||||
view = Infobox.createWithAction({
|
||||
title: 'Info',
|
||||
body: 'Lorem ipsum dolor sit amet.',
|
||||
closable: false,
|
||||
action: {
|
||||
label: 'Confirm'
|
||||
}
|
||||
});
|
||||
|
||||
view.render();
|
||||
|
||||
expect(view.$('.Infobox')).toBeDefined();
|
||||
expect(view.$('button').length).toBe(1);
|
||||
expect(view.$('button').text()).toContain('Confirm');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,96 @@
|
||||
var InfoboxView = require('builder/components/infobox/infobox-item-view');
|
||||
|
||||
describe('components/infobox/infobox-item-view', function () {
|
||||
var view;
|
||||
|
||||
beforeEach(function () {
|
||||
view = new InfoboxView({
|
||||
type: 'error',
|
||||
title: 'Info',
|
||||
body: 'Lorem ipsum dolor sit amet.',
|
||||
action: {
|
||||
label: 'Proceed'
|
||||
},
|
||||
closable: true
|
||||
});
|
||||
|
||||
view.render();
|
||||
});
|
||||
|
||||
it('should render properly', function () {
|
||||
expect(view.$('h2').text()).toBe('Info');
|
||||
expect(view.$('div').text()).toContain('Lorem ipsum');
|
||||
expect(view.$('.Infobox-buttons button').length).toBe(2);
|
||||
expect(view.$('.Infobox-buttons button').eq(0).html()).toContain('editor.messages.common.cancel');
|
||||
expect(view.$('.Infobox-buttons button').eq(1).html()).toContain('Proceed');
|
||||
});
|
||||
|
||||
it('should have className when it is defined', function () {
|
||||
var className = 'fs-class-name';
|
||||
|
||||
var view = new InfoboxView({
|
||||
type: 'alert',
|
||||
title: 'Info',
|
||||
body: 'Lorem ipsum dolor sit amet.',
|
||||
klass: className
|
||||
});
|
||||
|
||||
view.render();
|
||||
|
||||
expect(view.$el.hasClass(className)).toBe(true);
|
||||
});
|
||||
|
||||
it('should render loading when it is defined', function () {
|
||||
var view = new InfoboxView({
|
||||
type: 'alert',
|
||||
title: 'Info',
|
||||
body: 'Lorem ipsum dolor sit amet.',
|
||||
loading: true
|
||||
});
|
||||
|
||||
view.render();
|
||||
expect(view.$('.CDB-LoaderIcon').length).toBe(1);
|
||||
});
|
||||
|
||||
it('should render quota when needed', function () {
|
||||
var view = new InfoboxView({
|
||||
type: 'alert',
|
||||
title: 'Info',
|
||||
body: 'Lorem ipsum dolor sit amet.',
|
||||
quota: {
|
||||
usedQuota: 10,
|
||||
totalQuota: 100
|
||||
},
|
||||
action: {
|
||||
label: 'Proceed'
|
||||
}
|
||||
});
|
||||
|
||||
view.render();
|
||||
expect(view.$('.js-quota').length).toBe(1);
|
||||
expect(view.$('.Infobox-quotaBar').length).toBe(1);
|
||||
});
|
||||
|
||||
it('should trigger events properly', function () {
|
||||
var callback = {
|
||||
main: function () {},
|
||||
close: function () {}
|
||||
};
|
||||
|
||||
spyOn(callback, 'main');
|
||||
spyOn(callback, 'close');
|
||||
|
||||
view.on('action:main', callback.main);
|
||||
view.on('action:close', callback.close);
|
||||
|
||||
view.$('button').eq(0).trigger('click');
|
||||
view.$('button').eq(1).trigger('click');
|
||||
|
||||
expect(callback.main.calls.count()).toEqual(1);
|
||||
expect(callback.close.calls.count()).toEqual(1);
|
||||
});
|
||||
|
||||
it('should not have any leaks', function () {
|
||||
expect(view).toHaveNoLeaks();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,97 @@
|
||||
var Infobox = require('builder/components/infobox/infobox-factory');
|
||||
var InfoboxView = require('builder/components/infobox/infobox-view');
|
||||
var InfoboxModel = require('builder/components/infobox/infobox-model');
|
||||
var InfoboxCollection = require('builder/components/infobox/infobox-collection');
|
||||
|
||||
describe('components/infobox/infobox-view', function () {
|
||||
beforeEach(function () {
|
||||
var states = [
|
||||
{
|
||||
state: 'ready',
|
||||
createContentView: function () {
|
||||
return Infobox.createInfo({
|
||||
title: 'Info',
|
||||
body: 'Lorem ipsum dolor sit amet.',
|
||||
closable: false
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
state: 'error',
|
||||
createContentView: function () {
|
||||
return Infobox.createWithAction({
|
||||
title: 'Error',
|
||||
body: 'Lorem ipsum dolor sit amet.',
|
||||
action: {
|
||||
label: 'Confirm'
|
||||
}
|
||||
});
|
||||
},
|
||||
onAction: function () {},
|
||||
onClose: function () {}
|
||||
},
|
||||
{
|
||||
state: 'wadus',
|
||||
createContentView: function () {
|
||||
return Infobox.createWithAction({
|
||||
title: 'Wadus',
|
||||
body: 'Lorem ipsum dolor sit amet.',
|
||||
action: {
|
||||
label: 'Confirm'
|
||||
}
|
||||
});
|
||||
},
|
||||
onAction: function () {}
|
||||
}
|
||||
];
|
||||
|
||||
this.model = new InfoboxModel({
|
||||
state: 'ready',
|
||||
visible: true
|
||||
});
|
||||
|
||||
this.view = new InfoboxView({
|
||||
infoboxModel: this.model,
|
||||
infoboxCollection: new InfoboxCollection(states)
|
||||
});
|
||||
|
||||
this.view.render();
|
||||
});
|
||||
|
||||
it('should render properly', function () {
|
||||
expect(this.view.infoboxView).toBeDefined();
|
||||
expect(this.view.$('.Infobox').length).toBe(1);
|
||||
expect(this.view.$('h2').text()).toBe('Info');
|
||||
expect(this.view.$('.js-close').length).toBe(0);
|
||||
|
||||
this.model.set({state: 'error'});
|
||||
|
||||
expect(this.view.$('h2').text()).toBe('Error');
|
||||
expect(this.view.$('.js-close').length).toBe(1);
|
||||
expect(this.view.$('.Infobox-buttons button').length).toBe(2);
|
||||
});
|
||||
|
||||
it('should bind actions properly', function () {
|
||||
var model = this.view._infoboxCollection.at(1);
|
||||
spyOn(model.attributes, 'onAction');
|
||||
spyOn(model.attributes, 'onClose');
|
||||
|
||||
this.model.set({state: 'error'});
|
||||
this.view.$('.Infobox-buttons button').trigger('click');
|
||||
|
||||
expect(model.attributes.onAction).toHaveBeenCalled();
|
||||
|
||||
this.view.$('.js-close').trigger('click');
|
||||
expect(model.attributes.onClose).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should close the infobox', function () {
|
||||
this.model.set({state: 'wadus'});
|
||||
this.view.$('.js-close').trigger('click');
|
||||
expect(this.view.$el.html()).toBe('');
|
||||
});
|
||||
|
||||
it('should not have any leaks', function () {
|
||||
expect(this.view).toHaveNoLeaks();
|
||||
});
|
||||
});
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user