diff --git a/app/controllers/admin/connected_apps_controller.rb b/app/controllers/admin/connected_apps_controller.rb index a5308d4984..083afd946d 100644 --- a/app/controllers/admin/connected_apps_controller.rb +++ b/app/controllers/admin/connected_apps_controller.rb @@ -44,9 +44,9 @@ module Admin create_connected_app - jwt_service = VineJwtService.new(secret: connected_app_params[:vine_secret]) - vine_api = VineApiService.new(api_key: connected_app_params[:vine_api_key], - jwt_generator: jwt_service) + jwt_service = Vine::JwtService.new(secret: connected_app_params[:vine_secret]) + vine_api = Vine::ApiService.new(api_key: connected_app_params[:vine_api_key], + jwt_generator: jwt_service) if !@app.connect(api_key: connected_app_params[:vine_api_key], secret: connected_app_params[:vine_secret], vine_api:) diff --git a/app/controllers/checkout_controller.rb b/app/controllers/checkout_controller.rb index c5bce3a5e1..904d0d5b05 100644 --- a/app/controllers/checkout_controller.rb +++ b/app/controllers/checkout_controller.rb @@ -79,8 +79,8 @@ class CheckoutController < BaseController return true if redirect_to_payment_gateway # Redeem VINE voucher - vine_voucher_redeemer = VineVoucherRedeemerService.new(order: @order) - if vine_voucher_redeemer.call == false + vine_voucher_redeemer = Vine::VoucherRedeemerService.new(order: @order) + if vine_voucher_redeemer.redeem == false # rubocop:disable Rails/DeprecatedActiveModelErrorsMethods flash[:error] = if vine_voucher_redeemer.errors.keys.include?(:redeeming_failed) vine_voucher_redeemer.errors[:redeeming_failed] diff --git a/app/controllers/spree/admin/payments_controller.rb b/app/controllers/spree/admin/payments_controller.rb index bd60138d70..acbeabe4db 100644 --- a/app/controllers/spree/admin/payments_controller.rb +++ b/app/controllers/spree/admin/payments_controller.rb @@ -191,8 +191,8 @@ module Spree end def redeem_vine_voucher - vine_voucher_redeemer = VineVoucherRedeemerService.new(order: @order) - if vine_voucher_redeemer.call == false + vine_voucher_redeemer = Vine::VoucherRedeemerService.new(order: @order) + if vine_voucher_redeemer.redeem == false # rubocop:disable Rails/DeprecatedActiveModelErrorsMethods flash[:error] = if vine_voucher_redeemer.errors.keys.include?(:redeeming_failed) vine_voucher_redeemer.errors[:redeeming_failed] diff --git a/app/controllers/voucher_adjustments_controller.rb b/app/controllers/voucher_adjustments_controller.rb index b8f3a3f1e4..9fa62257b2 100644 --- a/app/controllers/voucher_adjustments_controller.rb +++ b/app/controllers/voucher_adjustments_controller.rb @@ -87,7 +87,7 @@ class VoucherAdjustmentsController < BaseController end def vine_voucher - vine_voucher_validator = VineVoucherValidatorService.new( + vine_voucher_validator = Vine::VoucherValidatorService.new( voucher_code: voucher_params[:voucher_code], enterprise: @order.distributor ) voucher = vine_voucher_validator.validate diff --git a/app/services/vine/api_service.rb b/app/services/vine/api_service.rb new file mode 100644 index 0000000000..cdf1326be3 --- /dev/null +++ b/app/services/vine/api_service.rb @@ -0,0 +1,77 @@ +# frozen_string_literal: true + +require "faraday" + +module Vine + class ApiService + attr_reader :api_key, :jwt_generator + + def initialize(api_key:, jwt_generator:) + @vine_api_url = ENV.fetch("VINE_API_URL") + @api_key = api_key + @jwt_generator = jwt_generator + end + + def my_team + my_team_url = "#{@vine_api_url}/my-team" + + response = connection.get(my_team_url) + + log_error("Vine::ApiService#my_team", response) + + response + end + + def voucher_validation(voucher_short_code) + voucher_validation_url = "#{@vine_api_url}/voucher-validation" + + response = connection.post( + voucher_validation_url, + { type: "voucher_code", value: voucher_short_code }, + 'Content-Type': "application/json" + ) + + log_error("Vine::ApiService#voucher_validation", response) + + response + end + + def voucher_redemptions(voucher_id, voucher_set_id, amount) + voucher_redemptions_url = "#{@vine_api_url}/voucher-redemptions" + + response = connection.post( + voucher_redemptions_url, + { voucher_id:, voucher_set_id:, amount: amount.to_i }, + 'Content-Type': "application/json" + ) + + log_error("Vine::ApiService#voucher_redemptions", response) + + response + end + + private + + def connection + jwt = jwt_generator.generate_token + Faraday.new( + request: { timeout: 30 }, + headers: { + 'X-Authorization': "JWT #{jwt}", + Accept: "application/json" + } + ) do |f| + f.request :json + f.response :json + f.request :authorization, 'Bearer', api_key + end + end + + def log_error(prefix, response) + return if response.success? + + Rails.logger.error "#{prefix} -- response_status: #{response.status}" + Rails.logger.error "#{prefix} -- response: #{response.body}" + end + end +end diff --git a/app/services/vine/jwt_service.rb b/app/services/vine/jwt_service.rb new file mode 100644 index 0000000000..acecc4f784 --- /dev/null +++ b/app/services/vine/jwt_service.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +module Vine + class JwtService + ALGORITHM = "HS256" + ISSUER = "openfoodnetwork" + + def initialize(secret: ) + @secret = secret + end + + def generate_token + generation_time = Time.zone.now + payload = { + iss: ISSUER, + iat: generation_time.to_i, + exp: (generation_time + 1.minute).to_i, + } + + JWT.encode(payload, @secret, ALGORITHM) + end + end +end diff --git a/app/services/vine/voucher_redeemer_service.rb b/app/services/vine/voucher_redeemer_service.rb new file mode 100644 index 0000000000..6e03e0d2b8 --- /dev/null +++ b/app/services/vine/voucher_redeemer_service.rb @@ -0,0 +1,66 @@ +# frozen_string_literal: true + +module Vine + class VoucherRedeemerService + attr_reader :order, :errors + + def initialize(order: ) + @order = order + @errors = {} + end + + def redeem + # Do nothing if we don't have a vine voucher added to the order + voucher_adjustment = order.voucher_adjustments.first + @voucher = voucher_adjustment&.originator + + return true if voucher_adjustment.nil? || !@voucher.vine? + + if vine_settings.nil? + errors[:vine_settings] = I18n.t("vine_voucher_redeemer_service.errors.vine_settings") + return false + end + + response = call_vine_api + + if !response.success? + handle_errors(response) + return false + end + + voucher_adjustment.close + + true + rescue Faraday::Error => e + Rails.logger.error e.inspect + Bugsnag.notify(e) + + errors[:vine_api] = I18n.t("vine_voucher_validator_service.errors.vine_api") + false + end + + private + + def vine_settings + ConnectedApps::Vine.find_by(enterprise: order.distributor)&.data + end + + def call_vine_api + jwt_service = Vine::JwtService.new(secret: vine_settings["secret"]) + vine_api = Vine::ApiService.new(api_key: vine_settings["api_key"], jwt_generator: jwt_service) + + # Voucher amount is stored in dollars, VINE expect cents + vine_api.voucher_redemptions( + @voucher.external_voucher_id, @voucher.external_voucher_set_id, (@voucher.amount * 100) + ) + end + + def handle_errors(response) + if response.status == 400 + errors[:redeeming_failed] = I18n.t("vine_voucher_redeemer_service.errors.redeeming_failed") + else + errors[:vine_api] = I18n.t("vine_voucher_redeemer_service.errors.vine_api") + end + end + end +end diff --git a/app/services/vine/voucher_validator_service.rb b/app/services/vine/voucher_validator_service.rb new file mode 100644 index 0000000000..a2d085105a --- /dev/null +++ b/app/services/vine/voucher_validator_service.rb @@ -0,0 +1,84 @@ +# frozen_string_literal: true + +module Vine + class VoucherValidatorService + attr_reader :voucher_code, :errors + + def initialize(voucher_code:, enterprise:) + @voucher_code = voucher_code + @enterprise = enterprise + @errors = {} + end + + def validate + if vine_settings.nil? + errors[:vine_settings] = I18n.t("vine_voucher_validator_service.errors.vine_settings") + return nil + end + + response = call_vine_api + + if !response.success? + handle_errors(response) + return nil + end + + save_voucher(response) + rescue Faraday::Error => e + Rails.logger.error e.inspect + Bugsnag.notify(e) + + # TODO do we need a more specific error ? + errors[:vine_api] = I18n.t("vine_voucher_validator_service.errors.vine_api") + nil + end + + private + + def vine_settings + ConnectedApps::Vine.find_by(enterprise: @enterprise)&.data + end + + def call_vine_api + # Check voucher is valid + jwt_service = Vine::JwtService.new(secret: vine_settings["secret"]) + vine_api = Vine::ApiService.new(api_key: vine_settings["api_key"], jwt_generator: jwt_service) + + vine_api.voucher_validation(voucher_code) + end + + def handle_errors(response) + if response.status == 400 + errors[:invalid_voucher] = I18n.t("vine_voucher_validator_service.errors.invalid_voucher") + elsif response.status == 404 + errors[:not_found_voucher] = + I18n.t("vine_voucher_validator_service.errors.not_found_voucher") + else + errors[:vine_api] = I18n.t("vine_voucher_validator_service.errors.vine_api") + end + end + + def save_voucher(response) + voucher_data = response.body["data"] + + # Check if voucher already exist + voucher = Voucher.vine.find_by(code: voucher_code, enterprise: @enterprise) + + amount = voucher_data["voucher_value_remaining"].to_f / 100 + if voucher.present? + voucher.update(amount: ) + else + voucher = Vouchers::FlatRate.create( + enterprise: @enterprise, + code: voucher_data["voucher_short_code"], + amount:, + external_voucher_id: voucher_data["id"], + external_voucher_set_id: voucher_data["voucher_set_id"], + voucher_type: "VINE" + ) + end + + voucher + end + end +end diff --git a/app/services/vine_api_service.rb b/app/services/vine_api_service.rb deleted file mode 100644 index 89b7b1a348..0000000000 --- a/app/services/vine_api_service.rb +++ /dev/null @@ -1,75 +0,0 @@ -# frozen_string_literal: true - -require "faraday" - -class VineApiService - attr_reader :api_key, :jwt_generator - - def initialize(api_key:, jwt_generator:) - @vine_api_url = ENV.fetch("VINE_API_URL") - @api_key = api_key - @jwt_generator = jwt_generator - end - - def my_team - my_team_url = "#{@vine_api_url}/my-team" - - response = connection.get(my_team_url) - - log_error("VineApiService#my_team", response) - - response - end - - def voucher_validation(voucher_short_code) - voucher_validation_url = "#{@vine_api_url}/voucher-validation" - - response = connection.post( - voucher_validation_url, - { type: "voucher_code", value: voucher_short_code }, - 'Content-Type': "application/json" - ) - - log_error("VineApiService#voucher_validation", response) - - response - end - - def voucher_redemptions(voucher_id, voucher_set_id, amount) - voucher_redemptions_url = "#{@vine_api_url}/voucher-redemptions" - - response = connection.post( - voucher_redemptions_url, - { voucher_id:, voucher_set_id:, amount: amount.to_i }, - 'Content-Type': "application/json" - ) - - log_error("VineApiService#voucher_redemptions", response) - - response - end - - private - - def connection - jwt = jwt_generator.generate_token - Faraday.new( - request: { timeout: 30 }, - headers: { - 'X-Authorization': "JWT #{jwt}", - Accept: "application/json" - } - ) do |f| - f.request :json - f.response :json - f.request :authorization, 'Bearer', api_key - end - end - - def log_error(prefix, response) - return if response.success? - - Rails.logger.error "#{prefix} -- response_status: #{response.status}" - Rails.logger.error "#{prefix} -- response: #{response.body}" - end -end diff --git a/app/services/vine_jwt_service.rb b/app/services/vine_jwt_service.rb deleted file mode 100644 index f65f04a7f6..0000000000 --- a/app/services/vine_jwt_service.rb +++ /dev/null @@ -1,21 +0,0 @@ -# frozen_string_literal: true - -class VineJwtService - ALGORITHM = "HS256" - ISSUER = "openfoodnetwork" - - def initialize(secret: ) - @secret = secret - end - - def generate_token - generation_time = Time.zone.now - payload = { - iss: ISSUER, - iat: generation_time.to_i, - exp: (generation_time + 1.minute).to_i, - } - - JWT.encode(payload, @secret, ALGORITHM) - end -end diff --git a/app/services/vine_voucher_redeemer_service.rb b/app/services/vine_voucher_redeemer_service.rb deleted file mode 100644 index b616d8a798..0000000000 --- a/app/services/vine_voucher_redeemer_service.rb +++ /dev/null @@ -1,64 +0,0 @@ -# frozen_string_literal: true - -class VineVoucherRedeemerService - attr_reader :order, :errors - - def initialize(order: ) - @order = order - @errors = {} - end - - def call - # Do nothing if we don't have a vine voucher added to the order - voucher_adjustment = order.voucher_adjustments.first - @voucher = voucher_adjustment&.originator - - return true if voucher_adjustment.nil? || !@voucher.vine? - - if vine_settings.nil? - errors[:vine_settings] = I18n.t("vine_voucher_redeemer_service.errors.vine_settings") - return false - end - - response = call_vine_api - - if !response.success? - handle_errors(response) - return false - end - - voucher_adjustment.close - - true - rescue Faraday::Error => e - Rails.logger.error e.inspect - Bugsnag.notify(e) - - errors[:vine_api] = I18n.t("vine_voucher_validator_service.errors.vine_api") - false - end - - private - - def vine_settings - ConnectedApps::Vine.find_by(enterprise: order.distributor)&.data - end - - def call_vine_api - jwt_service = VineJwtService.new(secret: vine_settings["secret"]) - vine_api = VineApiService.new(api_key: vine_settings["api_key"], jwt_generator: jwt_service) - - # Voucher amount is stored in dollars, VINE expect cents - vine_api.voucher_redemptions( - @voucher.external_voucher_id, @voucher.external_voucher_set_id, (@voucher.amount * 100) - ) - end - - def handle_errors(response) - if response.status == 400 - errors[:redeeming_failed] = I18n.t("vine_voucher_redeemer_service.errors.redeeming_failed") - else - errors[:vine_api] = I18n.t("vine_voucher_redeemer_service.errors.vine_api") - end - end -end diff --git a/app/services/vine_voucher_validator_service.rb b/app/services/vine_voucher_validator_service.rb deleted file mode 100644 index 038ecf8fbc..0000000000 --- a/app/services/vine_voucher_validator_service.rb +++ /dev/null @@ -1,81 +0,0 @@ -# frozen_string_literal: true - -class VineVoucherValidatorService - attr_reader :voucher_code, :errors - - def initialize(voucher_code:, enterprise:) - @voucher_code = voucher_code - @enterprise = enterprise - @errors = {} - end - - def validate - if vine_settings.nil? - errors[:vine_settings] = I18n.t("vine_voucher_validator_service.errors.vine_settings") - return nil - end - - response = call_vine_api - - if !response.success? - handle_errors(response) - return nil - end - - save_voucher(response) - rescue Faraday::Error => e - Rails.logger.error e.inspect - Bugsnag.notify(e) - - # TODO do we need a more specific error ? - errors[:vine_api] = I18n.t("vine_voucher_validator_service.errors.vine_api") - nil - end - - private - - def vine_settings - ConnectedApps::Vine.find_by(enterprise: @enterprise)&.data - end - - def call_vine_api - # Check voucher is valid - jwt_service = VineJwtService.new(secret: vine_settings["secret"]) - vine_api = VineApiService.new(api_key: vine_settings["api_key"], jwt_generator: jwt_service) - - vine_api.voucher_validation(voucher_code) - end - - def handle_errors(response) - if response.status == 400 - errors[:invalid_voucher] = I18n.t("vine_voucher_validator_service.errors.invalid_voucher") - elsif response.status == 404 - errors[:not_found_voucher] = I18n.t("vine_voucher_validator_service.errors.not_found_voucher") - else - errors[:vine_api] = I18n.t("vine_voucher_validator_service.errors.vine_api") - end - end - - def save_voucher(response) - voucher_data = response.body["data"] - - # Check if voucher already exist - voucher = Voucher.vine.find_by(code: voucher_code, enterprise: @enterprise) - - amount = voucher_data["voucher_value_remaining"].to_f / 100 - if voucher.present? - voucher.update(amount: ) - else - voucher = Vouchers::FlatRate.create( - enterprise: @enterprise, - code: voucher_data["voucher_short_code"], - amount:, - external_voucher_id: voucher_data["id"], - external_voucher_set_id: voucher_data["voucher_set_id"], - voucher_type: "VINE" - ) - end - - voucher - end -end diff --git a/spec/controllers/checkout_controller_spec.rb b/spec/controllers/checkout_controller_spec.rb index 37957c2ff9..9ae4a16b43 100644 --- a/spec/controllers/checkout_controller_spec.rb +++ b/spec/controllers/checkout_controller_spec.rb @@ -502,7 +502,7 @@ RSpec.describe CheckoutController, type: :controller do create(:voucher_flat_rate, voucher_type: "VINE", code: 'some_code', enterprise: distributor, amount: 6) } - let(:vine_voucher_redeemer) { instance_double(VineVoucherRedeemerService) } + let(:vine_voucher_redeemer) { instance_double(Vine::VoucherRedeemerService) } before do # Adding voucher to the order @@ -510,11 +510,11 @@ RSpec.describe CheckoutController, type: :controller do VoucherAdjustmentsService.new(order).update order.update_totals_and_states - allow(VineVoucherRedeemerService).to receive(:new).and_return(vine_voucher_redeemer) + allow(Vine::VoucherRedeemerService).to receive(:new).and_return(vine_voucher_redeemer) end it "completes the order and redirects to order confirmation" do - expect(vine_voucher_redeemer).to receive(:call).and_return(true) + expect(vine_voucher_redeemer).to receive(:redeem).and_return(true) put(:update, params:) @@ -524,7 +524,7 @@ RSpec.describe CheckoutController, type: :controller do context "when redeeming the voucher fails" do it "returns 422 and some error" do - allow(vine_voucher_redeemer).to receive(:call).and_return(false) + allow(vine_voucher_redeemer).to receive(:redeem).and_return(false) allow(vine_voucher_redeemer).to receive(:errors).and_return( { redeeming_failed: "Redeeming the voucher failed" } ) @@ -538,7 +538,7 @@ RSpec.describe CheckoutController, type: :controller do context "when an other error happens" do it "returns 422 and some error" do - allow(vine_voucher_redeemer).to receive(:call).and_return(false) + allow(vine_voucher_redeemer).to receive(:redeem).and_return(false) allow(vine_voucher_redeemer).to receive(:errors).and_return( { vine_api: "There was an error communicating with the API" } ) diff --git a/spec/fixtures/vcr_cassettes/VineApiService/_my_team/when_a_request_succeed/returns_the_response.yml b/spec/fixtures/vcr_cassettes/Vine_ApiService/_my_team/when_a_request_succeed/returns_the_response.yml similarity index 100% rename from spec/fixtures/vcr_cassettes/VineApiService/_my_team/when_a_request_succeed/returns_the_response.yml rename to spec/fixtures/vcr_cassettes/Vine_ApiService/_my_team/when_a_request_succeed/returns_the_response.yml diff --git a/spec/fixtures/vcr_cassettes/VineApiService/_voucher_redemptions/when_a_request_succeed/returns_the_response.yml b/spec/fixtures/vcr_cassettes/Vine_ApiService/_voucher_redemptions/when_a_request_succeed/returns_the_response.yml similarity index 100% rename from spec/fixtures/vcr_cassettes/VineApiService/_voucher_redemptions/when_a_request_succeed/returns_the_response.yml rename to spec/fixtures/vcr_cassettes/Vine_ApiService/_voucher_redemptions/when_a_request_succeed/returns_the_response.yml diff --git a/spec/fixtures/vcr_cassettes/VineApiService/_voucher_validation/when_a_request_succeed/returns_the_response.yml b/spec/fixtures/vcr_cassettes/Vine_ApiService/_voucher_validation/when_a_request_succeed/returns_the_response.yml similarity index 100% rename from spec/fixtures/vcr_cassettes/VineApiService/_voucher_validation/when_a_request_succeed/returns_the_response.yml rename to spec/fixtures/vcr_cassettes/Vine_ApiService/_voucher_validation/when_a_request_succeed/returns_the_response.yml diff --git a/spec/models/connected_apps/vine_spec.rb b/spec/models/connected_apps/vine_spec.rb index 8b37afb0f5..c3a2e8cf44 100644 --- a/spec/models/connected_apps/vine_spec.rb +++ b/spec/models/connected_apps/vine_spec.rb @@ -7,7 +7,7 @@ RSpec.describe ConnectedApps::Vine do let(:vine_api_key) { "12345" } let(:secret) { "my_secret" } - let(:vine_api) { instance_double(VineApiService) } + let(:vine_api) { instance_double(Vine::ApiService) } describe "#connect" do it "send a request to VINE api" do diff --git a/spec/requests/admin/connected_apps_controller_spec.rb b/spec/requests/admin/connected_apps_controller_spec.rb index 05b7eefa0c..a39eaa52af 100644 --- a/spec/requests/admin/connected_apps_controller_spec.rb +++ b/spec/requests/admin/connected_apps_controller_spec.rb @@ -13,11 +13,11 @@ RSpec.describe "Admin ConnectedApp" do describe "POST /admin/enterprises/:enterprise_id/connected_apps" do context "with type ConnectedApps::Vine" do - let(:vine_api) { instance_double(VineApiService) } + let(:vine_api) { instance_double(Vine::ApiService) } before do - allow(VineJwtService).to receive(:new).and_return(instance_double(VineJwtService)) - allow(VineApiService).to receive(:new).and_return(vine_api) + allow(Vine::JwtService).to receive(:new).and_return(instance_double(Vine::JwtService)) + allow(Vine::ApiService).to receive(:new).and_return(vine_api) end it "creates a new connected app" do @@ -115,7 +115,7 @@ RSpec.describe "Admin ConnectedApp" do before do allow(ENV).to receive(:fetch).and_call_original allow(ENV).to receive(:fetch).with("VINE_API_URL").and_raise(KeyError) - allow(VineApiService).to receive(:new).and_call_original + allow(Vine::ApiService).to receive(:new).and_call_original end it "redirects to enterprise edit page, with an error" do diff --git a/spec/requests/spree/admin/payments_spec.rb b/spec/requests/spree/admin/payments_spec.rb index aeeef365c2..6fb898f520 100644 --- a/spec/requests/spree/admin/payments_spec.rb +++ b/spec/requests/spree/admin/payments_spec.rb @@ -76,16 +76,16 @@ RSpec.describe Spree::Admin::PaymentsController, type: :request do create(:voucher_flat_rate, voucher_type: "VINE", code: 'some_code', enterprise: order.distributor, amount: 6) } - let(:vine_voucher_redeemer) { instance_double(VineVoucherRedeemerService) } + let(:vine_voucher_redeemer) { instance_double(Vine::VoucherRedeemerService) } before do add_voucher_to_order(vine_voucher, order) - allow(VineVoucherRedeemerService).to receive(:new).and_return(vine_voucher_redeemer) + allow(Vine::VoucherRedeemerService).to receive(:new).and_return(vine_voucher_redeemer) end it "completes the order and redirects to payment page" do - expect(vine_voucher_redeemer).to receive(:call).and_return(true) + expect(vine_voucher_redeemer).to receive(:redeem).and_return(true) post("/admin/orders/#{order.number}/payments.json", params:) @@ -97,7 +97,7 @@ RSpec.describe Spree::Admin::PaymentsController, type: :request do context "when redeeming the voucher fails" do it "redirect to payments page" do - allow(vine_voucher_redeemer).to receive(:call).and_return(false) + allow(vine_voucher_redeemer).to receive(:redeem).and_return(false) allow(vine_voucher_redeemer).to receive(:errors).and_return( { redeeming_failed: "Redeeming the voucher failed" } ) @@ -111,7 +111,7 @@ RSpec.describe Spree::Admin::PaymentsController, type: :request do context "when an other error happens" do it "redirect to payments page" do - allow(vine_voucher_redeemer).to receive(:call).and_return(false) + allow(vine_voucher_redeemer).to receive(:redeem).and_return(false) allow(vine_voucher_redeemer).to receive(:errors).and_return( { vine_api: "There was an error communicating with the API" } ) @@ -267,16 +267,16 @@ RSpec.describe Spree::Admin::PaymentsController, type: :request do create(:voucher_flat_rate, voucher_type: "VINE", code: 'some_code', enterprise: order.distributor, amount: 6) } - let(:vine_voucher_redeemer) { instance_double(VineVoucherRedeemerService) } + let(:vine_voucher_redeemer) { instance_double(Vine::VoucherRedeemerService) } before do add_voucher_to_order(vine_voucher, order) - allow(VineVoucherRedeemerService).to receive(:new).and_return(vine_voucher_redeemer) + allow(Vine::VoucherRedeemerService).to receive(:new).and_return(vine_voucher_redeemer) end it "completes the order and redirects to payment page" do - expect(vine_voucher_redeemer).to receive(:call).and_return(true) + expect(vine_voucher_redeemer).to receive(:redeem).and_return(true) put( "/admin/orders/#{order.number}/payments/#{order.payments.first.id}/" \ @@ -293,7 +293,7 @@ RSpec.describe Spree::Admin::PaymentsController, type: :request do context "when redeeming the voucher fails" do it "redirect to payments page" do - allow(vine_voucher_redeemer).to receive(:call).and_return(false) + allow(vine_voucher_redeemer).to receive(:redeem).and_return(false) allow(vine_voucher_redeemer).to receive(:errors).and_return( { redeeming_failed: "Redeeming the voucher failed" } ) @@ -312,7 +312,7 @@ RSpec.describe Spree::Admin::PaymentsController, type: :request do context "when an other error happens" do it "redirect to payments page" do - allow(vine_voucher_redeemer).to receive(:call).and_return(false) + allow(vine_voucher_redeemer).to receive(:redeem).and_return(false) allow(vine_voucher_redeemer).to receive(:errors).and_return( { vine_api: "There was an error communicating with the API" } ) diff --git a/spec/requests/voucher_adjustments_spec.rb b/spec/requests/voucher_adjustments_spec.rb index 158911dd68..ae8dc8e4bf 100644 --- a/spec/requests/voucher_adjustments_spec.rb +++ b/spec/requests/voucher_adjustments_spec.rb @@ -87,10 +87,10 @@ RSpec.describe VoucherAdjustmentsController, type: :request do end context "with a VINE voucher", feature: :connected_apps do - let(:vine_voucher_validator) { instance_double(VineVoucherValidatorService) } + let(:vine_voucher_validator) { instance_double(Vine::VoucherValidatorService) } before do - allow(VineVoucherValidatorService).to receive(:new).and_return(vine_voucher_validator) + allow(Vine::VoucherValidatorService).to receive(:new).and_return(vine_voucher_validator) end context "with a new voucher" do diff --git a/spec/services/vine_api_service_spec.rb b/spec/services/vine/api_service_spec.rb similarity index 96% rename from spec/services/vine_api_service_spec.rb rename to spec/services/vine/api_service_spec.rb index 1a9f9977d4..33292ade65 100644 --- a/spec/services/vine_api_service_spec.rb +++ b/spec/services/vine/api_service_spec.rb @@ -2,12 +2,12 @@ require "spec_helper" -RSpec.describe VineApiService do +RSpec.describe Vine::ApiService do subject(:vine_api) { described_class.new(api_key: vine_api_key, jwt_generator: jwt_service) } let(:vine_api_url) { "https://vine-staging.openfoodnetwork.org.au/api/v1" } let(:vine_api_key) { "12345" } - let(:jwt_service) { VineJwtService.new(secret:) } + let(:jwt_service) { Vine::JwtService.new(secret:) } let(:secret) { "my_secret" } let(:token) { "some.jwt.token" } @@ -59,7 +59,7 @@ RSpec.describe VineApiService do it "logs the error" do stub_request(:get, my_team_url).to_return(body: "error", status: 401) - expect(Rails.logger).to receive(:error).with(match("VineApiService#my_team")).twice + expect(Rails.logger).to receive(:error).with(match("Vine::ApiService#my_team")).twice response = vine_api.my_team @@ -124,7 +124,7 @@ RSpec.describe VineApiService do stub_request(:post, voucher_validation_url).to_return(body: "error", status: 401) expect(Rails.logger).to receive(:error).with( - match("VineApiService#voucher_validation") + match("Vine::ApiService#voucher_validation") ).twice response = vine_api.voucher_validation(voucher_short_code) @@ -192,7 +192,7 @@ RSpec.describe VineApiService do stub_request(:post, voucher_redemptions_url).to_return(body: "error", status: 401) expect(Rails.logger).to receive(:error).with( - match("VineApiService#voucher_redemptions") + match("Vine::ApiService#voucher_redemptions") ).twice response = vine_api.voucher_redemptions(voucher_id, voucher_set_id, amount) diff --git a/spec/services/vine_jwt_service_spec.rb b/spec/services/vine/jwt_service_spec.rb similarity index 97% rename from spec/services/vine_jwt_service_spec.rb rename to spec/services/vine/jwt_service_spec.rb index 204dede96c..1a964b3666 100644 --- a/spec/services/vine_jwt_service_spec.rb +++ b/spec/services/vine/jwt_service_spec.rb @@ -2,7 +2,7 @@ require "spec_helper" -RSpec.describe VineJwtService do +RSpec.describe Vine::JwtService do describe "#generate_token" do subject { described_class.new(secret: vine_secret) } let(:vine_secret) { "some_secret" } diff --git a/spec/services/vine_voucher_redeemer_service_spec.rb b/spec/services/vine/voucher_redeemer_service_spec.rb similarity index 84% rename from spec/services/vine_voucher_redeemer_service_spec.rb rename to spec/services/vine/voucher_redeemer_service_spec.rb index 10d04d7f03..5dd83da12b 100644 --- a/spec/services/vine_voucher_redeemer_service_spec.rb +++ b/spec/services/vine/voucher_redeemer_service_spec.rb @@ -2,7 +2,7 @@ require "spec_helper" -RSpec.describe VineVoucherRedeemerService, feature: :connected_apps do +RSpec.describe Vine::VoucherRedeemerService, feature: :connected_apps do subject(:voucher_redeemer_service) { described_class.new(order: ) } let(:user) { order.user } @@ -17,13 +17,13 @@ RSpec.describe VineVoucherRedeemerService, feature: :connected_apps do } let(:voucher_id) { "9d316d27-0dad-411a-8953-316a1aaf7742" } let(:voucher_set_id) { "9d314daa-0878-4b73-922d-698047640cf4" } - let(:vine_api_service) { instance_double(VineApiService) } + let(:vine_api_service) { instance_double(Vine::ApiService) } before do - allow(VineApiService).to receive(:new).and_return(vine_api_service) + allow(Vine::ApiService).to receive(:new).and_return(vine_api_service) end - describe "#call" do + describe "#redeem" do context "with a valid voucher" do let!(:vine_connected_app) { ConnectedApps::Vine.create( @@ -60,7 +60,7 @@ RSpec.describe VineVoucherRedeemerService, feature: :connected_apps do .with(voucher_id, voucher_set_id, 600) .and_return(mock_api_response(success: true, data:)) - voucher_redeemer_service.call + voucher_redeemer_service.redeem end it "closes the linked assement" do @@ -68,7 +68,7 @@ RSpec.describe VineVoucherRedeemerService, feature: :connected_apps do .and_return(mock_api_response(success: true, data:)) expect { - voucher_redeemer_service.call + voucher_redeemer_service.redeem }.to change { order.voucher_adjustments.first.state }.to("closed") end @@ -76,7 +76,7 @@ RSpec.describe VineVoucherRedeemerService, feature: :connected_apps do allow(vine_api_service).to receive(:voucher_redemptions) .and_return(mock_api_response(success: true, data:)) - expect(voucher_redeemer_service.call).to be(true) + expect(voucher_redeemer_service.redeem).to be(true) end context "when redeeming fails" do @@ -93,16 +93,16 @@ RSpec.describe VineVoucherRedeemerService, feature: :connected_apps do it "doesn't close the linked assement" do expect { - voucher_redeemer_service.call + voucher_redeemer_service.redeem }.not_to change { order.voucher_adjustments.first.state } end it "returns false" do - expect(voucher_redeemer_service.call).to be(false) + expect(voucher_redeemer_service.redeem).to be(false) end it "adds an error message" do - voucher_redeemer_service.call + voucher_redeemer_service.redeem expect(voucher_redeemer_service.errors).to include( { redeeming_failed: "Redeeming the voucher failed" } @@ -115,17 +115,17 @@ RSpec.describe VineVoucherRedeemerService, feature: :connected_apps do before { add_voucher(vine_voucher) } it "returns false" do - expect(voucher_redeemer_service.call).to be(false) + expect(voucher_redeemer_service.redeem).to be(false) end - it "doesn't call the VINE API" do + it "doesn't redeem the VINE API" do expect(vine_api_service).not_to receive(:voucher_redemptions) - voucher_redeemer_service.call + voucher_redeemer_service.redeem end it "adds an error message" do - voucher_redeemer_service.call + voucher_redeemer_service.redeem expect(voucher_redeemer_service.errors).to include( { vine_settings: "No Vine api settings for the given enterprise" } @@ -134,7 +134,7 @@ RSpec.describe VineVoucherRedeemerService, feature: :connected_apps do it "doesn't close the linked assement" do expect { - voucher_redeemer_service.call + voucher_redeemer_service.redeem }.not_to change { order.voucher_adjustments.first.state } end end @@ -148,13 +148,13 @@ RSpec.describe VineVoucherRedeemerService, feature: :connected_apps do } it "returns true" do - expect(voucher_redeemer_service.call).to be(true) + expect(voucher_redeemer_service.redeem).to be(true) end - it "doesn't call the VINE API" do + it "doesn't redeem the VINE API" do expect(vine_api_service).not_to receive(:voucher_redemptions) - voucher_redeemer_service.call + voucher_redeemer_service.redeem end end @@ -169,13 +169,13 @@ RSpec.describe VineVoucherRedeemerService, feature: :connected_apps do before { add_voucher(voucher) } it "returns true" do - expect(voucher_redeemer_service.call).to be(true) + expect(voucher_redeemer_service.redeem).to be(true) end - it "doesn't call the VINE API" do + it "doesn't redeem the VINE API" do expect(vine_api_service).not_to receive(:voucher_redemptions) - voucher_redeemer_service.call + voucher_redeemer_service.redeem end end @@ -192,11 +192,11 @@ RSpec.describe VineVoucherRedeemerService, feature: :connected_apps do end it "returns false" do - expect(voucher_redeemer_service.call).to be(false) + expect(voucher_redeemer_service.redeem).to be(false) end it "adds an error message" do - voucher_redeemer_service.call + voucher_redeemer_service.redeem expect(voucher_redeemer_service.errors).to include( { vine_api: "There was an error communicating with the API" } @@ -205,7 +205,7 @@ RSpec.describe VineVoucherRedeemerService, feature: :connected_apps do it "doesn't close the linked assement" do expect { - voucher_redeemer_service.call + voucher_redeemer_service.redeem }.not_to change { order.voucher_adjustments.first.state } end @@ -213,7 +213,7 @@ RSpec.describe VineVoucherRedeemerService, feature: :connected_apps do expect(Rails.logger).to receive(:error) expect(Bugsnag).to receive(:notify) - voucher_redeemer_service.call + voucher_redeemer_service.redeem end end @@ -240,11 +240,11 @@ RSpec.describe VineVoucherRedeemerService, feature: :connected_apps do end it "returns false" do - expect(voucher_redeemer_service.call).to be(false) + expect(voucher_redeemer_service.redeem).to be(false) end it "adds an error message" do - voucher_redeemer_service.call + voucher_redeemer_service.redeem expect(voucher_redeemer_service.errors).to include( { vine_api: "There was an error communicating with the API" } @@ -253,7 +253,7 @@ RSpec.describe VineVoucherRedeemerService, feature: :connected_apps do it "doesn't close the linked assement" do expect { - voucher_redeemer_service.call + voucher_redeemer_service.redeem }.not_to change { order.voucher_adjustments.first.state } end end diff --git a/spec/services/vine_voucher_validator_service_spec.rb b/spec/services/vine/voucher_validator_service_spec.rb similarity index 98% rename from spec/services/vine_voucher_validator_service_spec.rb rename to spec/services/vine/voucher_validator_service_spec.rb index 2576713b37..a3175e24e9 100644 --- a/spec/services/vine_voucher_validator_service_spec.rb +++ b/spec/services/vine/voucher_validator_service_spec.rb @@ -2,15 +2,15 @@ require "spec_helper" -RSpec.describe VineVoucherValidatorService, feature: :connected_apps do +RSpec.describe Vine::VoucherValidatorService, feature: :connected_apps do subject(:validate_voucher_service) { described_class.new(voucher_code:, enterprise: distributor) } let(:voucher_code) { "good_code" } let(:distributor) { create(:distributor_enterprise) } - let(:vine_api_service) { instance_double(VineApiService) } + let(:vine_api_service) { instance_double(Vine::ApiService) } before do - allow(VineApiService).to receive(:new).and_return(vine_api_service) + allow(Vine::ApiService).to receive(:new).and_return(vine_api_service) end describe "#validate" do