Skip to content

Commit

Permalink
[BUGFIX release] Transition to loaded.saved state after rollback
Browse files Browse the repository at this point in the history
Closes #3499 #3498
  • Loading branch information
tchak committed Jul 17, 2015
1 parent 0be4bd3 commit 50c63eb
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 29 deletions.
1 change: 1 addition & 0 deletions packages/ember-data/lib/system/model/states.js
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,7 @@ var DirtyState = {

rolledBack: function(internalModel) {
internalModel.clearErrorMessages();
internalModel.transitionTo('loaded.saved');
internalModel.triggerLater('ready');
},

Expand Down
67 changes: 38 additions & 29 deletions packages/ember-data/tests/unit/model/rollback-attributes-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ test("a record's changes can be made if it fails to save", function() {
});

test("a deleted record's attributes can be rollbacked if it fails to save, record arrays are updated accordingly", function() {
expect(7);
expect(8);
env.adapter.deleteRecord = function(store, type, snapshot) {
return Ember.RSVP.reject();
};
Expand All @@ -136,6 +136,7 @@ test("a deleted record's attributes can be rollbacked if it fails to save, recor
});
equal(person.get('isDeleted'), false);
equal(person.get('isError'), false);
equal(person.get('hasDirtyAttributes'), false, "must be not dirty");
}).then(function() {
equal(people.get('length'), 1, "the underlying record array is updated accordingly in an asynchronous way");
});
Expand All @@ -161,10 +162,14 @@ test("new record's attributes can be rollbacked", function() {

test("invalid new record's attributes can be rollbacked", function() {
var person;
var error = new DS.InvalidError([
{
detail: 'is invalid',
source: { pointer: 'data/attributes/name' }
}
]);
var adapter = DS.RESTAdapter.extend({
ajax: function(url, type, hash) {
var adapter = this;

return new Ember.RSVP.Promise(function(resolve, reject) {
/* If InvalidError is passed back in the reject it will throw the
exception which will bubble up the call stack (crashing the test)
Expand All @@ -173,13 +178,9 @@ test("invalid new record's attributes can be rollbacked", function() {
completes without failure and the failure hits the failure route
of the promise instead of crashing the save. */
Ember.run.next(function() {
reject(adapter.ajaxError({ name: 'is invalid' }));
reject(error);
});
});
},

ajaxError: function(jqXHR) {
return new DS.InvalidError(jqXHR);
}
});

Expand Down Expand Up @@ -231,10 +232,15 @@ test("invalid record's attributes can be rollbacked", function() {
name: DS.attr()
});

var error = new DS.InvalidError([
{
detail: 'is invalid',
source: { pointer: 'data/attributes/name' }
}
]);

var adapter = DS.RESTAdapter.extend({
ajax: function(url, type, hash) {
var adapter = this;

return new Ember.RSVP.Promise(function(resolve, reject) {
/* If InvalidError is passed back in the reject it will throw the
exception which will bubble up the call stack (crashing the test)
Expand All @@ -243,13 +249,9 @@ test("invalid record's attributes can be rollbacked", function() {
completes without failure and the failure hits the failure route
of the promise instead of crashing the save. */
Ember.run.next(function() {
reject(adapter.ajaxError({ name: 'is invalid' }));
reject(error);
});
});
},

ajaxError: function(jqXHR) {
return new DS.InvalidError(jqXHR);
}
});

Expand All @@ -264,6 +266,7 @@ test("invalid record's attributes can be rollbacked", function() {
dog.save().then(null, async(function() {
dog.rollbackAttributes();

equal(dog.get('hasDirtyAttributes'), false, "must not be dirty");
equal(dog.get('name'), "Pluto");
ok(dog.get('isValid'));
}));
Expand All @@ -276,10 +279,15 @@ test("invalid record's attributes rolled back to correct state after set", funct
breed: DS.attr()
});

var error = new DS.InvalidError([
{
detail: 'is invalid',
source: { pointer: 'data/attributes/name' }
}
]);

var adapter = DS.RESTAdapter.extend({
ajax: function(url, type, hash) {
var adapter = this;

return new Ember.RSVP.Promise(function(resolve, reject) {
/* If InvalidError is passed back in the reject it will throw the
exception which will bubble up the call stack (crashing the test)
Expand All @@ -288,13 +296,9 @@ test("invalid record's attributes rolled back to correct state after set", funct
completes without failure and the failure hits the failure route
of the promise instead of crashing the save. */
Ember.run.next(function() {
reject(adapter.ajaxError({ name: 'is invalid' }));
reject(error);
});
});
},

ajaxError: function(jqXHR) {
return new Error(jqXHR);
}
});

Expand All @@ -310,6 +314,8 @@ test("invalid record's attributes rolled back to correct state after set", funct
dog.save().then(null, async(function() {
equal(dog.get('name'), "is a dwarf planet");
equal(dog.get('breed'), "planet");
ok(Ember.isPresent(dog.get('errors.name')));
equal(dog.get('errors.name.length'), 1);

run(function() {
dog.set('name', 'Seymour Asses');
Expand All @@ -324,6 +330,8 @@ test("invalid record's attributes rolled back to correct state after set", funct

equal(dog.get('name'), "Pluto");
equal(dog.get('breed'), "Disney");
equal(dog.get('hasDirtyAttributes'), false, "must not be dirty");
ok(Ember.isEmpty(dog.get('errors.name')));
ok(dog.get('isValid'));
}));
});
Expand All @@ -334,19 +342,20 @@ test("when destroying a record setup the record state to invalid, the record's a
name: DS.attr()
});

var error = new DS.InvalidError([
{
detail: 'is invalid',
source: { pointer: 'data/attributes/name' }
}
]);

var adapter = DS.RESTAdapter.extend({
ajax: function(url, type, hash) {
var adapter = this;

return new Ember.RSVP.Promise(function(resolve, reject) {
Ember.run.next(function() {
reject(adapter.ajaxError({ name: 'is invalid' }));
reject(error);
});
});
},

ajaxError: function(jqXHR) {
return new DS.InvalidError(jqXHR);
}
});

Expand Down

0 comments on commit 50c63eb

Please sign in to comment.