diff --git a/app/assets/javascripts/darkswarm/services/checkout.js.coffee b/app/assets/javascripts/darkswarm/services/checkout.js.coffee index 83cf018365..f0da646ebe 100644 --- a/app/assets/javascripts/darkswarm/services/checkout.js.coffee +++ b/app/assets/javascripts/darkswarm/services/checkout.js.coffee @@ -14,15 +14,28 @@ Darkswarm.factory 'Checkout', ($injector, CurrentOrder, ShippingMethods, StripeE submit: => Loading.message = t 'submitting_order' - $http.put('/checkout.json', {order: @preprocess()}).success (data, status)=> - Navigation.go data.path - .error (response, status)=> - if response.path - Navigation.go response.path - else - Loading.clear() - @errors = response.errors - RailsFlashLoader.loadFlash(response.flash) + $http.put('/checkout.json', {order: @preprocess()}) + .then (response) => + Navigation.go response.data.path + .catch (response) => + try + @handle_checkout_error_response(response) + catch error + @loadFlash(error: t("checkout.failed")) # inform the user about the unexpected error + throw error # generate a BugsnagJS alert + + handle_checkout_error_response: (response) => + if response.data.path + Navigation.go response.data.path + else + throw response unless response.data.flash + + @errors = response.data.errors + @loadFlash(response.data.flash) + + loadFlash: (flash) => + Loading.clear() + RailsFlashLoader.loadFlash(flash) # Rails wants our Spree::Address data to be provided with _attributes preprocess: -> diff --git a/spec/javascripts/unit/darkswarm/services/checkout_spec.js.coffee b/spec/javascripts/unit/darkswarm/services/checkout_spec.js.coffee index 4ff2f0d97a..d7e23b457b 100644 --- a/spec/javascripts/unit/darkswarm/services/checkout_spec.js.coffee +++ b/spec/javascripts/unit/darkswarm/services/checkout_spec.js.coffee @@ -3,10 +3,13 @@ describe 'Checkout service', -> orderData = null $httpBackend = null Navigation = null + navigationSpy = null flash = null scope = null FlashLoaderMock = - loadFlash: (arg)-> + loadFlash: (arg) -> + Loading = + clear: (arg)-> paymentMethods = [{ id: 99 test: "foo" @@ -48,6 +51,7 @@ describe 'Checkout service', -> module 'Darkswarm' module ($provide)-> $provide.value "RailsFlashLoader", FlashLoaderMock + $provide.value "Loading", Loading $provide.value "currentOrder", orderData $provide.value "shippingMethods", shippingMethods $provide.value "paymentMethods", paymentMethods @@ -61,7 +65,7 @@ describe 'Checkout service', -> scope.Checkout = Checkout Navigation = $injector.get("Navigation") flash = $injector.get("flash") - spyOn(Navigation, "go") # Stubbing out writes to window.location + navigationSpy = spyOn(Navigation, "go") # Stubbing out writes to window.location it "defaults to no shipping method", -> expect(Checkout.order.shipping_method_id).toEqual null @@ -116,12 +120,46 @@ describe 'Checkout service', -> $httpBackend.flush() expect(FlashLoaderMock.loadFlash).toHaveBeenCalledWith {error: "frogs"} - it "puts errors into the scope", -> - $httpBackend.expectPUT("/checkout.json").respond 400, {errors: {error: "frogs"}} + it "puts errors into the scope when there is a flash messages", -> + $httpBackend.expectPUT("/checkout.json").respond 400, {errors: {error: "frogs"}, flash: {error: "flash frogs"}} Checkout.submit() + $httpBackend.flush() expect(Checkout.errors).toEqual {error: "frogs"} + it "throws exception and sends generic flash message when there are errors but no flash message", -> + $httpBackend.expectPUT("/checkout.json").respond 400, {errors: {error: "broken response"}} + try + Checkout.submit() + $httpBackend.flush() + catch error + expect(error.data.errors.error).toBe("broken response") + + expect(Checkout.errors).toEqual {} + + it "throws an exception and sends a flash message to the flash service when reponse doesnt contain errors nor a flash message", -> + spyOn(FlashLoaderMock, "loadFlash") # Stubbing out writes to window.location + $httpBackend.expectPUT("/checkout.json").respond 400, "broken response" + try + Checkout.submit() + $httpBackend.flush() + catch error + expect(error.data).toBe("broken response") + + expect(FlashLoaderMock.loadFlash).toHaveBeenCalledWith({ error: t("checkout.failed") }) + + it "throws an exception and sends a flash message to the flash service when an exception is thrown while handling the error", -> + spyOn(FlashLoaderMock, "loadFlash") # Stubbing out writes to window.location + navigationSpy.and.callFake(-> throw "unexpected error") + $httpBackend.expectPUT("/checkout.json").respond 400, {path: 'path'} + try + Checkout.submit() + $httpBackend.flush() + catch error + expect(error).toBe("unexpected error") + + expect(FlashLoaderMock.loadFlash).toHaveBeenCalledWith({ error: t("checkout.failed") }) + describe "when using the Stripe Connect gateway", -> beforeEach inject ($injector, StripeElements) -> Checkout.order.payment_method_id = 666