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
10 changes: 5 additions & 5 deletions client/spa/js/instructor/editInstructor.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@
<section id="instructor">
<div class="main container">
<form action="#">
<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>
<input class="textfield" id="firstName" value="<%- firstName %>" /><span class="help-inline"></span><br/>
<input class="textfield" id="lastName" value="<%- lastName %>" /><span class="help-inline"></span><br/>
<input class="textfield" id="skills" value="<%- skills %>" /><span class="help-inline"></span><br/>
<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>
2 changes: 1 addition & 1 deletion client/spa/js/instructor/instructor.model.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@ module.exports = Backbone.Model.extend({
if (!attrs.skills){
errors.push('skills cannot be empty');
}
return errors;
return errors.length > 0 ? errors: false;
}
});
31 changes: 22 additions & 9 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,7 +30,7 @@ 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));

Expand All @@ -44,21 +44,34 @@ module.exports = Backbone.View.extend({
lastName: this.$('#lastName').val().trim(),
skills: this.$('#skills').val().trim()
};
var validate = {
var check = {
success: function() {
$('#result').addClass('success')
.html('Successfully updated instructor')
.fadeIn().delay(4000).fadeOut();
this.hideErrors(); // hide if successful for validation array to work
},
error: function(model, error) {

error: function(model, errors) {
this.showErrors(errors);
}
};

this.model.save(formData, validate);
this.model.save(formData, check);
},
cancel: function(e) {
e.preventDefault(); // prevent event bubbling
this.render();
},
showErrors: function(errors) {
_.each(errors, function (error) {
var fields = this.$('.' + error.name);
fields.addClass('error');
fields.find('.help-inline').text(error.message);
}, this);
},

hideErrors: function () {
this.$('.textfield').removeClass('error');
this.$('.help-inline').text('');
}
});
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
3 changes: 2 additions & 1 deletion client/spa/js/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ 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');
// 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'});
// 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 %>" /><span class="help-inline"></span><br/>
<input class="textfield" id="lastName" value="<%- lastName %>" /><span class="help-inline"></span><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