Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions client/spa/js/account/account.controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/**
* Created by russia on 2/2/15.
*/
'use strict';

var Backbone = require('../vendor/index').Backbone;
var $ = require('../vendor/index').$;
var Model = require('./account.model');
var View = require('./account.view');

module.exports = Backbone.Controller.extend({

routes: {
'accounts/:id': 'showAccount'
},

initialize: function(){
this.options.container = this.options.container || 'body';
this.model = new Model();
this.view = new View({model: this.model});
},

showAccount: function(accountId, cb){
this.fetchModel(accountId, function(err){
var view;

if (err){
view = this.renderError();
} else {
view = this.renderView();
}

if (cb){
cb(err, view);
}

}.bind(this));
},

fetchModel: function(accountId, cb){
this.model.set({id: accountId});

this.model.fetch({
success: function(model, response, options){
//console.log(model);
cb(null, model);
},
error: function(model, response, options){
//console.error(response);
cb(response, model);
}
});
},

renderToContainer: function(view){
return $(this.options.container).html(view);
},

renderView: function(){
this.renderToContainer(this.view.render().$el);
return this.view;
},

renderError: function(){
return this.renderToContainer(
'<p>There was a problem rendering this account</p>');
}

});
3 changes: 3 additions & 0 deletions client/spa/js/account/account.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<h1><%- cust_name %></h1>
<p><%- account_type %></p>
<button class="delete">Delete</button>
30 changes: 30 additions & 0 deletions client/spa/js/account/account.model.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* Created by russia on 2/2/15.
*/
'use strict';

var Backbone = require('../vendor/index').Backbone;

module.exports = Backbone.Model.extend({

defaults: {
account_type: 'enterprise'
},

urlRoot: '/api/account',

initialize: function(){
this.on('change', function(){
this.trigger('foo', 'bar');
});
},

validate: function(attrs) {
if (!attrs.cust_name) {
return 'name cannot be empty';
}
if (!attrs.account_type) {
return 'name cannot be empty';
}
}
});
39 changes: 39 additions & 0 deletions client/spa/js/account/account.view.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/**
* Created by russia on 2/2/15.
*/
'use strict';

var Backbone = require('../vendor/index').Backbone;
var _ = require('../vendor/index')._;
var $ = require('../vendor/index').$;

var fs = require('fs'); //will be replaced by brfs in the browser

// readFileSync will be evaluated statically so errors can't be caught
var template = fs.readFileSync(__dirname + '/account.html', 'utf8');

module.exports = Backbone.View.extend({

className: 'account',

template: _.template(template),

events: {
'click .delete': 'destroy'
},

initialize: function(){
this.listenTo(this.model, 'destroy', this.remove);
},

render: function(){
var context = this.model.toJSON();
this.$el.html(this.template(context));
return this;
},

destroy: function(){
this.model.destroy();
}

});
94 changes: 94 additions & 0 deletions client/spa/js/account/spec/account.controller.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/**
* Created by russia on 2/2/15.
*/
/*
global jasmine, describe, it, expect, beforeEach, afterEach, xdescribe, xit,
spyOn
*/

// Get the code you want to test
var Controller = require('../account.controller');
var $ = require('jquery');
var matchers = require('jasmine-jquery-matchers');

// Test suite
console.log('test account.controller');
describe('Account controller', function(){

var controller;

beforeEach(function(){
controller = new Controller();
});

it('can be created', function(){
expect(controller).toBeDefined();
});

describe('when it is created', function(){

it('has the expected routes', function(){
expect(controller.routes).toEqual(jasmine.objectContaining({
'accounts/:id': 'showAccount'
}));
});

it('without a container option, uses body as the container', function(){
expect(controller.options.container).toEqual('body');
});

it('with a container option, uses specified container', function(){
var ctrl = new Controller({container: '.newcontainer'});
expect(ctrl.options.container).toEqual('.newcontainer');
});
});

describe('when calling showAccount', function(){

beforeEach(function(){
jasmine.addMatchers(matchers);
});

var success = function(callbacks){
controller.model.set({'cust_name': 'valid account', 'account_type':'enterprise'});
callbacks.success(controller.model);
};
var err = function(callbacks){
callbacks.error('error', controller.model);
};

it('with a valid account id, fetches the model', function(){
spyOn(controller.model, 'fetch').and.callFake(success);
var cb = function(err, view){
expect(err).toBeNull();
expect(controller.model.get('cust_name')).toEqual('valid account');
};
controller.showAccount(1, cb);
});

it('with a valid account id, renders the view', function(){
spyOn(controller.model, 'fetch').and.callFake(success);
spyOn(controller.view, 'render').and.callFake(function(){
controller.view.$el = 'fake render';
return controller.view;
});
var cb = function(err, view){
expect($('body')).toHaveText('fake render');
expect(view.cid).toEqual(controller.view.cid);
};
controller.showAccount(1, cb);
});

it('with an invalid account id, renders an error message', function(){
spyOn(controller.model, 'fetch').and.callFake(err);
var cb = function(err, view){
expect(err).toBeTruthy();
expect($('body')).toHaveText(
'There was a problem rendering this account');
};
controller.showAccount(1, cb);
});

});

});
90 changes: 90 additions & 0 deletions client/spa/js/account/spec/account.model.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/**
* Created by russia on 2/2/15.
*/

/*
global jasmine, describe, it, expect, beforeEach, afterEach, xdescribe, xit,
spyOn
*/
'use strict';

// Get the code you want to test
var Model = require('../account.model');

// Test suite
console.log('test account.model');
describe('Account model ', function(){

var model;

describe('when creating a new model ', function(){

beforeEach(function(){
model = new Model();
});

it('sets the correct default values', function(){
expect(model.get('account_type')).toEqual('enterprise');
});

xit('initializes with custom logic', function(){

});
});

describe('when updating the model ', function(){

var errorSpy;

beforeEach(function(){
errorSpy = jasmine.createSpy('Invalid');
model = new Model({
id: 1
});
model.on('invalid', errorSpy);
model.save();
});

it('does not save when name is empty ', function(){
expect(errorSpy).toHaveBeenCalled();
expect(errorSpy).toHaveBeenCalledWith(
model,
'name cannot be empty',
{ validate: true, validationError: 'name cannot be empty'}
);
});

// Use if you have transformation logic on set
xit('sets the values correctly ', function(){

});

// Use if you have transformation logic on get
xit('retrieves the correct values ', function(){

});
});

describe('when changing the state of the model ', function(){

var eventSpy;

beforeEach(function(){
eventSpy = jasmine.createSpy('Change Event');
model = new Model({
id: 1,
name: 'test'
});
model.on('foo', eventSpy);
model.set({name: 'changed'});
});

it('triggers the custom event foo', function(){
expect(eventSpy).toHaveBeenCalled();
expect(eventSpy).toHaveBeenCalledWith(
'bar'
);
});
});

});
Loading