<commit_before># frozen_string_literal: true

require 'spec_helper'

describe Spree::OrdersController, type: :controller do
  include OpenFoodNetwork::EmailHelper
  include CheckoutHelper

  let(:distributor) { double(:distributor) }
  let(:order) { create(:order) }
  let(:order_cycle) { create(:simple_order_cycle) }

  describe "viewing an order" do
    let(:customer) { create(:customer) }
    let(:order) { create(:order_with_credit_payment, customer: customer, distributor: customer.enterprise) }

    before do
      allow(controller).to receive(:spree_current_user) { current_user }
    end

    context "after checking out as an anonymous guest" do
      let(:customer) { create(:customer, user: nil) }
      let(:current_user) { nil }

      it "loads page" do
        get :show, params: { id: order.number, token: order.token }
        expect(response).to be_success
      end

      it "stores order token in session as 'access_token'" do
        get :show, params: { id: order.number, token: order.token }
        expect(session[:access_token]).to eq(order.token)
      end
    end

    context "when returning to order page after checking out as an anonymous guest" do
      let(:customer) { create(:customer, user: nil) }
      let(:current_user) { nil }

      before do
        session[:access_token] = order.token
      end

      it "loads page" do
        get :show, params: { id: order.number }
        expect(response).to be_success
      end
    end

    context "when logged in as the customer" do
      let(:current_user) { order.user }

      it "loads page" do
        get :show, params: { id: order.number }
        expect(response).to be_success
      end
    end

    context "when logged in as another customer" do
      let(:current_user) { create(:user) }

      it "redirects to unauthorized" do
        get :show, params: { id: order.number }
        expect(response).to redirect_to unauthorized_path
      end
    end

    context "when neither checked out as an anonymous guest nor logged in" do
      let(:current_user) { nil }

      before do
        request.env["PATH_INFO"] = order_path(order)
      end

      it "redirects to unauthorized" do
        get :show, params: { id: order.number }
        expect(response).to redirect_to(root_path(anchor: "login?after_login=#{order_path(order)}"))
        expect(flash[:error]).to eq("Please log in to view your order.")
      end
    end
  end

  describe "confirming a payment intent" do
    let(:customer) { create(:customer) }
    let(:order) { create(:order, customer: customer, distributor: customer.enterprise) }
    let(:payment_method) { create(:stripe_sca_payment_method) }
    let!(:payment) { create(
      :payment,
      payment_method: payment_method,
      cvv_response_message: "https://stripe.com/redirect",
      response_code: "pi_123",
      order: order,
      state: "pending")
    }

    before do
      allow(controller).to receive(:spree_current_user) { current_user }
    end

    context "after returning from Stripe to authorize a payment" do
      let(:current_user) { order.user }

      context "with a valid payment intent" do
        let(:payment_intent) { "pi_123" }

        before do
          allow_any_instance_of(Stripe::PaymentIntentValidator)
            .to receive(:call)
            .with(payment_intent, anything)
            .and_return(payment_intent)
        end

        it "completes the payment" do
          get :show, params: { id: order.number, payment_intent: payment_intent }

          expect(response).to be_success
          payment.reload
          expect(payment.cvv_response_message).to be nil
          expect(payment.state).to eq("completed")
        end
      end

      context "with an invalid payment intent" do
        let(:payment_intent) { "invalid" }
        let(:result) { instance_double(ProcessPaymentIntent::Result) }

        before do
          allow_any_instance_of(Stripe::PaymentIntentValidator)
            .to receive(:call)
            .with(payment_intent, anything)
            .and_return(result)
        end

        it "does not complete the payment" do
          get :show, params: { id: order.number, payment_intent: payment_intent }

          expect(response).to be_success
          payment.reload
          expect(payment.cvv_response_message).to eq("https://stripe.com/redirect")
          expect(payment.state).to eq("pending")
        end
      end

      context "with an invalid last payment" do
        let(:payment_intent) { "valid" }
        let(:finder) { instance_double(OrderPaymentFinder, last_payment: payment) }

        before do
          allow(payment).to receive(:response_code).and_return("invalid")
          allow(OrderPaymentFinder).to receive(:new).with(order).and_return(finder)
        end

        it "does not complete the payment" do
          get :show, params: { id: order.number, payment_intent: payment_intent }

          expect(response).to be_success
          payment.reload
          expect(payment.cvv_response_message).to eq("https://stripe.com/redirect")
          expect(payment.state).to eq("pending")
        end
      end
    end
  end

  describe "viewing cart" do
    it "redirects home when no distributor is selected" do
      get :edit
      expect(response).to redirect_to root_path
    end

    it "redirects to shop when order is empty" do
      allow(controller).to receive(:current_distributor).and_return(distributor)
      allow(controller).to receive(:current_order_cycle).and_return(order_cycle)
      allow(controller).to receive(:current_order).and_return order
      allow(order).to receive_message_chain(:line_items, :empty?).and_return true
      allow(order).to receive(:insufficient_stock_lines).and_return []
      allow(order).to receive(:line_item_variants).and_return []
      allow(order_cycle).to receive(:variants_distributed_by).and_return []

      session[:access_token] = order.token
      get :edit<commit_msg>Properly mock validator and extend tests<commit_after># frozen_string_literal: true

require 'spec_helper'

describe Spree::OrdersController, type: :controller do
  include OpenFoodNetwork::EmailHelper
  include CheckoutHelper

  let(:distributor) { double(:distributor) }
  let(:order) { create(:order) }
  let(:order_cycle) { create(:simple_order_cycle) }

  describe "viewing an order" do
    let(:customer) { create(:customer) }
    let(:order) { create(:order_with_credit_payment, customer: customer, distributor: customer.enterprise) }

    before do
      allow(controller).to receive(:spree_current_user) { current_user }
    end

    context "after checking out as an anonymous guest" do
      let(:customer) { create(:customer, user: nil) }
      let(:current_user) { nil }

      it "loads page" do
        get :show, params: { id: order.number, token: order.token }
        expect(response).to be_success
      end

      it "stores order token in session as 'access_token'" do
        get :show, params: { id: order.number, token: order.token }
        expect(session[:access_token]).to eq(order.token)
      end
    end

    context "when returning to order page after checking out as an anonymous guest" do
      let(:customer) { create(:customer, user: nil) }
      let(:current_user) { nil }

      before do
        session[:access_token] = order.token
      end

      it "loads page" do
        get :show, params: { id: order.number }
        expect(response).to be_success
      end
    end

    context "when logged in as the customer" do
      let(:current_user) { order.user }

      it "loads page" do
        get :show, params: { id: order.number }
        expect(response).to be_success
      end
    end

    context "when logged in as another customer" do
      let(:current_user) { create(:user) }

      it "redirects to unauthorized" do
        get :show, params: { id: order.number }
        expect(response).to redirect_to unauthorized_path
      end
    end

    context "when neither checked out as an anonymous guest nor logged in" do
      let(:current_user) { nil }

      before do
        request.env["PATH_INFO"] = order_path(order)
      end

      it "redirects to unauthorized" do
        get :show, params: { id: order.number }
        expect(response).to redirect_to(root_path(anchor: "login?after_login=#{order_path(order)}"))
        expect(flash[:error]).to eq("Please log in to view your order.")
      end
    end
  end

  describe "confirming a payment intent" do
    let(:customer) { create(:customer) }
    let(:order) { create(:order, customer: customer, distributor: customer.enterprise) }
    let(:payment_method) { create(:stripe_sca_payment_method) }
    let!(:payment) { create(
      :payment,
      payment_method: payment_method,
      cvv_response_message: "https://stripe.com/redirect",
      response_code: "pi_123",
      order: order,
      state: "pending")
    }

    before do
      allow(controller).to receive(:spree_current_user) { current_user }
    end

    context "after returning from Stripe to authorize a payment" do
      let(:current_user) { order.user }

      context "with a valid payment intent" do
        let(:payment_intent) { "pi_123" }

        before do
          allow_any_instance_of(Stripe::PaymentIntentValidator)
            .to receive(:call)
            .with(payment_intent, kind_of(String))
            .and_return(payment_intent)
        end

        it "completes the payment" do
          get :show, params: { id: order.number, payment_intent: payment_intent }

          expect(response).to be_success
          payment.reload
          expect(payment.cvv_response_message).to be nil
          expect(payment.state).to eq("completed")
        end
      end

      context "with an invalid payment intent" do
        let(:payment_intent) { "invalid" }

        before do
          allow_any_instance_of(Stripe::PaymentIntentValidator)
            .to receive(:call)
            .with(payment_intent, kind_of(String))
            .and_raise(Stripe::StripeError, "error message")
        end

        it "does not complete the payment" do
          get :show, params: { id: order.number, payment_intent: payment_intent }

          expect(response).to be_success
          expect(flash[:error]).to eq("#{I18n.t("payment_could_not_process")}. error message")
          payment.reload
          expect(payment.cvv_response_message).to eq("https://stripe.com/redirect")
          expect(payment.state).to eq("pending")
        end
      end

      context "with an invalid last payment" do
        let(:payment_intent) { "valid" }
        let(:finder) { instance_double(OrderPaymentFinder, last_payment: payment) }

        before do
          allow(payment).to receive(:response_code).and_return("invalid")
          allow(OrderPaymentFinder).to receive(:new).with(order).and_return(finder)

          allow_any_instance_of(Stripe::PaymentIntentValidator)
            .to receive(:call)
            .with(payment_intent, kind_of(String))
            .and_return(payment_intent)
        end

        it "does not complete the payment" do
          get :show, params: { id: order.number, payment_intent: payment_intent }

          expect(response).to be_success
          expect(flash[:error]).to eq("#{I18n.t("payment_could_not_process")}. ")
          payment.reload
          expect(payment.cvv_response_message).to eq("https://stripe.com/redirect")
          expect(payment.state).to eq("pending")
        end
      end
    end
  end

  describe "viewing cart" do
    it "redirects home when no distributor is selected" do
      get :edit
      expect(response).to redirect_to root_path
    end

    it "redirects to shop when order is empty" do
      allow(controller).to receive(:current_distributor).and_return(distributor)
      allow(controller).to receive(:current_order_cycle).and_return(order_cycle)
      allow(controller).to receive(:current_order).and_return order
      allow(order).to receive_message_chain(:line_items, :empty?).and_return true
      allow(order).to receive(:insufficient_stock_lines).and_return []
      allow(order).to receive(:line_item_variants).and_return []
      allow(order_cycle).to receive(:variants_distributed_by).and_return []

      session[:access_token] = order.token
      get :edit
{'fraction_non_alphanumeric': 0.10264120276310443, 'fraction_numerical': 0.001300284437220642, 'mean_word_length': 2.815813953488372, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 6, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4257036', 'n_tokens_mistral': 3551, 'n_tokens_neox': 3445, 'n_words': 900}