Initial commit
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
var $ = require('jquery');
|
||||
var Model = require('../../../src/core/model');
|
||||
|
||||
describe('core/model', function () {
|
||||
var TestModel;
|
||||
var model;
|
||||
|
||||
beforeEach(function () {
|
||||
TestModel = Model.extend({
|
||||
initialize: function () {
|
||||
this.initCalled = true;
|
||||
Model.prototype.initialize.call(this);
|
||||
},
|
||||
url: 'irrelevant.json',
|
||||
test_method: function () {}
|
||||
});
|
||||
|
||||
spyOn(Model.prototype, 'initialize').and.callThrough();
|
||||
model = new TestModel();
|
||||
});
|
||||
|
||||
it('should call initialize', function () {
|
||||
expect(model.initCalled).toBe(true);
|
||||
expect(Model.prototype.initialize).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should attach save to the element context', function () {
|
||||
spyOn(model, 'save');
|
||||
model.bind('irrelevantEvent', model.save);
|
||||
model.trigger('irrelevantEvent');
|
||||
expect(model.save).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should attach fetch to the element context', function () {
|
||||
spyOn(model, 'fetch');
|
||||
model.bind('irrelevantEvent', model.fetch);
|
||||
model.trigger('irrelevantEvent');
|
||||
expect(model.fetch).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should add the correct response from server', function () {
|
||||
model.sync = function (method, model, options) {
|
||||
options.success({ 'response': true });
|
||||
};
|
||||
model.fetch();
|
||||
expect(model.get('response')).toBeTruthy();
|
||||
});
|
||||
|
||||
it("should trigger 'loadModelStarted' event when fetch", function () {
|
||||
var loadModelStartedSpy = jasmine.createSpy('loadModelStarted');
|
||||
model.bind('loadModelStarted', loadModelStartedSpy);
|
||||
model.fetch();
|
||||
expect(loadModelStartedSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should trigger 'loadModelCompleted' event when fetched", function () {
|
||||
model.sync = function (method, model, options) {
|
||||
var dfd = $.Deferred();
|
||||
options.success({ 'response': true });
|
||||
dfd.resolve();
|
||||
return dfd.promise();
|
||||
};
|
||||
var loadModelCompletedSpy = jasmine.createSpy('loadModelCompleted');
|
||||
model.bind('loadModelCompleted', loadModelCompletedSpy);
|
||||
model.fetch();
|
||||
expect(loadModelCompletedSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should trigger 'loadModelFailed' event when fetch fails", function () {
|
||||
model.url = 'irrelevantError.json';
|
||||
|
||||
model.sync = function (method, model, options) {
|
||||
var dfd = $.Deferred();
|
||||
options.error({ 'response': true });
|
||||
return dfd.reject();
|
||||
};
|
||||
|
||||
var loadModelFailedSpy = jasmine.createSpy('loadModelFailed');
|
||||
model.bind('loadModelFailed', loadModelFailedSpy);
|
||||
|
||||
model.fetch();
|
||||
expect(loadModelFailedSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should retrigger an event when launched on a descendant object', function (done) {
|
||||
model.child = new TestModel({});
|
||||
model.retrigger('cachopo', model.child);
|
||||
var spy = jasmine.createSpy('spy');
|
||||
model.bind('cachopo', spy);
|
||||
model.child.trigger('cachopo');
|
||||
setTimeout(function () {
|
||||
expect(spy).toHaveBeenCalled();
|
||||
done();
|
||||
}, 25);
|
||||
});
|
||||
|
||||
it("should trigger 'saving' event when save", function () {
|
||||
var savingSpy = jasmine.createSpy('saving');
|
||||
model.bind('saving', savingSpy);
|
||||
model.save();
|
||||
expect(savingSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should trigger 'saved' event when saved", function () {
|
||||
model.sync = function (method, model, options) {
|
||||
var dfd = $.Deferred();
|
||||
options.success({ 'response': true });
|
||||
dfd.resolve();
|
||||
return dfd.promise();
|
||||
};
|
||||
var savedSpy = jasmine.createSpy('saving');
|
||||
model.bind('saved', savedSpy);
|
||||
model.save();
|
||||
expect(savedSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should trigger 'errorSaving' event when save fails", function () {
|
||||
model.url = 'irrelevantError.json';
|
||||
|
||||
model.sync = function (method, model, options) {
|
||||
var dfd = $.Deferred();
|
||||
options.error({ 'response': true });
|
||||
return dfd.reject();
|
||||
};
|
||||
|
||||
var errorSavingSpy = jasmine.createSpy('errorSaving');
|
||||
model.bind('errorSaving', errorSavingSpy);
|
||||
|
||||
model.save();
|
||||
expect(errorSavingSpy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,58 @@
|
||||
var sanitize = require('../../../src/core/sanitize');
|
||||
|
||||
describe('core/sanitize', function () {
|
||||
describe('.html', function () {
|
||||
describe('when given a HTML', function () {
|
||||
it('should allow safe HTML', function () {
|
||||
expect(sanitize.html('test')).toEqual('test');
|
||||
expect(sanitize.html('<div>works</div>')).toEqual('<div>works</div>');
|
||||
});
|
||||
|
||||
it('should remove unsafe stuff', function () {
|
||||
expect(sanitize.html('<img src="fail.png" onerror="document.body.appendChild(document.createElement(\'script\')).src=\'http://localhost/xss.js\'" /> nono')).toEqual('<img src="fail.png"> nono');
|
||||
expect(sanitize.html('nono <scrip src="ext.js"></script>')).toEqual('nono ');
|
||||
});
|
||||
|
||||
it('should allow target attributes for links', function () {
|
||||
expect(sanitize.html('<a href="https://carto.com/" target="_blank">carto.com</a>')).toEqual('<a href="https://carto.com/" target="_blank">carto.com</a>');
|
||||
});
|
||||
it('should remove iframe tag', function () {
|
||||
expect(sanitize.html('no <iframe src="" onload="document.body.appendChild(document.createElement(\'script\')).src=\'http://localhost/xss.js\'"/> no')).toEqual('no ');
|
||||
});
|
||||
});
|
||||
|
||||
describe('when given an 2nd param with a function', function () {
|
||||
beforeEach(function () {
|
||||
this.optionalSanitizer = jasmine.createSpy('optionalSanitizer').and.returnValue('optional sanitizer result');
|
||||
});
|
||||
|
||||
it('should use that to sanitize instead', function () {
|
||||
expect(sanitize.html('<p>something</p>', this.optionalSanitizer)).toEqual('optional sanitizer result');
|
||||
expect(this.optionalSanitizer).toHaveBeenCalled();
|
||||
expect(this.optionalSanitizer).toHaveBeenCalledWith('<p>something</p>');
|
||||
});
|
||||
});
|
||||
|
||||
describe('when given a 2nd param with a non-undefined/function value', function () {
|
||||
it('should skip sanitize', function () {
|
||||
expect(sanitize.html('<script src="i-know-what-im-doing.js"></script>', false)).toEqual('<script src="i-know-what-im-doing.js"></script>');
|
||||
expect(sanitize.html('<script src="i-know-what-im-doing.js"></script>', null)).toEqual('<script src="i-know-what-im-doing.js"></script>');
|
||||
});
|
||||
});
|
||||
|
||||
describe('common XSS attacks', function () {
|
||||
var attacks = [
|
||||
'<iframe><iframe src="/>"><p <a><img/src="x"/onerror="prompt(document.cookie)">',
|
||||
"<iframe srcdoc='<svg/onload=alert(document.cookie)>’>"
|
||||
];
|
||||
|
||||
it('should avoid `' + attacks[0] + '`', function () {
|
||||
expect(sanitize.html(attacks[0])).toEqual('');
|
||||
});
|
||||
|
||||
it('should avoid `' + attacks[1] + '`', function () {
|
||||
expect(sanitize.html(attacks[1])).toEqual('');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,21 @@
|
||||
var log = require('cdb.log');
|
||||
var TemplateList = require('../../../src/core/template-list');
|
||||
|
||||
describe('core/template-list', function () {
|
||||
var tmpl;
|
||||
|
||||
beforeEach(function () {
|
||||
spyOn(log, 'error');
|
||||
tmpl = new TemplateList();
|
||||
tmpl.reset([
|
||||
{name: 't1', template: 'hi, my name is <%= name %>'},
|
||||
{name: 't2', template: 'byee!! <%= name %>'}
|
||||
]);
|
||||
});
|
||||
|
||||
it('should get template by name', function () {
|
||||
expect(tmpl.getTemplate('t1')).toBeTruthy();
|
||||
expect(tmpl.getTemplate('t2')({name: 'cartojs-test'})).toEqual('byee!! cartojs-test');
|
||||
expect(tmpl.getTemplate('nononon')).toBeFalsy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,31 @@
|
||||
var Template = require('../../../src/core/template');
|
||||
|
||||
describe('core/template', function () {
|
||||
var tmpl;
|
||||
|
||||
beforeEach(function () {
|
||||
tmpl = new Template({
|
||||
template: 'hi, my name is <%= name %>'
|
||||
});
|
||||
});
|
||||
|
||||
it('should render', function () {
|
||||
expect(tmpl.render({name: 'cartojs-test'})).toEqual('hi, my name is cartojs-test');
|
||||
});
|
||||
|
||||
it('should accept compiled templates', function () {
|
||||
tmpl = new Template({
|
||||
compiled: function (vars) { return 'hola ' + vars.name; }
|
||||
});
|
||||
expect(tmpl.render({name: 'cartojs-test'})).toEqual('hola cartojs-test');
|
||||
});
|
||||
|
||||
it('should render using mustache', function () {
|
||||
tmpl = new Template({
|
||||
template: 'hi, my name is {{ name }}',
|
||||
type: 'mustache'
|
||||
});
|
||||
|
||||
expect(tmpl.render({name: 'cartojs-test'})).toEqual('hi, my name is cartojs-test');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,107 @@
|
||||
var util = require('../../../src/core/util');
|
||||
|
||||
describe('core/util', function () {
|
||||
it('should identify user agents properly', function () {
|
||||
var browser, ua;
|
||||
ua =
|
||||
'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36';
|
||||
browser = util._inferBrowser(ua);
|
||||
expect(browser.chrome).toBeDefined();
|
||||
|
||||
ua =
|
||||
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.75.14 (KHTML, like Gecko) Version/7.0.3 Safari/7046A194A';
|
||||
browser = util._inferBrowser(ua);
|
||||
expect(browser.safari).toBeDefined();
|
||||
|
||||
ua =
|
||||
'Opera/9.80 (X11; Linux i686; Ubuntu/14.10) Presto/2.12.388 Version/12.16';
|
||||
browser = util._inferBrowser(ua);
|
||||
expect(browser.opera).toBeDefined();
|
||||
|
||||
ua =
|
||||
'Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; AS; rv:11.0) like Gecko';
|
||||
browser = util._inferBrowser(ua);
|
||||
expect(browser.ie).toBeDefined();
|
||||
expect(browser.ie.version).toMatch(/\d+/);
|
||||
|
||||
ua = 'Mozilla/5.0 (Windows NT 6.3; rv:36.0) Gecko/20100101 Firefox/36.0';
|
||||
browser = util._inferBrowser(ua);
|
||||
expect(browser.firefox).toBeDefined();
|
||||
|
||||
ua =
|
||||
'Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.10136';
|
||||
browser = util._inferBrowser(ua);
|
||||
expect(browser.edge).toBeDefined();
|
||||
});
|
||||
|
||||
describe('supportsTouch', function () {
|
||||
var currentOnTouchStartValue, currentTouchPointsValue;
|
||||
|
||||
beforeEach(function () {
|
||||
currentOnTouchStartValue = window.ontouchstart;
|
||||
currentTouchPointsValue = navigator.msMaxTouchPoints;
|
||||
window.ontouchstart = function () {};
|
||||
});
|
||||
|
||||
it('should support it if ontouchstart event is defined', function () {
|
||||
window.ontouchstart = 'something';
|
||||
expect(util.supportsTouch()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should support it if msMaxTouchPoints has more than one', function () {
|
||||
Object.defineProperty(window, 'ontouchstart', {
|
||||
value: undefined,
|
||||
writable: true
|
||||
});
|
||||
|
||||
navigator.msMaxTouchPoints = 2;
|
||||
expect(util.supportsTouch()).toBeTruthy();
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
window.ontouchstart = currentOnTouchStartValue;
|
||||
navigator.msMaxTouchPoints = currentTouchPointsValue;
|
||||
});
|
||||
});
|
||||
|
||||
describe('google maps checks', function () {
|
||||
var existingGMaps = null;
|
||||
|
||||
beforeEach(function () {
|
||||
existingGMaps = window.google;
|
||||
window.google = undefined;
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
window.google = existingGMaps;
|
||||
});
|
||||
|
||||
it('gmaps is required as global and it must be greater than 3.31', function () {
|
||||
var checkGoogle = function () {
|
||||
util.isGoogleMapsLoaded();
|
||||
};
|
||||
|
||||
expect(checkGoogle).toThrowError('Google Maps is required');
|
||||
|
||||
window.google = { something: 'something' };
|
||||
expect(checkGoogle).toThrowError('Google Maps is required');
|
||||
|
||||
var INVALID_VERSION_MESSAGE =
|
||||
'Google Maps version should be >= 3.31';
|
||||
window.google.maps = {
|
||||
version: '2.9.9'
|
||||
};
|
||||
expect(checkGoogle).toThrowError(INVALID_VERSION_MESSAGE);
|
||||
|
||||
window.google.maps = {
|
||||
version: '3.33.0'
|
||||
};
|
||||
expect(checkGoogle).not.toThrowError(INVALID_VERSION_MESSAGE);
|
||||
|
||||
window.google.maps = {
|
||||
version: '3.31.0'
|
||||
};
|
||||
expect(checkGoogle).not.toThrow();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,165 @@
|
||||
var $ = require('jquery');
|
||||
var _ = require('underscore');
|
||||
var Backbone = require('backbone');
|
||||
var View = require('../../../src/core/view');
|
||||
|
||||
describe('core/view', function () {
|
||||
var TestView;
|
||||
var view;
|
||||
|
||||
beforeEach(function () {
|
||||
TestView = View.extend({
|
||||
initialize: function () {
|
||||
this.init_called = true;
|
||||
},
|
||||
test_method: function () {}
|
||||
});
|
||||
|
||||
View.viewCount = 0;
|
||||
view = new TestView({
|
||||
el: $('<div>')
|
||||
});
|
||||
});
|
||||
|
||||
it('should call initialize', function () {
|
||||
expect(view.init_called).toEqual(true);
|
||||
});
|
||||
|
||||
it('should increment refCount', function () {
|
||||
expect(View.viewCount).toEqual(1);
|
||||
expect(View.views[view.cid]).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should decrement refCount', function () {
|
||||
view.clean();
|
||||
expect(View.viewCount).toEqual(0);
|
||||
expect(View.views[view.cid]).toBeFalsy();
|
||||
});
|
||||
|
||||
it('clean should remove view from dom', function () {
|
||||
var dom = $('<div>');
|
||||
dom.append(view.el);
|
||||
expect(dom.children().length).toEqual(1);
|
||||
view.clean();
|
||||
expect(dom.children().length).toEqual(0);
|
||||
});
|
||||
|
||||
it('clean should unbind all events', function () {
|
||||
view.bind('meh', function () {});
|
||||
expect(_.size(view._events)).toEqual(1);
|
||||
view.clean();
|
||||
expect(view._events).toEqual(undefined);
|
||||
});
|
||||
|
||||
it('should unlink the view model', function () {
|
||||
var called = false;
|
||||
var newView = new TestView({ el: $('<div>'), model: new Backbone.Model() });
|
||||
|
||||
spyOn(newView, 'test_method');
|
||||
newView.model.bind('change', newView.test_method, newView);
|
||||
newView.model.bind('change', function () { called = true; });
|
||||
|
||||
newView.model.trigger('change');
|
||||
expect(called).toEqual(true);
|
||||
expect(newView.test_method).toHaveBeenCalled();
|
||||
expect(newView.test_method.calls.count()).toEqual(1);
|
||||
called = false;
|
||||
newView.clean();
|
||||
// trigger again
|
||||
newView.model.trigger('change');
|
||||
expect(called).toEqual(true);
|
||||
expect(newView.test_method.calls.count()).toEqual(1);
|
||||
});
|
||||
|
||||
it('should unlink linked models', function () {
|
||||
var called = false;
|
||||
var model = new Backbone.Model();
|
||||
spyOn(view, 'test_method');
|
||||
model.bind('change', view.test_method, view);
|
||||
model.bind('change', function () { called = true; });
|
||||
view.add_related_model(model);
|
||||
|
||||
model.trigger('change');
|
||||
expect(called).toEqual(true);
|
||||
expect(view.test_method).toHaveBeenCalled();
|
||||
expect(view.test_method.calls.count()).toEqual(1);
|
||||
called = false;
|
||||
view.clean();
|
||||
expect(_.size(view._models)).toEqual(0);
|
||||
// trigger again
|
||||
model.trigger('change');
|
||||
expect(called).toEqual(true);
|
||||
expect(view.test_method.calls.count()).toEqual(1);
|
||||
});
|
||||
|
||||
it('should add and remove subview', function () {
|
||||
var v1 = new View();
|
||||
view.addView(v1);
|
||||
expect(view._subviews[v1.cid]).toEqual(v1);
|
||||
expect(v1._parent).toEqual(view);
|
||||
view.removeView(v1);
|
||||
expect(view._subviews[v1.cid]).toEqual(undefined);
|
||||
});
|
||||
|
||||
it('should remove and clean subviews', function () {
|
||||
var v1 = new View();
|
||||
spyOn(v1, 'clean');
|
||||
view.addView(v1);
|
||||
expect(view._subviews[v1.cid]).toEqual(v1);
|
||||
view.clean();
|
||||
expect(view._subviews[v1.cid]).toEqual(undefined);
|
||||
expect(v1.clean).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('subview shuould be removed from its parent', function () {
|
||||
var v1 = new View();
|
||||
view.addView(v1);
|
||||
expect(view._subviews[v1.cid]).toEqual(v1);
|
||||
v1.clean();
|
||||
expect(view._subviews[v1.cid]).toEqual(undefined);
|
||||
});
|
||||
|
||||
it('extendEvents should extend events', function () {
|
||||
var V1 = View.extend({
|
||||
events: View.extendEvents({
|
||||
'click': 'hide'
|
||||
})
|
||||
});
|
||||
var v1 = new V1();
|
||||
expect(v1.el.style.display).not.toEqual('none');
|
||||
v1.$el.trigger('click');
|
||||
expect(v1.el.style.display).toEqual('none');
|
||||
});
|
||||
|
||||
it('should retrigger an event when launched on a descendant object', function (done) {
|
||||
var launched = false;
|
||||
view.child = new TestView({});
|
||||
view.retrigger('cachopo', view.child);
|
||||
view.bind('cachopo', function () {
|
||||
launched = true;
|
||||
});
|
||||
view.child.trigger('cachopo');
|
||||
setTimeout(function () {
|
||||
expect(launched).toBeTruthy();
|
||||
done();
|
||||
}, 25);
|
||||
});
|
||||
|
||||
it('should kill an event', function () {
|
||||
var ev = {
|
||||
stopPropagation: function () {},
|
||||
preventDefault: function () {}
|
||||
};
|
||||
var ev2 = 'thisisnotanevent';
|
||||
|
||||
spyOn(ev, 'stopPropagation');
|
||||
spyOn(ev, 'preventDefault');
|
||||
|
||||
view.killEvent(ev);
|
||||
view.killEvent(ev2);
|
||||
view.killEvent();
|
||||
|
||||
expect(ev.stopPropagation).toHaveBeenCalled();
|
||||
expect(ev.preventDefault).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user