diff --git a/app/assets/javascripts/admin/order_cycles/services/order_cycle_resource.js.coffee b/app/assets/javascripts/admin/order_cycles/services/order_cycle_resource.js.coffee new file mode 100644 index 0000000000..4a5df3c44a --- /dev/null +++ b/app/assets/javascripts/admin/order_cycles/services/order_cycle_resource.js.coffee @@ -0,0 +1,8 @@ +angular.module("admin.orderCycles").factory 'OrderCycleResource', ($resource) -> + $resource('/admin/order_cycles/:id/:action.json', {}, { + 'index': + method: 'GET' + isArray: true + 'update': + method: 'PUT' + }) diff --git a/app/assets/javascripts/admin/order_cycles/services/order_cycles.js.coffee b/app/assets/javascripts/admin/order_cycles/services/order_cycles.js.coffee new file mode 100644 index 0000000000..48bdf57147 --- /dev/null +++ b/app/assets/javascripts/admin/order_cycles/services/order_cycles.js.coffee @@ -0,0 +1,34 @@ +angular.module("admin.orderCycles").factory 'OrderCycles', ($q, OrderCycleResource) -> + new class OrderCycles + orderCyclesByID: {} + pristineByID: {} + + index: (params={}, callback=null) -> + OrderCycleResource.index params, (data) => + for orderCycle in data + @orderCyclesByID[orderCycle.id] = orderCycle + @pristineByID[orderCycle.id] = angular.copy(orderCycle) + + (callback || angular.noop)(data) + + save: (order_cycle) -> + deferred = $q.defer() + order_cycle.$update({id: order_cycle.id}) + .then( (data) => + @pristineByID[order_cycle.id] = angular.copy(order_cycle) + deferred.resolve(data) + ).catch (response) -> + deferred.reject(response) + deferred.promise + + saved: (order_cycle) -> + @diff(order_cycle).length == 0 + + diff: (order_cycle) -> + changed = [] + for attr, value of order_cycle when not angular.equals(value, @pristineByID[order_cycle.id][attr]) + changed.push attr unless attr is "$$hashKey" + changed + + resetAttribute: (order_cycle, attribute) -> + order_cycle[attribute] = @pristineByID[order_cycle.id][attribute] diff --git a/spec/javascripts/unit/admin/order_cycles/services/order_cycles_spec.js.coffee b/spec/javascripts/unit/admin/order_cycles/services/order_cycles_spec.js.coffee new file mode 100644 index 0000000000..2004ec378b --- /dev/null +++ b/spec/javascripts/unit/admin/order_cycles/services/order_cycles_spec.js.coffee @@ -0,0 +1,106 @@ +describe "OrderCycles service", -> + OrderCycles = OrderCycleResource = orderCycles = $httpBackend = null + + beforeEach -> + module 'admin.orderCycles' + + this.addMatchers + toDeepEqual: (expected) -> + return angular.equals(this.actual, expected) + + inject ($q, _$httpBackend_, _OrderCycles_, _OrderCycleResource_) -> + OrderCycles = _OrderCycles_ + OrderCycleResource = _OrderCycleResource_ + $httpBackend = _$httpBackend_ + + describe "#index", -> + result = response = null + + beforeEach -> + response = [{ id: 5, name: 'OrderCycle 1'}] + $httpBackend.expectGET('/admin/order_cycles.json').respond 200, response + result = OrderCycles.index() + $httpBackend.flush() + + it "stores returned data in @orderCyclesByID, with ids as keys", -> + # OrderCycleResource returns instances of Resource rather than raw objects + expect(OrderCycles.orderCyclesByID).toDeepEqual { 5: response[0] } + + it "stores returned data in @pristineByID, with ids as keys", -> + expect(OrderCycles.pristineByID).toDeepEqual { 5: response[0] } + + it "returns an array of orderCycles", -> + expect(result).toDeepEqual response + + + describe "#save", -> + result = null + + describe "success", -> + orderCycle = null + resolved = false + + beforeEach -> + orderCycle = new OrderCycleResource({ id: 15, name: 'OrderCycle 1' }) + $httpBackend.expectPUT('/admin/order_cycles/15.json').respond 200, { id: 15, name: 'OrderCycle 1'} + OrderCycles.save(orderCycle).then( -> resolved = true) + $httpBackend.flush() + + it "updates the pristine copy of the orderCycle", -> + # Resource results have extra properties ($then, $promise) that cause them to not + # be exactly equal to the response object provided to the expectPUT clause above. + expect(OrderCycles.pristineByID[15]).toEqual orderCycle + + it "resolves the promise", -> + expect(resolved).toBe(true); + + + describe "failure", -> + orderCycle = null + rejected = false + + beforeEach -> + orderCycle = new OrderCycleResource( { id: 15, name: 'OrderCycle 1' } ) + $httpBackend.expectPUT('/admin/order_cycles/15.json').respond 422, { error: 'obj' } + OrderCycles.save(orderCycle).catch( -> rejected = true) + $httpBackend.flush() + + it "does not update the pristine copy of the orderCycle", -> + expect(OrderCycles.pristineByID[15]).toBeUndefined() + + it "rejects the promise", -> + expect(rejected).toBe(true); + + describe "#saved", -> + describe "when attributes of the object have been altered", -> + beforeEach -> + spyOn(OrderCycles, "diff").andReturn ["attr1", "attr2"] + + it "returns false", -> + expect(OrderCycles.saved({})).toBe false + + describe "when attributes of the object have not been altered", -> + beforeEach -> + spyOn(OrderCycles, "diff").andReturn [] + + it "returns false", -> + expect(OrderCycles.saved({})).toBe true + + + describe "diff", -> + beforeEach -> + OrderCycles.pristineByID = { 23: { id: 23, name: "ent1", is_primary_producer: true } } + + it "returns a list of properties that have been altered", -> + expect(OrderCycles.diff({ id: 23, name: "orderCycle123", is_primary_producer: true })).toEqual ["name"] + + + describe "resetAttribute", -> + orderCycle = { id: 23, name: "ent1", is_primary_producer: true } + + beforeEach -> + OrderCycles.pristineByID = { 23: { id: 23, name: "orderCycle1", is_primary_producer: true } } + + it "resets the specified value according to the pristine record", -> + OrderCycles.resetAttribute(orderCycle, "name") + expect(orderCycle.name).toEqual "orderCycle1"