Skip to content
4 changes: 2 additions & 2 deletions client/spa/js/instructor/editInstructor.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
<input class="textfield" id="firstName" value="<%- firstName %>" /><br/>
<input class="textfield" id="lastName" value="<%- lastName %>" /><br/>
<input class="textfield" id="skills" value="<%- skills %>" /><br/>
<button class="i-save">Save</button>
<button class="i-cancel">Cancel</button>
<button class="save">Save</button>
<button class="cancel">Cancel</button>
</form>
</div>
</section>
4 changes: 2 additions & 2 deletions client/spa/js/instructor/instructor.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
<div class="main container">
<h1><%- firstName %> <%- lastName %></h1>
<p><%- skills %></p>
<button class="i-edit">Edit</button>
<button class="i-delete">Delete</button>
<button class="modify">Edit</button>
<button class="delete">Delete</button>
<div id="result"></div>
</div>
</section>
19 changes: 9 additions & 10 deletions client/spa/js/instructor/instructor.view.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ module.exports = Backbone.View.extend({
template: _.template(template),
editTemplate: _.template(editTemplate),
events: {
'click .i-delete': 'destroy',
'click .i-edit': 'edit',
'click .i-save': 'save',
'click .i-cancel': 'cancel'
'click .delete': 'destroy',
'click .modify': 'modify',
'click .save': 'save',
'click .cancel': 'cancel'
},
initialize: function(){
this.listenTo(this.model, 'destroy', this.remove);
Expand All @@ -30,32 +30,31 @@ module.exports = Backbone.View.extend({
destroy: function(){
this.model.destroy();
},
edit: function(e){
modify: function(e){
var context = this.model.toJSON();
this.$el.html(this.editTemplate(context));

return this;
},
save: function(e) {
e.preventDefault(); // if there's no changes, do not do anything

var formData = {
firstName: this.$('#firstName').val().trim(),
lastName: this.$('#lastName').val().trim(),
skills: this.$('#skills').val().trim()
};
var validate = {
var options = {
success: function() {
$('#result').addClass('success')
.html('Successfully updated instructor')
.fadeIn().delay(4000).fadeOut();
},
error: function(model, error) {

console.log('error');
}
};

this.model.save(formData, validate);
this.model.save(formData, options);
console.log(this.model);
},
cancel: function(e) {
e.preventDefault(); // prevent event bubbling
Expand Down
8 changes: 4 additions & 4 deletions client/spa/js/instructor/spec/instructor.view.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,15 +69,15 @@ describe('Instructor view ', function(){
// call delegate after spyOn
view.delegateEvents();
view.render();
view.$('.i-edit').trigger('click');
view.$('.modify').trigger('click');
});

describe('when the user enters new instructor information ', function(){

describe('when user clicks on the cancel button', function(){

beforeEach(function(){
view.$('.i-cancel').trigger('click');
view.$('.cancel').trigger('click');
});

it('cancels the user input', function(){
Expand All @@ -91,7 +91,7 @@ describe('Instructor view ', function(){
view.$('#lastName').val('changed lastName');
view.$('#skills').val('changed skills');

view.$('.i-save').trigger('click');
view.$('.save').trigger('click');
});

it('updates the model', function(){
Expand Down Expand Up @@ -120,7 +120,7 @@ describe('Instructor view ', function(){
it('deletes the model', function(){
// Must render for the event to be fired
view.render();
view.$('.i-delete').trigger('click');
view.$('.delete').trigger('click');
expect(view.destroy).toHaveBeenCalled();
expect(model.destroy).toHaveBeenCalled();
}); // end delete model test
Expand Down
6 changes: 5 additions & 1 deletion client/spa/js/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,14 @@ window.Backbone = require('./vendor').Backbone;
// Include your code
var Instructor = require('./instructor/instructor.controller');
var Resource = require('./learning-resource/learning-resource.controller');
var Student = require('./student/student.controller');
var Students = require('./student/students.controller');

// Initialize it
window.instructor = new Instructor({router:true, container: 'body'});
window.resource = new Resource({router:true, container: 'body'});

window.student = new Student({router:true, container: 'body'});
window.students = new Students({router:true, container: 'body'});
// Additional modules go here


Expand Down
10 changes: 10 additions & 0 deletions client/spa/js/student/editStudent.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<section id="student">
<div class="main container">
<form action="#">
<input class="textfield" id="firstName" value="<%- firstName %>" /><br/>
<input class="textfield" id="lastName" value="<%- lastName %>" /><br/>
<button class="save">Save</button>
<button class="cancel">Cancel</button>
</form>
</div>
</section>
94 changes: 94 additions & 0 deletions client/spa/js/student/spec/student.controller.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
'use strict';

/*
global jasmine, describe, it, expect, beforeEach, afterEach, xdescribe, xit,
spyOn
*/
// Get the code you want to test
var Controller = require('../student.controller');
var $ = require('jquery');
var matchers = require('jasmine-jquery-matchers');
// Test suite
console.log('test student.controller');
describe('student 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({
'students/:id': 'showStudent'
}));
});

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 showstudent', function(){

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

var success = function(callbacks){
controller.model.set({'firstName': 'valid firstName',
'lastName': 'valid lastName'});
callbacks.success(controller.model);
};

var err = function(callbacks){
callbacks.error('error', controller.model);
};

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

controller.showStudent(1, cb);

});

it('with a valid student 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('');
expect(view.cid).toEqual(controller.view.cid);
};
controller.showStudent(1, cb);
});

it('with an invalid student 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 student');
};
controller.showStudent('whatid', cb);
});
});
});
89 changes: 89 additions & 0 deletions client/spa/js/student/spec/student.model.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
'use strict';

/*
global jasmine, describe, it, expect, beforeEach, afterEach, xdescribe, xit,
spyOn
*/
// Get the code you want to test
var Model = require('../student.model');

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

describe('when creating a new model ', function(){
beforeEach(function(){
model = new Model();
});

it('has the expected routes', function(){
expect(model.urlRoot).toEqual('/api/students');
});
});

describe('when updating the model for student with errorSpy ', function(){
var errorSpy;

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

it('does not save when firstName is empty ', function(){
model.set('firstName', null);
model.save();
expect(errorSpy).toHaveBeenCalled();
expect(errorSpy.calls.mostRecent().args[0]).toBe(model);
expect(errorSpy.calls.mostRecent().args[1][0]).toEqual(
'firstName cannot be empty');
});

it('does not save when lastName is empty ', function(){
model.set('lastName', null);
model.save();
expect(errorSpy).toHaveBeenCalled();
expect(errorSpy.calls.mostRecent().args[0]).toBe(model);
expect(errorSpy.calls.mostRecent().args[1][0]).toEqual(
'lastName cannot be empty');
});
});

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

beforeEach(function(){

model = new Model({
id: 1,
firstName: 'Mike',
lastName: 'Foster'
});

});

it('does not save when firstName is empty ', function(){
model.set('firstName', null);
model.save();
expect(model.validationError).toEqual(['firstName cannot be empty']);
});

it('does not save when lastName is empty ', function(){
model.set('lastName', null);
model.save();
expect(model.validationError).toEqual(['lastName cannot be empty']);
});

it('does not save when firstName and lastName are empty ', function(){
model.set({firstName:null, lastName:null});
model.save();
expect(model.validationError).toEqual(['firstName cannot be empty',
'lastName cannot be empty']);
});

});
});
Loading