Acceptance tests aren't resetting - ember.js

I have some acceptance tests that test a component. If I run each test separately, they pass just fine. However, when I run the tests together, they fail because they're retaining the values from the previous tests.
Here is my code:
filter-test.js
module('Integration - Filter', {
beforeEach: function() {
App = startApp();
server = setupPretender();
authenticateSession();
},
afterEach: function() {
Ember.run(App, 'destroy');
server.shutdown();
}
});
test('filters can be saved and selected via the dropdown', function(assert) {
visit('/status');
fillIn('.filter-status', 'Not Completed');
fillIn('.filter-id', '444');
andThen(function() {
assert.ok(find('.status-title').text().includes('2 of 7'), 'the new filter filters the results');
});
});
test('only saved filters can be edited', function(assert) {
visit('/status');
fillIn('.filter-id', 'not an id');
click('.update-filter');
andThen(function() {
assert.equal(find('.alert').text(), 'Not a Saved Filter×');
});
});
test('filter values can be cleared', function(assert) {
visit('/status');
fillIn('.filter-id', '444');
fillIn('.filter-status', 'Completed');
click('.clear-filters');
andThen(function() {
// this fails because `.filter-id` is set to 'not an id':
assert.equal(find('.filter-id').val(), '', 'filter for was reset to its initial value');
// this also fails because `.filter-status` is set to 'Not Completed':
assert.equal(find('.filter-status').val(), 'Everything', 'status dropdown was reset to its initial value');
});
});
ps-filter/component.js
export default Ember.Component.extend({
classNames: ['panel', 'panel-default', 'filter-panel'],
currentFilter: null,
initialValues: null,
didInsertElement: function() {
this.set('initialValues', Ember.copy(this.get('filterValues')));
},
actions: {
saveFilter: function(name) {
var filters = this._getFilterList();
var filterValues = this.get('filterValues');
if (!Ember.isEmpty(name)) {
filters[name] = filterValues;
this.sendAction('updateFilter', filters);
this.set('currentFilter', name);
}
},
updateFilter: function() {
var filterValues = this.get('filterValues');
var currentFilter = this.get('currentFilter')
var filters = this.get('userFilters');
filters[currentFilter] = filterValues;
this.sendAction('updateFilter', filters);
},
clearFilters: function() {
this.set('currentFilter', null);
this.set('filterValues', Ember.copy(this.get('initialValues')));
}
}
});
status/controller.js
export default Ember.ArrayController.extend({
filterValues: {
filterStatus: 'Everything',
filterId: 'id',
},
userFilters: Ember.computed.alias('currentUser.content.preferences.filters')
});
status/template.hbs
<div class="row">
{{ps-filter
filterValues=filterValues
userFilters=userFilters
updateFilter='updateFilter'
}}
</div>
From what I gathered, it seems that it sets the initialValues to the filterValues left over from the previous test. However, I thought that the afterEach was supposed to reset it to its original state. Is there a reason why it doesn't reset it to the values in the controller?
Note that the component works normally when I run it in development.
Ember versions listed in the Ember Inspector:
Ember : 1.11.3
Ember Data : 1.0.0-beta.18
I'm running Ember CLI 0.2.7.
Edit
I don't think this is the issue at all, but here is my pretender setup:
tests/helpers/setup-pretender.js
export default function setupPretender(attrs) {
var users = [
{
id: 1,
name: 'ttest',
preferences: null
}
];
var activities = [
{
id: 36874,
activity_identifier: '18291',
status: 'Complete'
}, {
id: 36873,
activity_identifier: '82012',
status: 'In Progress'
}, {
id: 35847,
activity_identifier: '189190',
status: 'In Progress'
}, {
id: 35858,
activity_identifier: '189076',
status: 'Not Started'
}, {
id: 382901,
activity_identifier: '182730',
status: 'Not Started'
}, {
id: 400293,
activity_identifier: '88392',
status: 'Complete'
}, {
id: 400402,
activity_identifier: '88547',
status: 'Complete'
}
];
return new Pretender(function() {
this.get('api/v1/users/:id', function(request) {
var user = users.find(function(user) {
if (user.id === parseInt(request.params.id, 10)) {
return user;
}
});
return [200, {"Content-Type": "application/json"}, JSON.stringify({user: user})];
});
this.get('api/v1/activities', function(request) {
return [200, {"Content-Type": "application/json"}, JSON.stringify({
activities: activities
})];
});
this.put('api/v1/users/:id', function(request) {
var response = Ember.$.parseJSON(request.requestBody);
response.user.id = parseInt(request.params.id, 10);
var oldUser = users.find(function(user) {
if (user.id === parseInt(request.params.id, 10)) {
return user;
}
});
var oldUserIndex = users.indexOf(oldUser);
if (oldUserIndex > -1) {
users.splice(oldUserIndex, 1);
users.push(response.user);
}
return [200, {"Content-Type": "application/json"}, JSON.stringify(response)];
});
});
}
When I run the tests, it fails because it reset the value to the one in the previous test. For example, when I run 'filter values can be cleared', the .filter-id input has the same .filter-id value from 'only saved filter can be edited. If I change the value in 'only saved filters can be edited'back to '', the 'filter values can be cleared' test passes.
Basically, the component sets the initialValues property when it first inserts the element. It's set to a copy of the filterValues property, so it should be set to the controller's filterValues property, and shouldn't change. However, it seems that the modified filterValues property is carried over to the next test, which means that initialValues is set to that modified property when it rerenders. So, the test rerenders the templates, but retains the modified values in the controller and component.
I can make the tests pass by creating an initialValues property in the controller and passing that into the component, but that'd mean having duplicate properties in the controller (since filterValues and initialValues would have the same values).
I could modify the user record in the component, but I thought we're supposed to only modify records in the controller or router. Besides, isn't the afterEach hook supposed to reset the app?

Related

Unit testing Sails/Waterline models with mocha/supertest: toJSON() issue

I'm setting up unit tests on my Sails application's models, controllers and services.
I stumbled upon a confusing issue, while testing my User model. Excerpt of User.js:
module.exports = {
attributes: {
username: {
type: 'string',
required: true
},
[... other attributes...] ,
isAdmin: {
type: 'boolean',
defaultsTo: false
},
toJSON: function() {
var obj = this.toObject();
// Don't send back the isAdmin attribute
delete obj.isAdmin;
delete obj.updatedAt;
return obj;
}
}
}
Following is my test.js, meant to be run with mocha. Note that I turned on the pluralize flag in blueprints config. Also, I use sails-ember-blueprints, in order to have Ember Data-compliant blueprints. So my request has to look like {user: {...}}.
// Require app factory
var Sails = require('sails/lib/app');
var assert = require('assert');
var request = require('supertest');
// Instantiate the Sails app instance we'll be using
var app = Sails();
var User;
before(function(done) {
// Lift Sails and store the app reference
app.lift({
globals: true,
// load almost everything but policies
loadHooks: ['moduleloader', 'userconfig', 'orm', 'http', 'controllers', 'services', 'request', 'responses', 'blueprints'],
}, function() {
User = app.models.user;
console.log('Sails lifted!');
done();
});
});
// After Function
after(function(done) {
app.lower(done);
});
describe.only('User', function() {
describe('.update()', function() {
it('should modify isAdmin attribute', function (done) {
User.findOneByUsername('skippy').exec(function(err, user) {
if(err) throw new Error('User not found');
user.isAdmin = false;
request(app.hooks.http.app)
.put('/users/' + user.id)
.send({user:user})
.expect(200)
.expect('Content-Type', /json/)
.end(function() {
User.findOneByUsername('skippy').exec(function(err, user) {
assert.equal(user.isAdmin, false);
done();
});
});
});
});
});
});
Before I set up a policy that will prevent write access on User.isAdmin, I expect my user.isAdmin attribute to be updated by this request.
Before running the test, my user's isAdmin flag is set to true. Running the test shows the flag isn't updated:
1) User .update() should modify isAdmin attribute:
Uncaught AssertionError: true == false
This is even more puzzling since the following QUnit test, run on client side, does update the isAdmin attribute, though it cannot tell if it was updated, since I remove isAdmin from the payload in User.toJSON().
var user;
module( "user", {
setup: function( assert ) {
stop(2000);
// Authenticate with user skippy
$.post('/auth/local', {identifier: 'skippy', password: 'Guru-Meditation!!'}, function (data) {
user = data.user;
}).always(QUnit.start);
}
, teardown: function( assert ) {
$.get('/logout', function(data) {
});
}
});
asyncTest("PUT /users with isAdmin attribute should modify it in the db and return the user", function () {
stop(1000);
user.isAdmin = true;
$.ajax({
url: '/users/' + user.id,
type: 'put',
data: {user: user},
success: function (data) {
console.log(data);
// I can not test isAdmin value here
equal(data.user.firstName, user.firstName, "first name should not be modified");
start();
},
error: function (reason) {
equal(typeof reason, 'object', 'reason for failure should be an object');
start();
}
});
});
In the mongoDB console:
> db.user.find({username: 'skippy'});
{ "_id" : ObjectId("541d9b451043c7f1d1fd565a"), "isAdmin" : false, ..., "username" : "skippy" }
Yet even more puzzling, is that commenting out delete obj.isAdmin in User.toJSON() makes the mocha test pass!
So, I wonder:
Is the toJSON() method on Waterline models only used for output filtering? Or does it have an effect on write operations such as update().
Might this issue be related to supertest? Since the jQuery.ajax() in my QUnit test does modify the isAdmin flag, it is quite strange that the supertest request does not.
Any suggestion really appreciated.

Collection is empty when a route calls it, but if I go away and come back, the collection holds what it is supposed to

The code works every-time EXCEPT for when the router is first called with page load. The, the collection is created, but it's not populated with the notes.fetch();. I've been looking all over, and I can't see why this is happening.
For example, when I go to the URL to load this page, everything but what is in the collection loads. When I go to #blank/' and then go "Back" to thelist` view, the collection AND the models load as they are supposed to. SO how do I get the collection to load once the page loads?
Here's the code:
$(function() {
// Note: The model and collection are extended from TastypieModel and TastypieCollection
// to handle the parsing and URLs
window.Note = TastypieModel.extend({});
window.Notes = TastypieCollection.extend({
model: Note,
url: NOTES_API_URL
});
window.notes = new Notes();
window.NoteView = Backbone.View.extend({
className: "panel panel-default note",
template: _.template($('#notes-item').html()),
events: {
'click .note .edit': 'editNoteToggle',
'click .note .edit-note': 'doEdit'
},
initialize: function () {
_.bindAll(this, 'render');
this.model.bind('change', this.render);
},
render: function() {
this.$el.html(this.template(this.model.toJSON()));
return this;
},
editNoteToggle: function() {
console.log("I've toggled the edit box");
},
doEdit: function() {
console.log('This will edit the note');
}
});
window.NoteListView = Backbone.View.extend({
el: "#app",
template: _.template($('#notes-item-list').html()),
events: {
'click #add-note': 'addNote'
},
initialize: function () {
_.bindAll(this, 'render', 'addNote');
this.collection.bind('change', this.render);
},
render: function() {
this.$el.html(this.template());
console.log('before the loop');
console.log(this.collection.toJSON()); //<- Empty when it first loads, then contains the models when I visit another page and come "back" to this page
this.collection.each(function(note){
var view = new NoteView({ model: note });
$('#notes-list').append(view.render().el);
});
console.log('done');
$('#add-note-toggle').on('click', this, function() {
$('#note-add-form').toggle();
});
return this;
},
addNote: function() {
console.log('The add note was clicked');
}
});
window.NotesRouter = Backbone.Router.extend({
routes: {
'': 'list',
'blank/': 'blank'
},
initialize: function() {
// starts by assigning the collection to a variable so that it can load the collection
this.notesView = new NoteListView({
collection: notes
});
notes.fetch();
},
list: function () {
$('#app').empty();
$('#app').append(this.notesView.render().el);
},
blank: function() {
$('#app').empty();
$('#app').text('Another view');
}
});
window.notesRouter = new NotesRouter();
Backbone.history.start();
})
It looks like your listening to the wrong collection event. Try using
window.NoteListView = Backbone.View.extend({
// ...
initialize: function () {
this.collection.bind('reset', this.render);
}
// ...
});
window.NotesRouter = Backbone.Router.extend({
// ...
initialize: function() {
notes.fetch({reset: true});
}
// ...
});
Right now you are firing off an async collection.fetch(), which will eventually load the data. Problem is, once that data is loaded into the collection, it won't fire a change event, just a bunch of adds. When you go to the blank page and back, you're data has arrived by the second render call and displays properly.
If you modify your fetch() to throw a reset event and then listen for that, you'll have a freshly rendered NoteList once the data comes in without the need to go to the blank page.

ember.js sending actions to controllers from views

I've created a typeahead view and i'm trying to send an action to the current controller to set a property. Here is my typeahead view
App.Typeahead = Ember.TextField.extend({
dataset_name: undefined, //The string used to identify the dataset. Used by typeahead.js to cache intelligently.
dataset_limit: 5, //The max number of suggestions from the dataset to display for a given query. Defaults to 5.
dataset_template: undefined, //The template used to render suggestions. Can be a string or a precompiled template. If not provided, suggestions will render as their value contained in a <p> element (i.e. <p>value</p>).
dataset_engine: undefined, //The template engine used to compile/render template if it is a string. Any engine can use used as long as it adheres to the expected API. Required if template is a string.
dataset_local: undefined, //An array of datums.
dataset_prefetch: undefined, //Can be a URL to a JSON file containing an array of datums or, if more configurability is needed, a prefetch options object.
dataset_remote: undefined, //Can be a URL to fetch suggestions from when the data provided by local and prefetch is insufficient or, if more configurability is needed, a remote options object.
ctrl_action: undefined,
didInsertElement: function () {
this._super();
var self = this;
Ember.run.schedule('actions', this, function () {
self.$().typeahead({
name: self.get('dataset_name'),
limit: self.get('dataset_limit'),
template: self.get('dataset_template'),
engine: self.get('dataset_engine'),
local: self.get('dataset_local'),
prefetch: self.get('dataset_prefetch'),
remote: self.get('dataset_remote')
}).on('typeahead:selected', function (ev, datum) {
self.selected(datum);
});
});
},
willDestroyElement: function () {
this._super();
this.$().typeahead('destroy');
},
selected: function(datum) {
this.get('controller').send(this.get('ctrl_action'), datum);
}
});
Here's an implementation
App.CompanyTA = App.Typeahead.extend({
dataset_limit: 10,
dataset_engine: Hogan,
dataset_template: '<p><strong>{{value}}</strong> - {{year}}</p>',
dataset_prefetch: '../js/stubs/post_1960.json',
ctrl_action: 'setCompanyDatum',
selected: function (datum) {
this._super(datum);
this.set('value', datum.value);
}
});
and here's my controller
App.PeopleNewController = Ember.ObjectController.extend({
//content: Ember.Object.create(),
firstName: '',
lastName: '',
city: '',
state: '',
ta_datum: undefined,
actions: {
doneEditing: function () {
var firstName = this.get('firstName');
if (!firstName.trim()) { return; }
var lastName = this.get('lastName');
if (!lastName.trim()) { return; }
var city = this.get('city');
if (!city.trim()) { return; }
var state = this.get('state');
if (!state.trim()) { return; }
var test = this.get('ta_datum');
// Create the new person model
var person = this.store.createRecord('person', {
firstName: firstName,
lastName: lastName,
city: city,
state: state
});
// Clear the fields
this.set('firstName', '');
this.set('lastName', '');
this.set('city', '');
this.set('state', '');
// Save the new model
person.save();
},
setCompanyDatum: function(datum) {
this.set('ta_datum', datum);
}
}
});
I'm expecting the setCompanyDatum controller action to be called, but it's not. Everything else is working as expected. The App.Typeahead.selected method is being called with the right action name, but it doesn't actually call the action method.
the controller inside your App.Typeahead points to the instance of the App.Typeahead, not the controller from the route where you are creating the view.
You should just be using sendAction
http://emberjs.jsbin.com/EduDitE/2/edit
{{view App.Typeahead}}
App.IndexRoute = Ember.Route.extend({
model: function() {
return ['red', 'yellow', 'blue'];
},
actions:{
externalAction:function(item){
console.log('helllllo' + item);
}
}
});
App.Typeahead = Ember.TextField.extend({
internalAction: 'externalAction',
didInsertElement: function () {
this.sendAction('internalAction', " I'm a sent action");
this._super();
}
});

Fullcalendar, backbone.js, Cannot edit event

So, I think I am in over my head here. I am trying to get fullcalendar to work with backbone and django. I am still learning all of this but I can now make new events and save them via django-tastypie, and they do show up in the calendar, wohoo! However, I can not edit or drag them. Uncaught TypeError: Cannot call method 'isNew' of undefined line 96, is what I get when events are clicked and Uncaught TypeError: Cannot call method 'save' of undefined line 78. I have done my best to figure this out, but no success. Why is this.model.isnew() undefined in render and the same for save? I do not fully understand all of this so I have probably made some stupid mistake somewhere or misunderstood how everything works. I would be grateful if anyone could give me a hint.
I added console.log(fcEvent); to eventClick, and when I inspect it, it says start and end dates are invalid. Does anyone know what that means? If I inspect the same object just after it was added with addOne, the dates are valid. I am also using https://github.com/PaulUithol/backbone-tastypie if that matters.
edit: Tried this to make sure events.fetch() succeeded, this resulted in no events in the calendar whatsoever. Does that mean that events.fetch() never succeeds? I can see "GET /api/event/ HTTP/1.1" 200 6079 in the log.
alternative fetch:
events.fetch({
success: function(){
new EventsView({el: $("#calendar"), collection: events}).render();
}});
Original program:
$(function(){
var Event = Backbone.Model.extend();
var Events = Backbone.Collection.extend({
model: Event,
url: '/api/event/'
});
var EventsView = Backbone.View.extend({
initialize: function(){
_.bindAll(this);
this.collection.bind('reset', this.addAll);
this.collection.bind('add', this.addOne);
this.collection.bind('change', this.change);
this.collection.bind('destroy', this.destroy);
this.eventView = new EventView();
},
render: function() {
this.$el.fullCalendar({
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,basicDay'
},
selectable: true,
selectHelper: true,
editable: true,
ignoreTimezone: false,
disableResizing:false,
select: this.select,
defaultView: 'agendaWeek',
eventClick: this.eventClick,
eventDrop: this.eventDropOrResize,
eventResize: this.eventDropOrResize,
events: 'events'
});
},
addAll: function() {
this.$el.fullCalendar('addEventSource', this.collection.toJSON());
},
addOne: function(event) {
this.$el.fullCalendar('renderEvent', event.toJSON(), true);
},
select: function(start, end, allDay) {
var eventView = new EventView();
console.log('select');
eventView.collection = this.collection;
eventView.model = new Event({start: start, end: end, allDay: allDay});
eventView.render();
},
eventClick: function(fcEvent) {
console.log('click');
this.eventView.collection = this.collection;
this.eventView.model = this.collection.at(fcEvent.id);
console.log(fcEvent);
this.eventView.render();
},
change: function(event) {
// Look up the underlying event in the calendar and update its details from the model
var fcEvent = this.$el.fullCalendar('clientEvents', event.get('id'))[0];
fcEvent.title = event.get('title');
fcEvent.color = event.get('color');
console.log('change');
this.$el.fullCalendar('updateEvent', fcEvent);
},
eventDropOrResize: function(fcEvent) {
console.log(fcEvent);
// Lookup the model that has the ID of the event and update its attributes
this.eventView.collection.at(fcEvent.id).save({start: fcEvent.start, end: fcEvent.end});
},
destroy: function(event) {
this.$el.fullCalendar('removeEvents', event.id);
}
});
var EventView = Backbone.View.extend({
el: $('#eventDialog'),
initialize: function() {
_.bindAll(this);
},
render: function() {
var buttons = {'Ok': this.save};
if (!this.model.isNew()) {
_.extend(buttons, {'Delete': this.destroy});
}
_.extend(buttons, {'Cancel': this.close});
this.$el.dialog({
modal: true,
title: (this.model.isNew() ? 'New' : 'Edit') + ' Event',
buttons: buttons,
open: this.open
});
return this;
},
open: function() {
this.$('#title').val(this.model.get('title'));
this.$('#color').val(this.model.get('color'));
},
save: function() {
this.model.set({'title': this.$('#title').val(), 'color': this.$('#color').val(),});
console.log('save');
if (this.model.isNew()) {
this.collection.create(this.model, {success: this.close,wait: true });
} else {
this.model.save({}, {success: this.close});
}
},
close: function() {
this.$el.dialog('close');
},
destroy: function() {
this.model.destroy({success: this.close});
}
});
var events = new Events();
new EventsView({el: $("#calendar"), collection: events}).render();
events.fetch();
});
You can try this. The issue comes down to an undefined Model.
On this line.
select: function(start, end, allDay) {
var eventView = new EventView();
eventView.collection = this.collection;
eventView.model = new Event({start: start, end: end, allDay: allDay});
eventView.render();
},...
Change it to. I have a feeling that your Model is not being instantiated properly.
select: function(start, end, allDay) {
var eventView = new EventView({
collection: this.collection,
model: new Event({start: start, end: end, allDay: allDay})
});
eventView.render();
},
Another issue is, you're instantiating the EventsView and passing in the collection and models before the fetch call.
var events = new Events();
$.when(events.fetch()).then(function() {
// Create the Events view when the Events asynchronous operation completes.
new EventsView({el: $("#calendar"), collection: events}).render();
});
Edit: here's a JS Bin for additional changes.
I got this working except for events not actually disappearing from the calendar, even though they are deleted in the database. I dont know if this is the correct way to do this, probably not, but it worked. Model was undefined in EventView so I had to get the model from the collection and pass it on to EventView.
eventClick: function(fcEvent) {
console.log(fcEvent.id);
this.mymodel = this.collection.where({'id':fcEvent.id})[0];
this.eventView = new EventView({collection: this.collection, model: this.mymodel})
this.eventView.render();
},
change: function(event) {
// Look up the underlying event in the calendar and update its details from the model
var fcEvent = this.$el.fullCalendar('clientEvents', event.get('id'))[0];
fcEvent.title = event.get('title');
fcEvent.color = event.get('color');
console.log('change');
this.$el.fullCalendar('updateEvent', fcEvent);
},
eventDropOrResize: function(fcEvent) {
console.log(fcEvent);
// Lookup the model that has the ID of the event and update its attributes
this.collection.where({'id':fcEvent.id})[0].save({start: fcEvent.start, end: fcEvent.end});
},

Testing Ember Data - Switching to FixtureAdapter during test runs

I have an ember.js app and I'm setting up a DS.Store like this (view actual code):
(function (app) {
'use strict';
...
var store = DS.Store.extend({
revision: 12
});
app.Store = store;
})(window.Balanced);
Now I have a qunit test and in that test I would like to swap the default RESTAdapter for a FixtureAdapter so that I can setup fixtures for my models. I figure I need to write something like this but I'm not 100% sure:
(function () {
'use strict';
var fixtureAdapter;
module('tests.store.module', {
setup: function () {
fixtureAdapter = DS.FixtureAdapter.extend({
});
Balanced.Store.reopen({
adapter: fixtureAdapter
});
// TODO: how does this work?
Balanced.Marketplace.FIXTURES = [
{id: 1, name: '1'},
{id: 2, name: 'poop'},
{id: 3, name: 'poop'}
];
},
teardown: function () {
// teardown code
}
}
);
test("Marketplace query", function () {
var marketplaces = Balanced.Marketplace.find();
// TODO: how do I test this?
});
})();
For my basic unit testing with jasmine I setup the store manually like so (using the local storage adapter to avoid xhr requests)
describe ("CodeCamp.SessionView Tests", function(){
var get = Ember.get, set = Ember.set, sut, controller, session, store;
beforeEach(function(){
store = DS.Store.create({
revision: 11,
adapter: DS.LSAdapter.create()
});
sut = CodeCamp.SessionView.create();
controller = CodeCamp.SessionController.create();
controller.set("store", store);
sut.set("controller", controller);
session = CodeCamp.Session.createRecord({ id: 1, name: "First", room: "A", ratings: [], speakers: [], tags: []});
});
afterEach(function() {
Ember.run(function() {
store.destroy();
controller.destroy();
sut.destroy();
session.destroy();
});
store = null;
controller = null;
sut = null;
session = null;
});
it ("will create rating when form is valid", function(){
sut.set('score', '1234');
sut.set('feedback', 'abcd');
sut.addRating(session);
var ratings = CodeCamp.Session.find(1).get('ratings');
var rating = ratings.objectAt(0);
expect(rating.get('score')).toEqual('1234');
expect(rating.get('feedback')).toEqual('abcd');
expect(rating.get('session').get('id')).toEqual(1);
});
});
The test above goes end-to-end for the following ember view
CodeCamp.SessionView = Ember.View.extend({
templateName: 'session',
addRating: function(event) {
if (this.formIsValid()) {
var rating = this.buildRatingFromInputs(event);
this.get('controller').addRating(rating);
this.resetForm();
}
},
buildRatingFromInputs: function(session) {
var score = this.get('score');
var feedback = this.get('feedback');
return CodeCamp.Rating.createRecord(
{ score: score,
feedback: feedback,
session: session
});
},
formIsValid: function() {
var score = this.get('score');
var feedback = this.get('feedback');
if (score === undefined || feedback === undefined || score.trim() === "" || feedback.trim() === "") {
return false;
}
return true;
},
resetForm: function() {
this.set('score', '');
this.set('feedback', '');
}
});
If you want to see this entire app in action (just a sample ember app with a few basic jasmine tests) it's on github
https://github.com/toranb/ember-code-camp/