/pancake-web/pancake/web/static/test/spec/ListViewSpec.js
JavaScript | 545 lines | 401 code | 118 blank | 26 comment | 5 complexity | 07af225f88f8d12e371fcda3622df1c7 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, LGPL-2.1, MIT, Apache-2.0
- /*global
- define: true,
- beforeEach: true,
- describe: true,
- it: true,
- expect: true,
- jasmine: true,
- config: true,
- spyOn: true
- */
- config.csrf_token = config.username = "asdfasdfa";
- define([
- 'config',
- '$',
- 'backbone',
- 'lib/template',
- 'views/listview',
- 'models/livecollection'
- ], function(
- config,
- $,
- Backbone,
- template,
- ListView,
- LiveCollection
- ){
- var listNode = null,
- collection = null;
- var SubView = Backbone.View.extend({
- tagName: 'div',
- className: 'subview',
- template: template('<figure class="card"><div class="media"></div><figcaption class="caption"></figcaption></figure>'),
- initialize: function (options) {
- Backbone.View.prototype.initialize.apply(this, arguments);
- $(this.el).append(this.template(this.model ? this.model.toJSON() : options));
- }
- });
- describe("ListView", function() {
- beforeEach(function(){
- // create an element afresh with each spec
- listNode = document.getElementById('listview_container');
- if(listNode){
- listNode.parentNode.removeChild(listNode);
- }
- $('<div id="listview_container"></div>').appendTo( document.body );
- listNode = document.getElementById('listview_container');
- collection = new Backbone.Collection([
- new Backbone.Model({ title: "Initial Title", id: "001" }),
- new Backbone.Model({ title: "Another Title", id: "002" })
- ]);
- });
-
- it("is a Backbone.View", function(){
- var view = new ListView({ view: SubView });
- expect(view instanceof Backbone.View).toBeTruthy();
- });
- it("instantiates with an el reference", function(){
- var view = new ListView({ el: listNode, view: SubView });
- expect(view).toBeTruthy();
- expect(view.el).toBe( listNode );
- });
- it("instantiates with an empty collection", function(){
- var view = new ListView({ collection: new Backbone.Collection(), view: SubView });
- expect(view).toBeTruthy();
- expect(view.collection).toBeTruthy();
- });
-
- it("renders a non-empty collection", function(){
- var initialContents = $(".subview", listNode);
- var view = new ListView({ collection: collection, el: listNode, view: SubView });
-
- var postRenderContents = $(".subview", listNode);
- // sanity check the fixture
- expect(initialContents.length).toBe(0);
- expect(postRenderContents.length).toBeTruthy();
- });
- it("adds subviews when models are added to the collection", function(){
- var view = new ListView({ collection: collection, el: listNode, view: SubView });
- var initialContents = $(".subview", listNode);
-
- collection.add( new Backbone.Model({ title: "Added Title", id: "003" }) );
- var postRenderContents = $(".subview", listNode);
- expect(postRenderContents.length ).toBeGreaterThan(initialContents.length);
- expect(postRenderContents.length -initialContents.length ).toBe(1);
- });
-
- it("removes subviews when models are removed from the collection", function(){
- var view = new ListView({ collection: collection, el: listNode, view: SubView });
- var initialContents = $(".subview", listNode);
-
- var firstModel = collection.at(0);
- console.log("model to remove: ", firstModel);
- collection.remove( firstModel );
- expect(collection.length ).toBe(1);
- var postRenderContents = $(".subview", listNode);
- expect(postRenderContents.length ).toBeLessThan(initialContents.length);
- expect(Math.abs(postRenderContents.length - initialContents.length) ).toBe(1);
- });
- it("renders subviews in the correct order when models inserted", function(){
- var view = new ListView({ collection: collection, el: listNode, view: SubView });
- var initialContents = $(".subview", listNode);
-
- var modelIndex0 = new Backbone.Model({ title: "At index 0", id: 'index1'}),
- modelEnd = new Backbone.Model({ title: "Appended", id: 'theend'});
-
- collection.add( modelIndex0, { at: 0 } );
- collection.add( modelEnd, { } );
- var postRenderContents = $(".subview", listNode);
- expect( postRenderContents[0].getAttribute("data-itemid")).toBe( modelIndex0.id );
- expect( postRenderContents[postRenderContents.length-1].getAttribute("data-itemid")).toBe( modelEnd.id );
- });
- });
- describe('ListView views()', function () {
- var list;
- beforeEach(function () {
- list = new ListView({
- collection: new Backbone.Collection()
- });
- });
- it('is a method', function () {
- expect(typeof list.views).toBe('function');
- });
- it('returns an array', function () {
- expect(list.views() instanceof Array).toBeTruthy();
- });
- it('should return a shallow copy of the internal views array', function () {
- // Note: I'm accessing an internal property that might change here. Please
- // don't use _views in production code.
- expect(list._views.length).toBe(0);
- expect(list.views().length).toBe(0);
- expect(list.views()).not.toBe(list._views);
- list.collection.add([
- { id: 'abc', foo: 'bar' },
- { id: 'def', foo: 'baz' }
- ]);
- expect(list._views.length).toBe(2);
- expect(list.views().length).toBe(2);
- expect(list.views()).not.toBe(list._views);
- expect(list.views()[0]).toBe(list._views[0]);
- expect(list.views()[1]).toBe(list._views[1]);
- });
- });
- describe('ListView lookup()', function () {
- var list;
- beforeEach(function () {
- list = new ListView({
- collection: new Backbone.Collection()
- });
- list.collection.add([
- { id: 'abc', foo: 'bar' },
- { id: 'def', foo: 'baz' }
- ]);
- });
- it('is a method', function () {
- expect(typeof list.lookup).toBe('function');
- });
- it('returns the sub-view that corresponds to the passed model', function () {
- var m = list.collection.at(0);
- var v = list.lookup(m);
- expect(v instanceof Backbone.View).toBeTruthy();
- expect(v.model).toBe(m);
- });
- it('returns undefined if the model does not exist in the collection', function () {
- var m = new Backbone.Model();
- var v = list.lookup(m);
- expect(v).toBe(undefined);
- });
- });
- describe('ListView register()', function () {
- var list;
- beforeEach(function () {
- list = new ListView({
- collection: new Backbone.Collection()
- });
- list.collection.add([
- { id: 'abc', foo: 'bar' },
- { id: 'def', foo: 'baz' }
- ]);
- });
- it('is a method', function () {
- expect(typeof list.register).toBe('function');
- });
- it('registers a sub-view with the internal view cache', function () {
- var m = new Backbone.Model();
- // Add model silently to collection (so that listview doesn't itself call
- // register).
- list.collection.add(m, { silent: true });
- var v = new Backbone.View({ model: m });
- list.register(v);
- expect(list._views.pop()).toBe(v);
- });
- it('updates the internal "by model" cid lookup table', function () {
- var m = new Backbone.Model();
- // _viewsByModelCid is a semi-private property. Don't use it
- // in production.
- expect(list._viewsByModelCid[m.cid]).not.toBeTruthy();
- // Add model silently to collection (so that listview doesn't itself call
- // register).
- list.collection.add(m, { silent: true });
- var v = new Backbone.View({ model: m });
- list.register(v);
- expect(list._viewsByModelCid[m.cid]).toBe(v);
- });
- it('should throw an exception if you try to register a view whos model does not appear in ListView\'s collection', function () {
- var v = new Backbone.View({ model: new Backbone.Model() });
- expect(function () {
- list.register(v);
- }).toThrow();
- });
- });
- describe('ListView deregister()', function () {
- var list;
- beforeEach(function () {
- list = new ListView({
- collection: new Backbone.Collection()
- });
- list.collection.add([
- { id: 'abc', foo: 'bar' },
- { id: 'def', foo: 'baz' }
- ]);
- });
- it('is a method', function () {
- expect(typeof list.deregister).toBe('function');
- });
- it('deregisters a sub-view from the internal view cache', function () {
- var m = list.collection.at(0);
- var v = list.lookup(m);
- list.deregister(v);
- expect(list.lookup(v)).not.toBeTruthy();
- });
- it('removes the view\'s entry from the internal "by model cid" lookup table', function () {
- var m = list.collection.at(0);
- var v = list.lookup(m);
- list.deregister(v);
- expect(list._viewsByModelCid[v.model.cid]).not.toBeTruthy();
- });
- });
- describe('ListView deregisterAll()', function () {
- var list;
- beforeEach(function () {
- list = new ListView({
- collection: new Backbone.Collection()
- });
- list.collection.add([
- { id: 'abc', foo: 'bar' },
- { id: 'def', foo: 'baz' }
- ]);
- });
- it('is a method', function () {
- expect(typeof list.deregisterAll).toBe('function');
- });
- it('empties the sub view registry completely', function () {
- expect(list.views().length).toBe(2);
- list.deregisterAll();
- expect(list.views().length).toBe(0);
- });
- it('empties the sub view "by model cid" lookup table', function () {
- var keys = Object.keys(list._viewsByModelCid);
- expect(keys.length).toBe(2);
- list.deregisterAll();
-
- keys = Object.keys(list._viewsByModelCid);
- expect(keys.length).toBe(0);
- });
- });
- describe('ListView resetViews()', function () {
- var list;
- beforeEach(function () {
- list = new ListView({
- collection: new Backbone.Collection()
- });
- list.collection.add([
- { id: 'abc', foo: 'bar' },
- { id: 'def', foo: 'baz' }
- ]);
- });
- it('should deregister all views from the internal cache', function () {
- spyOn(list, 'deregisterAll');
- list.resetViews();
- expect(list.deregisterAll).toHaveBeenCalled();
- });
- it('should re-render all views', function () {
- spyOn(list, 'addView');
- list.resetViews();
- expect(list.addView).toHaveBeenCalled();
- // 2 = one call for each model in the collection.
- expect(list.addView.callCount).toBe(2);
- });
- });
- describe('ListView createView()', function () {
- var list, m;
- beforeEach(function () {
- m = new Backbone.Model({ id: '123', foo: 'bing' });
- list = new ListView({
- collection: new Backbone.Collection()
- });
- list.collection.add([
- { id: 'abc', foo: 'bar' },
- { id: 'def', foo: 'baz' }
- ]);
- });
- it('should return a view instance', function () {
- // First, add the model to the collection silently, so that we don't get
- // an exception from register.
- list.collection.add(m, { silent: true });
- expect(list.createView({ model: m }) instanceof Backbone.View).toBeTruthy();
- });
- it('should register the view it creates', function () {
- spyOn(list, 'register').andCallThrough();
- // First, add the model to the collection silently, so that we don't get
- // an exception from register.
- list.collection.add(m, { silent: true });
- list.createView({ model: m });
- expect(list.register).toHaveBeenCalled();
- });
- });
- describe('ListView appendView', function () {
- var list, m;
- beforeEach(function () {
- list = new ListView({
- collection: new Backbone.Collection()
- });
- list.collection.add([
- { id: 'abc', foo: 'bar' },
- { id: 'def', foo: 'baz' }
- ]);
- });
- it('should render the view', function () {
- var m = list.collection.at(0);
- var v = list.lookup(m);
- spyOn(v, 'render').andCallThrough();
- list.appendView(m);
- expect(v.render).toHaveBeenCalled();
- });
- it('should insert it at the same index as the model', function () {
- var m0 = list.collection.at(0);
- expect(list.$('list').children().get(0)).toBe(list.lookup(m0).el);
- var m1 = list.collection.at(1);
- expect(list.$('list').children().get(1)).toBe(list.lookup(m1).el);
- });
- });
- describe('ListView "add" event handler', function () {
- var list, m;
- beforeEach(function () {
- m = new Backbone.Model({ id: '123', foo: 'bing' });
- list = new ListView({
- collection: new Backbone.Collection()
- });
- list.collection.add([
- { id: 'abc', foo: 'bar' },
- { id: 'def', foo: 'baz' }
- ]);
- });
- it('should create, register and append a new view for models added to the collection.', function () {
- spyOn(list, 'createView').andCallThrough();
- spyOn(list, 'appendView').andCallThrough();
- spyOn(list, 'register').andCallThrough();
- list.collection.add(m);
- expect(list.createView).toHaveBeenCalled();
- expect(list.appendView).toHaveBeenCalled();
- expect(list.register).toHaveBeenCalled();
- });
- });
- describe('ListView "remove" event handler', function () {
- var list, m;
- beforeEach(function () {
- m = new Backbone.Model({ id: '123', foo: 'bing' });
- list = new ListView({
- collection: new Backbone.Collection()
- });
- list.collection.add([
- { id: 'abc', foo: 'bar' },
- { id: 'def', foo: 'baz' }
- ]);
- });
- it('should remove and deregister the view for models removed from the collection.', function () {
- var m = list.collection.at(0);
- var v = list.lookup(m);
- spyOn(v, 'remove').andCallThrough();
- spyOn(list, 'deregister').andCallThrough();
- list.collection.remove(m);
- expect(v.remove).toHaveBeenCalled();
- expect(list.deregister).toHaveBeenCalled();
- });
- });
- describe('ListView "move" event handler', function () {
- var list, m;
- beforeEach(function () {
- list = new ListView({
- collection: new LiveCollection()
- });
- list.collection.add([
- { id: 'abc', foo: 'bar' },
- { id: 'def', foo: 'baz' }
- ]);
- });
- it('should remove the view from the old location and re-render the same view at the new location', function () {
- var m = list.collection.at(0);
- var v = list.lookup(m);
- spyOn(list, 'removeView').andCallThrough();
- spyOn(list, 'appendView').andCallThrough();
- // Make sure no new view is created.
- spyOn(list, 'createView').andCallThrough();
- list.collection.move(m, { at: 1 });
-
- expect(list.appendView).toHaveBeenCalledWith(m);
- expect(list.createView).not.toHaveBeenCalled();
- expect(list.removeView).toHaveBeenCalledWith(m);
- });
- it('should update the internal view cache', function () {
- spyOn(list, 'deregister').andCallThrough();
- spyOn(list, 'register').andCallThrough();
- var m = list.collection.at(0);
- list.collection.move(m, { at: 1 });
-
- expect(list.register).toHaveBeenCalled();
- expect(list.deregister).toHaveBeenCalled();
- });
- });
- describe('ListView getModelData', function () {
- var m = new Backbone.Model({
- title: 'Ladies of the New Century',
- artist: 'Mum'
- });
- var list = new ListView({ model: m });
- it("returns a JSON representation of the view's model", function () {
- expect(list.getModelData().title).toBe('Ladies of the New Century');
- expect(list.getModelData().artist).toBe('Mum');
- });
- it('returns a new object every time', function () {
- expect(list.getModelData()).not.toBe(list.getModelData());
- });
- it("returns an empty object if the model does not exist", function () {
- var list = new ListView();
- expect(typeof list.getModelData()).toBe('object');
- });
- });
- });