ruby-on-railsrspec

How to test redirect_back in RSpec 3.12 requests?


My application manages treatments as a list of tasks. Tasks are created and edited through a modal window invoked from the treatment Show view. When closing the task form, I redirect_back to the treatment, with root_path as the fallback location:

  def update    
    @task.updated_by = current_login    
    respond_to do |format|
      if @task.update_attributes(task_params)
        format.html { redirect_back fallback_location: root_path, notice: t('.Success') } 
        format.json { head :no_content }
      else
        format.html { redirect_back fallback_location: root_path, notice: "#{t('.Failure')}: #{@task.errors.full_messages.join(',')}" }
        format.json { render json: @task.errors, status: :unprocessable_entity }
      end
    end
  end

Testing this with Rspec always raises an error, because it redirects to root_path:

  describe "update - PATCH /tasks/:id" do
    context "with valid parameters" do
      let(:new_attributes) do 
        {
          sort_code: "RSPEC-Updated"
        }
      end
      it "updates the requested task" do
        patch task_url(task), params: { 
          task: new_attributes 
        }.merge(extra_fields)
        expect(response).to redirect_to(treatment_url(task.parent))
      end
    end

How could I configure the test in order to redirect to the expected location and make it pass?


Solution

  • redirect_back method uses request.referer to redirect to the previous location:

    def redirect_back(fallback_location,, **args)
      if referer = request.headers["Referer"]
        redirect_to referer, **args
      else
        redirect_to fallback_location, **args
      end
    end
    

    So you need to set the referer to the desired URL (like in your case it should be set to treatment_url(task.parent)).

    You can try setting the referer in Rspec either by stubbing or maybe like this mentioned here on this answer:

    request.env['HTTP_REFERER'] = treatment_url(task.parent)