diff --git a/app/assets/javascripts/darkswarm/controllers/checkout/accordion_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/checkout/accordion_controller.js.coffee index 38f41c6f6b..a0ba6f4e29 100644 --- a/app/assets/javascripts/darkswarm/controllers/checkout/accordion_controller.js.coffee +++ b/app/assets/javascripts/darkswarm/controllers/checkout/accordion_controller.js.coffee @@ -9,8 +9,8 @@ Darkswarm.controller "AccordionCtrl", ($scope, storage, $timeout) -> $scope.show = (name)-> $scope.accordion[name] = true - $timeout => - if $scope.checkout.$valid - for k, v of $scope.accordion - $scope.accordion[k] = false + #$timeout => + #if $scope.checkout.$valid + #for k, v of $scope.accordion + #$scope.accordion[k] = false diff --git a/app/assets/javascripts/darkswarm/controllers/checkout/billing_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/checkout/billing_controller.js.coffee index 4dc4d8f88c..dcc397396c 100644 --- a/app/assets/javascripts/darkswarm/controllers/checkout/billing_controller.js.coffee +++ b/app/assets/javascripts/darkswarm/controllers/checkout/billing_controller.js.coffee @@ -1,4 +1,4 @@ -Darkswarm.controller "BillingCtrl", ($scope) -> +Darkswarm.controller "BillingCtrl", ($scope, $timeout) -> angular.extend(this, new FieldsetMixin($scope)) $scope.name = "billing" $scope.nextPanel = "shipping" @@ -8,3 +8,4 @@ Darkswarm.controller "BillingCtrl", ($scope) -> $scope.order.bill_address.city, $scope.order.bill_address.zipcode] + #$timeout $scope.onTimeout diff --git a/app/assets/javascripts/darkswarm/controllers/checkout/checkout_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/checkout/checkout_controller.js.coffee index 64f0184e98..19d1810f38 100644 --- a/app/assets/javascripts/darkswarm/controllers/checkout/checkout_controller.js.coffee +++ b/app/assets/javascripts/darkswarm/controllers/checkout/checkout_controller.js.coffee @@ -1,13 +1,12 @@ -Darkswarm.controller "CheckoutCtrl", ($scope, storage, CheckoutFormState, Order, CurrentUser) -> +Darkswarm.controller "CheckoutCtrl", ($scope, storage, Order, CurrentUser) -> $scope.Order = Order - storage.bind $scope, "Order.order", {storeName: "order_#{Order.order.id}#{Order.order.user_id}"} + Order.bindFieldsToLocalStorage($scope) + $scope.order = Order.order # Ordering is important + $scope.secrets = Order.secrets $scope.enabled = if CurrentUser then true else false $scope.purchase = (event)-> event.preventDefault() $scope.Order.submit() - - $scope.CheckoutFormState = CheckoutFormState - storage.bind $scope, "CheckoutFormState.ship_address_same_as_billing", { defaultValue: true} diff --git a/app/assets/javascripts/darkswarm/controllers/checkout/details_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/checkout/details_controller.js.coffee index 8153c24f92..e0fef8e343 100644 --- a/app/assets/javascripts/darkswarm/controllers/checkout/details_controller.js.coffee +++ b/app/assets/javascripts/darkswarm/controllers/checkout/details_controller.js.coffee @@ -1,6 +1,5 @@ -Darkswarm.controller "DetailsCtrl", ($scope) -> +Darkswarm.controller "DetailsCtrl", ($scope, $timeout) -> angular.extend(this, new FieldsetMixin($scope)) - $scope.name = "details" $scope.nextPanel = "billing" @@ -12,3 +11,5 @@ Darkswarm.controller "DetailsCtrl", ($scope) -> $scope.fullName = -> [$scope.order.bill_address.firstname ? null, $scope.order.bill_address.lastname ? null].join(" ").trim() + + $timeout $scope.onTimeout diff --git a/app/assets/javascripts/darkswarm/controllers/checkout/payment_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/checkout/payment_controller.js.coffee index ee5ff84b4a..33a06e5d1f 100644 --- a/app/assets/javascripts/darkswarm/controllers/checkout/payment_controller.js.coffee +++ b/app/assets/javascripts/darkswarm/controllers/checkout/payment_controller.js.coffee @@ -1,3 +1,9 @@ -Darkswarm.controller "PaymentCtrl", ($scope) -> +Darkswarm.controller "PaymentCtrl", ($scope, $timeout) -> angular.extend(this, new FieldsetMixin($scope)) $scope.name = "payment" + + $scope.months = {1: "January", 2: "February", 3: "March", 4: "April", 5: "May", 6: "June", 7: "July", 8: "August", 9: "September", 10: "October", 11: "November", 12: "December"} + $scope.years = [moment().year()..(moment().year()+15)] + $scope.secrets.card_month = "1" + $scope.secrets.card_year = moment().year() + $timeout $scope.onTimeout diff --git a/app/assets/javascripts/darkswarm/controllers/checkout/shipping_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/checkout/shipping_controller.js.coffee index a6a38329b4..1d0280842d 100644 --- a/app/assets/javascripts/darkswarm/controllers/checkout/shipping_controller.js.coffee +++ b/app/assets/javascripts/darkswarm/controllers/checkout/shipping_controller.js.coffee @@ -1,5 +1,6 @@ -Darkswarm.controller "ShippingCtrl", ($scope) -> +Darkswarm.controller "ShippingCtrl", ($scope, $timeout) -> angular.extend(this, new FieldsetMixin($scope)) $scope.name = "shipping" $scope.nextPanel = "payment" + $timeout $scope.onTimeout diff --git a/app/assets/javascripts/darkswarm/directives/flash.js.coffee b/app/assets/javascripts/darkswarm/directives/flash.js.coffee index 86eb2a05a2..454c3304bd 100644 --- a/app/assets/javascripts/darkswarm/directives/flash.js.coffee +++ b/app/assets/javascripts/darkswarm/directives/flash.js.coffee @@ -1,12 +1,20 @@ Darkswarm.directive "ofnFlash", (flash, $timeout)-> + typePairings = + info: "standard" + error: "alert" + success: "success" scope: {} restrict: 'AE' - template: "{{flash.message}}" + templateUrl: "flash.html" + controller: ($scope)-> + $scope.closeAlert = (index)-> + $scope.flashes.splice(index, 1) + link: ($scope, element, attr) -> $scope.flashes = [] - show = (message, type)-> + show = (message, type)=> if message - $scope.flashes.push({message: message, type: type}) + $scope.flashes.push({message: message, type: typePairings[type]}) $timeout($scope.delete, 5000) $scope.delete = -> diff --git a/app/assets/javascripts/darkswarm/mixins/fieldset_mixin.js.coffee b/app/assets/javascripts/darkswarm/mixins/fieldset_mixin.js.coffee index ff01db5483..26b7ac3518 100644 --- a/app/assets/javascripts/darkswarm/mixins/fieldset_mixin.js.coffee +++ b/app/assets/javascripts/darkswarm/mixins/fieldset_mixin.js.coffee @@ -1,8 +1,12 @@ window.FieldsetMixin = ($scope)-> - $scope.next = (event)-> - event.preventDefault() + $scope.next = (event = false)-> + event.preventDefault() if event $scope.show $scope.nextPanel + $scope.onTimeout = -> + if $scope[$scope.name].$valid + $scope.next() + $scope.valid = -> $scope.form().$valid diff --git a/app/assets/javascripts/darkswarm/services/checkout_form_state.js.coffee b/app/assets/javascripts/darkswarm/services/checkout_form_state.js.coffee deleted file mode 100644 index 6fedb6b3c6..0000000000 --- a/app/assets/javascripts/darkswarm/services/checkout_form_state.js.coffee +++ /dev/null @@ -1,3 +0,0 @@ -Darkswarm.factory 'CheckoutFormState', ()-> - # Just a singleton place to store data about the form state - new class CheckoutFormState diff --git a/app/assets/javascripts/darkswarm/services/current_order.js.coffee b/app/assets/javascripts/darkswarm/services/current_order.js.coffee index 6e329a38f9..9d8cbda9ef 100644 --- a/app/assets/javascripts/darkswarm/services/current_order.js.coffee +++ b/app/assets/javascripts/darkswarm/services/current_order.js.coffee @@ -2,6 +2,5 @@ Darkswarm.factory 'CurrentOrder', (currentOrder) -> new class CurrentOrder constructor: -> @[k] = v for k, v of currentOrder - empty: => @line_items.length == 0 diff --git a/app/assets/javascripts/darkswarm/services/flash.js.coffee b/app/assets/javascripts/darkswarm/services/flash.js.coffee new file mode 100644 index 0000000000..2be131da1d --- /dev/null +++ b/app/assets/javascripts/darkswarm/services/flash.js.coffee @@ -0,0 +1,9 @@ +Darkswarm.factory 'Flash', (flash)-> + new class Flash + loadFlash: (rails_flash)-> + for type, message of rails_flash + switch type + when "notice" + flash.info = message + else + flash[type] = message diff --git a/app/assets/javascripts/darkswarm/services/order.js.coffee b/app/assets/javascripts/darkswarm/services/order.js.coffee index 8078cf8fc3..cea0f54d23 100644 --- a/app/assets/javascripts/darkswarm/services/order.js.coffee +++ b/app/assets/javascripts/darkswarm/services/order.js.coffee @@ -1,9 +1,23 @@ -Darkswarm.factory 'Order', ($resource, order, $http, CheckoutFormState, flash, Navigation)-> +Darkswarm.factory 'Order', ($resource, order, $http, flash, Navigation, storage)-> new class Order errors: {} + secrets: {} + order: order + ship_address_same_as_billing: true - constructor: -> - @order = order + #Whitelist of fields from Order.order to bind into localStorage + fieldsToBind: ["bill_address", "email", "payment_method_id", "shipping_method_id", "ship_address"] + + # Bind all the fields from fieldsToBind, + anything on the Order class + bindFieldsToLocalStorage: (scope)=> + prefix = "order_#{@order.id}#{@order.user_id}" + for field in @fieldsToBind + storage.bind scope, "Order.order.#{field}", + storeName: "#{prefix}_#{field}" + + storage.bind scope, "Order.ship_address_same_as_billing", + storeName: "#{prefix}_sameasbilling" + defaultValue: true submit: -> $http.put('/checkout', {order: @preprocess()}).success (data, status)=> @@ -24,12 +38,25 @@ Darkswarm.factory 'Order', ($resource, order, $http, CheckoutFormState, flash, N munged_order["ship_address_attributes"] = value when "payment_method_id" munged_order["payments_attributes"] = [{payment_method_id: value}] + when "form_state" # don't keep this shit else munged_order[name] = value - if CheckoutFormState.ship_address_same_as_billing + if @ship_address_same_as_billing munged_order.ship_address_attributes = munged_order.bill_address_attributes + + if @paymentMethod()?.method_type == 'gateway' + angular.extend munged_order.payments_attributes[0], { + source_attributes: + number: @secrets.card_number + month: @secrets.card_month + year: @secrets.card_year + verification_value: @secrets.card_verification_value + first_name: @order.bill_address.firstname + last_name: @order.bill_address.lastname + } + munged_order shippingMethod: -> @@ -39,7 +66,7 @@ Darkswarm.factory 'Order', ($resource, order, $http, CheckoutFormState, flash, N @shippingMethod()?.require_ship_address shippingPrice: -> - @shippingMethod()?.price + @shippingMethod()?.price || 0.0 paymentMethod: -> @order.payment_methods[@order.payment_method_id] diff --git a/app/assets/javascripts/templates/flash.html.haml b/app/assets/javascripts/templates/flash.html.haml new file mode 100644 index 0000000000..8767cf3743 --- /dev/null +++ b/app/assets/javascripts/templates/flash.html.haml @@ -0,0 +1,2 @@ +%alert{close: "closeAlert($index)", "ng-repeat" => "flash in flashes", type: "flash.type"} + {{ flash.message }} diff --git a/app/controllers/checkout_controller.rb b/app/controllers/checkout_controller.rb index 3879f16741..b0cdeebba2 100644 --- a/app/controllers/checkout_controller.rb +++ b/app/controllers/checkout_controller.rb @@ -15,7 +15,6 @@ class CheckoutController < Spree::CheckoutController end def update - if @order.update_attributes(params[:order]) fire_event('spree.checkout.update') while @order.state != "complete" @@ -26,7 +25,7 @@ class CheckoutController < Spree::CheckoutController if @order.next state_callback(:after) else - unless @order.errors.empty? + if @order.errors.present? flash[:error] = @order.errors.full_messages.to_sentence else flash[:error] = t(:payment_processing_failed) diff --git a/app/models/enterprise.rb b/app/models/enterprise.rb index 7c54bb1f10..3c851bde45 100644 --- a/app/models/enterprise.rb +++ b/app/models/enterprise.rb @@ -149,6 +149,16 @@ class Enterprise < ActiveRecord::Base self.relatives.is_distributor end + def website + strip_url read_attribute(:website) + end + def facebook + strip_url read_attribute(:facebook) + end + def linkedin + strip_url read_attribute(:linkedin) + end + def suppliers self.relatives.is_primary_producer end @@ -180,6 +190,10 @@ class Enterprise < ActiveRecord::Base private + def strip_url(url) + url.andand.sub /(https?:\/\/)?(www\.)?/, '' + end + def initialize_country self.address ||= Spree::Address.new self.address.country = Spree::Country.find_by_id(Spree::Config[:default_country_id]) if self.address.new_record? diff --git a/app/views/checkout/_order.rabl b/app/views/checkout/_order.rabl index 36e5a98eed..af37d2edf1 100644 --- a/app/views/checkout/_order.rabl +++ b/app/views/checkout/_order.rabl @@ -1,3 +1,6 @@ +#NOTE: when adding new fields for user input, it may want to be cached in localStorage +# If so, make sure to add it to Order.attributes_to_cache + object current_order attributes :id, :email, :shipping_method_id, :user_id @@ -18,7 +21,7 @@ child current_order.ship_address => :ship_address do end node :shipping_methods do - Hash[current_order.available_shipping_methods("front_end").collect { |method| + Hash[current_distributor.shipping_methods.uniq.collect { |method| [method.id, { require_ship_address: method.require_ship_address, price: method.compute_amount(current_order).to_f, @@ -30,7 +33,8 @@ end node :payment_methods do Hash[current_order.available_payment_methods.collect { |method| [method.id, { - name: method.name + name: method.name, + method_type: method.method_type }] }] end diff --git a/app/views/checkout/_shipping.html.haml b/app/views/checkout/_shipping.html.haml index e5208d5f60..8c88acf02a 100644 --- a/app/views/checkout/_shipping.html.haml +++ b/app/views/checkout/_shipping.html.haml @@ -42,10 +42,10 @@ = f.fields_for :ship_address, @order.ship_address do |sa| #ship_address{"ng-if" => "Order.requireShipAddress()"} %label - %input{type: :checkbox, "ng-model" => "CheckoutFormState.ship_address_same_as_billing"} + %input{type: :checkbox, "ng-model" => "Order.ship_address_same_as_billing"} Shipping address same as billing address? - %div.visible{"ng-if" => "!CheckoutFormState.ship_address_same_as_billing"} + %div.visible{"ng-if" => "!Order.ship_address_same_as_billing"} .row .small-12.columns = validated_input "Address", "order.ship_address.address1", "ofn-focus" => "accordion['shipping']" diff --git a/app/views/json/_producer.rabl b/app/views/json/_producer.rabl index 4c0efae8e1..1f4a99cdfc 100644 --- a/app/views/json/_producer.rabl +++ b/app/views/json/_producer.rabl @@ -1,4 +1,4 @@ -attributes :name, :id, :description, :long_description +attributes :id, :name, :description, :long_description, :website, :instagram, :facebook, :linkedin, :twitter node :promo_image do |producer| producer.promo_image.url diff --git a/app/views/shop/products/_form.html.haml b/app/views/shop/products/_form.html.haml index 6212ef746d..95bfdac31d 100644 --- a/app/views/shop/products/_form.html.haml +++ b/app/views/shop/products/_form.html.haml @@ -17,13 +17,18 @@ "ng-repeat" => "product in data.products | filter:query | orderBy:ordering.order | limitTo: limit track by product.id"} %div = render partial: "shop/products/summary" - %div{"bo-if" => "hasVariants"} = render partial: "shop/products/variants" - .variants.row{"bo-if" => "!hasVariants"} = render partial: "shop/products/master" + + %product{"ng-show" => "data.loading"} + .row.summary + .small-12.columns.text-center + Loading products + .row .small-12.columns %input.button.primary.right.add_to_cart{type: :submit, value: "Add to Cart"} + diff --git a/app/views/shopping_shared/_about.html.haml b/app/views/shopping_shared/_about.html.haml index e03eb05255..5e630b4d7f 100644 --- a/app/views/shopping_shared/_about.html.haml +++ b/app/views/shopping_shared/_about.html.haml @@ -2,7 +2,8 @@ .row .small-12.large-9.columns %p= current_distributor.long_description.andand.html_safe - .small-12.large-3.columns - / Hide image until image styles are working correctly: - / %img.about.right{src: current_distributor.promo_image.url(:large)} + + - if current_distributor.promo_image.exists? + .small-12.large-3.columns + %img.about.right{src: current_distributor.promo_image.url(:large)} diff --git a/app/views/shopping_shared/_contact.html.haml b/app/views/shopping_shared/_contact.html.haml index 89eff0a723..249f0092c8 100644 --- a/app/views/shopping_shared/_contact.html.haml +++ b/app/views/shopping_shared/_contact.html.haml @@ -19,7 +19,7 @@ %ul.small-block-grid-1.large-block-grid-2{bindonce: true} - unless current_distributor.website.blank? %li - %a{href: current_distributor.website, target: "_blank" } + %a{href: "http://#{current_distributor.website}", target: "_blank" } %i.ofn-i_049-web = current_distributor.website @@ -32,24 +32,24 @@ - unless current_distributor.twitter.blank? %li - %a{href: current_distributor.twitter, target: "_blank" } + %a{href: "http://twitter.com/#{current_distributor.twitter}", target: "_blank" } %i.ofn-i_041-twitter = current_distributor.twitter - unless current_distributor.facebook.blank? %li - %a{href: current_distributor.facebook, target: "_blank" } + %a{href: "http://#{current_distributor.facebook}", target: "_blank" } %i.ofn-i_044-facebook = current_distributor.facebook - unless current_distributor.linkedin.blank? %li - %a{href: current_distributor.linkedin, target: "_blank" } + %a{href: "http://#{current_distributor.linkedin}", target: "_blank" } %i.ofn-i_042-linkedin = current_distributor.linkedin - unless current_distributor.instagram.blank? %li - %a{href: current_distributor.instagram, target: "_blank" } + %a{href: "http://instagram.com.#{current_distributor.instagram}", target: "_blank" } %i.ofn-i_043-instagram = current_distributor.instagram diff --git a/app/views/shopping_shared/_details.html.haml b/app/views/shopping_shared/_details.html.haml index 2a8e1b10b1..1b30627533 100644 --- a/app/views/shopping_shared/_details.html.haml +++ b/app/views/shopping_shared/_details.html.haml @@ -1,7 +1,8 @@ %navigation %distributor.details.row #distributor_title - %img.left{src: current_distributor.logo.url(:thumb)} + - if current_distributor.logo.exists? + %img.left{src: current_distributor.logo.url(:thumb)} %h3 = current_distributor.name %location= current_distributor.address.city diff --git a/app/views/spree/checkout/payment/_gateway.html.haml b/app/views/spree/checkout/payment/_gateway.html.haml new file mode 100644 index 0000000000..5cd25dafba --- /dev/null +++ b/app/views/spree/checkout/payment/_gateway.html.haml @@ -0,0 +1,8 @@ += validated_input "Card Number", "secrets.card_number", required: true, maxlength: 19, autocomplete: "off" + +%label{for: "secrets.card_month"} Expiry Date +%select{"ng-model" => "secrets.card_month", "ng-options" => "number as name for (number, name) in months", name: "secrets.card_month", required: true} + +%select{"ng-model" => "secrets.card_year", "ng-options" => "year for year in years", name: "secrets.card_year", required: true} + += validated_input "CVV", "secrets.card_verification_value", required: true diff --git a/db/migrate/20140522044009_add_primary_taxon_to_products.rb b/db/migrate/20140522044009_add_primary_taxon_to_products.rb index 28c27f820f..d985d7f1b8 100644 --- a/db/migrate/20140522044009_add_primary_taxon_to_products.rb +++ b/db/migrate/20140522044009_add_primary_taxon_to_products.rb @@ -6,7 +6,9 @@ class AddPrimaryTaxonToProducts < ActiveRecord::Migration add_foreign_key :spree_products, :spree_taxons, column: :primary_taxon_id Spree::Product.all.each do |p| - p.update_column :primary_taxon_id, (p.taxons.first || Spree::Taxon.first) + primary_taxon = p.taxons.where('spree_taxons.name != ?', 'specials').first + first_taxon = Spree::Taxonomy.find_by_name('Products').andand.root || Spree::Taxon.first + p.update_column :primary_taxon_id, (primary_taxon || first_taxon) end change_column :spree_products, :primary_taxon_id, :integer, null: false diff --git a/spec/features/consumer/shopping/checkout_spec.rb b/spec/features/consumer/shopping/checkout_spec.rb index c24456b16a..dd84a1e8ca 100644 --- a/spec/features/consumer/shopping/checkout_spec.rb +++ b/spec/features/consumer/shopping/checkout_spec.rb @@ -96,37 +96,57 @@ feature "As a consumer I want to check out my cart", js: true do end place_order - page.should have_content "Your order has been processed successfully", wait: 10 + page.should have_content "Your order has been processed successfully" ActionMailer::Base.deliveries.length.should == 1 email = ActionMailer::Base.deliveries.last site_name = Spree::Config[:site_name] email.subject.should include "#{site_name} Order Confirmation" end - it "takes us to the order confirmation page when submitted with 'same as billing address' checked" do - toggle_shipping - choose sm1.name - toggle_payment - choose pm1.name - toggle_details - within "#details" do - fill_in "First Name", with: "Will" - fill_in "Last Name", with: "Marshall" - fill_in "Email", with: "test@test.com" - fill_in "Phone", with: "0468363090" + context "with basic details filled" do + before do + toggle_shipping + choose sm1.name + toggle_payment + choose pm1.name + toggle_details + within "#details" do + fill_in "First Name", with: "Will" + fill_in "Last Name", with: "Marshall" + fill_in "Email", with: "test@test.com" + fill_in "Phone", with: "0468363090" + end + toggle_billing + within "#billing" do + fill_in "City", with: "Melbourne" + fill_in "Postcode", with: "3066" + fill_in "Address", with: "123 Your Face" + select "Australia", from: "Country" + select "Victoria", from: "State" + end + toggle_shipping + check "Shipping address same as billing address?" end - toggle_billing - within "#billing" do - fill_in "City", with: "Melbourne" - fill_in "Postcode", with: "3066" - fill_in "Address", with: "123 Your Face" - select "Australia", from: "Country" - select "Victoria", from: "State" + + it "takes us to the order confirmation page when submitted with 'same as billing address' checked" do + place_order + page.should have_content "Your order has been processed successfully" + end + + context "with a credit card payment method" do + let!(:pm1) { create(:payment_method, distributors: [distributor], name: "Roger rabbit", type: "Spree::Gateway::Bogus") } + + it "takes us to the order confirmation page when submitted with a valid credit card" do + toggle_payment + fill_in 'Card Number', with: "4111111111111111" + select 'February', from: 'secrets.card_month' + select (Date.today.year+1).to_s, from: 'secrets.card_year' + fill_in 'CVV', with: '123' + + place_order + page.should have_content "Your order has been processed successfully" + end end - toggle_shipping - check "Shipping address same as billing address?" - place_order - page.should have_content "Your order has been processed successfully", wait: 10 end end end diff --git a/spec/javascripts/unit/darkswarm/controllers/checkout/accordion_controller_spec.js.coffee b/spec/javascripts/unit/darkswarm/controllers/checkout/accordion_controller_spec.js.coffee index d35fb93e86..8e59248806 100644 --- a/spec/javascripts/unit/darkswarm/controllers/checkout/accordion_controller_spec.js.coffee +++ b/spec/javascripts/unit/darkswarm/controllers/checkout/accordion_controller_spec.js.coffee @@ -30,11 +30,3 @@ describe "AccordionCtrl", -> scope.order = id: 129 ctrl = $controller 'AccordionCtrl', {$scope: scope} - - it "automatically closes all sections if the entire form is valid", -> - waitsFor -> - (scope.accordion.details and - scope.accordion.shipping and - scope.accordion.payment and - scope.accordion.billing) == false - , "the accordion to close", 100 diff --git a/spec/javascripts/unit/darkswarm/controllers/checkout/checkout_controller_spec.js.coffee b/spec/javascripts/unit/darkswarm/controllers/checkout/checkout_controller_spec.js.coffee index 8632cb49ec..edda65e0cf 100644 --- a/spec/javascripts/unit/darkswarm/controllers/checkout/checkout_controller_spec.js.coffee +++ b/spec/javascripts/unit/darkswarm/controllers/checkout/checkout_controller_spec.js.coffee @@ -10,13 +10,18 @@ describe "CheckoutCtrl", -> Order = submit: -> navigate: -> + bindFieldsToLocalStorage: -> order: id: 1 + email: "public" + secrets: + card_number: "this is a secret" describe "with user", -> beforeEach -> inject ($controller, $rootScope) -> scope = $rootScope.$new() + spyOn(Order, "bindFieldsToLocalStorage") ctrl = $controller 'CheckoutCtrl', {$scope: scope, Order: Order, CurrentUser: {}} it "delegates to the service on submit", -> @@ -29,6 +34,9 @@ describe "CheckoutCtrl", -> it "is enabled", -> expect(scope.enabled).toEqual true + it "triggers localStorage binding", -> + expect(Order.bindFieldsToLocalStorage).toHaveBeenCalled() + describe "without user", -> beforeEach -> inject ($controller, $rootScope) -> @@ -37,3 +45,8 @@ describe "CheckoutCtrl", -> it "is disabled", -> expect(scope.enabled).toEqual false + + it "does not store secrets in local storage", -> + keys = (localStorage.key(i) for i in [0..localStorage.length]) + for key in keys + expect(localStorage.getItem(key)).not.toMatch Order.secrets.card_number diff --git a/spec/javascripts/unit/darkswarm/services/order_spec.js.coffee b/spec/javascripts/unit/darkswarm/services/order_spec.js.coffee index 4f6c711f99..f6a4112eef 100644 --- a/spec/javascripts/unit/darkswarm/services/order_spec.js.coffee +++ b/spec/javascripts/unit/darkswarm/services/order_spec.js.coffee @@ -2,16 +2,22 @@ describe 'Order service', -> Order = null orderData = null $httpBackend = null - CheckoutFormState = null Navigation = null flash = null + storage = null + scope = null beforeEach -> - orderData = { + orderData = id: 3102 payment_method_id: null - bill_address: {test: "foo"} + email: "test@test.com" + bill_address: + test: "foo" + firstname: "Robert" + lastname: "Harrington" ship_address: {test: "bar"} + user_id: 901 shipping_methods: 7: require_ship_address: true @@ -23,22 +29,51 @@ describe 'Order service', -> payment_methods: 99: test: "foo" - } + method_type: "gateway" + 123: + test: "bar" + method_type: "check" + angular.module('Darkswarm').value('order', orderData) module 'Darkswarm' - inject ($injector, _$httpBackend_)-> + inject ($injector, _$httpBackend_, _storage_, $rootScope)-> $httpBackend = _$httpBackend_ + storage = _storage_ Order = $injector.get("Order") + scope = $rootScope.$new() + scope.Order = Order Navigation = $injector.get("Navigation") flash = $injector.get("flash") - CheckoutFormState = $injector.get("CheckoutFormState") spyOn(Navigation, "go") # Stubbing out writes to window.location it "defaults to no shipping method", -> expect(Order.order.shipping_method_id).toEqual null expect(Order.shippingMethod()).toEqual undefined + it "has a shipping price of zero with no shipping method", -> + expect(Order.shippingPrice()).toEqual 0.0 + + it "binds to localStorage when given a scope", -> + spyOn(storage, "bind") + Order.fieldsToBind = ["testy"] + Order.bindFieldsToLocalStorage({}) + prefix = "order_#{Order.order.id}#{Order.order.user_id}" + expect(storage.bind).toHaveBeenCalledWith({}, "Order.order.testy", {storeName: "#{prefix}_testy"}) + expect(storage.bind).toHaveBeenCalledWith({}, "Order.ship_address_same_as_billing", {storeName: "#{prefix}_sameasbilling", defaultValue: true}) + + it "binds order to local storage", -> + Order.bindFieldsToLocalStorage(scope) + prefix = "order_#{Order.order.id}#{Order.order.user_id}" + expect(localStorage.getItem("#{prefix}_email")).toMatch "test@test.com" + + it "does not store secrets in local storage", -> + Order.secrets = + card_number: "superfuckingsecret" + Order.bindFieldsToLocalStorage(scope) + keys = (localStorage.key(i) for i in [0..localStorage.length]) + for key in keys + expect(localStorage.getItem(key)).not.toMatch Order.secrets.card_number describe "with shipping method", -> beforeEach -> @@ -57,7 +92,7 @@ describe 'Order service', -> it 'Gets the current payment method', -> expect(Order.paymentMethod()).toEqual null Order.order.payment_method_id = 99 - expect(Order.paymentMethod()).toEqual {test: "foo"} + expect(Order.paymentMethod()).toEqual {test: "foo", method_type: "gateway"} it "Posts the Order to the server", -> $httpBackend.expectPUT("/checkout", {order: Order.preprocess()}).respond 200, {path: "test"} @@ -76,14 +111,39 @@ describe 'Order service', -> $httpBackend.flush() expect(Order.errors).toEqual {error: "frogs"} - it "Munges the order attributes to add _attributes as Rails needs", -> - expect(Order.preprocess().bill_address_attributes).not.toBe(undefined) - expect(Order.preprocess().bill_address).toBe(undefined) - expect(Order.preprocess().ship_address_attributes).not.toBe(undefined) - expect(Order.preprocess().ship_address).toBe(undefined) + describe "data preprocessing", -> + beforeEach -> + Order.order.payment_method_id = 99 - it "Munges the order attributes to clone ship address from bill address", -> - CheckoutFormState.ship_address_same_as_billing = false - expect(Order.preprocess().ship_address_attributes).toEqual(orderData.ship_address) - CheckoutFormState.ship_address_same_as_billing = true - expect(Order.preprocess().ship_address_attributes).toEqual(orderData.bill_address) + Order.secrets = + card_number: "1234567890123456" + card_month: "10" + card_year: "2015" + card_verification_value: "123" + + it "munges the order attributes to add _attributes as Rails needs", -> + expect(Order.preprocess().bill_address_attributes).not.toBe(undefined) + expect(Order.preprocess().bill_address).toBe(undefined) + expect(Order.preprocess().ship_address_attributes).not.toBe(undefined) + expect(Order.preprocess().ship_address).toBe(undefined) + + it "munges the order attributes to clone ship address from bill address", -> + Order.ship_address_same_as_billing = false + expect(Order.preprocess().ship_address_attributes).toEqual(orderData.ship_address) + Order.ship_address_same_as_billing = true + expect(Order.preprocess().ship_address_attributes).toEqual(orderData.bill_address) + + it "creates attributes for card fields", -> + source_attributes = Order.preprocess().payments_attributes[0].source_attributes + expect(source_attributes).toBeDefined() + expect(source_attributes.number).toBe Order.secrets.card_number + expect(source_attributes.month).toBe Order.secrets.card_month + expect(source_attributes.year).toBe Order.secrets.card_year + expect(source_attributes.verification_value).toBe Order.secrets.card_verification_value + expect(source_attributes.first_name).toBe Order.order.bill_address.firstname + expect(source_attributes.last_name).toBe Order.order.bill_address.lastname + + it "does not create attributes for card fields when no card is supplied", -> + Order.order.payment_method_id = 123 + source_attributes = Order.preprocess().payments_attributes[0].source_attributes + expect(source_attributes).not.toBeDefined() diff --git a/spec/models/enterprise_spec.rb b/spec/models/enterprise_spec.rb index 23f300fba5..542d95a4b0 100644 --- a/spec/models/enterprise_spec.rb +++ b/spec/models/enterprise_spec.rb @@ -445,4 +445,18 @@ describe Enterprise do supplier.supplied_taxons.should == [taxon1, taxon2] end end + + describe "presentation of attributes" do + let(:distributor) { + create(:distributor_enterprise, + website: "http://www.google.com", + facebook: "www.facebook.com/roger", + linkedin: "http://linkedin.com") + } + it "strips http and www from url fields" do + distributor.website.should == "google.com" + distributor.facebook.should == "facebook.com/roger" + distributor.linkedin.should == "linkedin.com" + end + end end