2013-05-08 22 views
7

Tiếp theo Railscast on Devise and OmniAuth tôi đã thực hiện một OmniauthCallbacksController < Devise::OmniauthCallbacksController trong đó có một phương pháp duy nhất để xử lý một callback OmniAuth:RSpec: Kiểm tra chuyển hướng trong lập mưu :: OmniauthCallbacksController lớp con

def all 
    user = User.from_omniauth(request.env["omniauth.auth"]) 
    if user.persisted? 
    sign_in_and_redirect user 
    else 
    session["devise.user_attributes"] = user.attributes 
    redirect_to new_user_registration_url 
    end 
end 
alias_method :facebook, :all 

routes.rb:

devise_for :users, controllers: {omniauth_callbacks: "omniauth_callbacks", :sessions => "sessions" } 

Tôi muốn tùy chỉnh điều này, vì vậy tôi đang cố gắng kiểm tra nó bằng cách sử dụng RSpec. Câu hỏi đặt ra là làm cách nào để thử nghiệm phương pháp này và chuyển hướng?

Nếu trong spec tôi đặt user_omniauth_callback_path(:facebook) nó không phàn nàn về tuyến đường không tồn tại, nhưng dường như không thực sự gọi phương thức.

Theo this answer "kiểm tra bộ điều khiển sử dụng bốn động từ HTTP (GET, POST, PUT, DELETE), bất kể bộ điều khiển của bạn có RESTful hay không." Tôi đã thử get user_... v.v. nhưng ở đây nó phàn nàn rằng tuyến đường không tồn tại. Và thực sự nếu tôi làm rake routes nó cho thấy không có động từ HTTP cho tuyến đường này:

user_omniauth_callback [BLANK] /users/auth/:action/callback(.:format) omniauth_callbacks#(?-mix:facebook) 

Bạn có thể thấy những gì tôi đang thiếu không?

EDIT

Vì vậy, sau this question một cách gọi phương pháp này là:

controller.send(:all) 

Tuy nhiên tôi sau đó gặp phải lỗi tương tự mà người hỏi chạy vào:

ActionController::RackDelegation#content_type delegated to @_response.content_type, but @_response is nil 

Trả lời

5

Bạn sẽ cần phải làm ba việc để đạt được điều này.

  • nhập OmniAuth môi trường thử nghiệm
  • tạo ra một thử nghiệm OmniAuth giả
  • còn sơ khai ra phương pháp from_omniauth của bạn để trở người dùng

Đây là một giải pháp khả thi, nhập vào spec tự (spec /feature/login_spec.rb chẳng hạn). . .

let(:current_user) { FactoryGirl.create(:user) } 

before do 
    OmniAuth.config.test_mode = true 
    OmniAuth.config.mock_auth[:facebook] = OmniAuth::AuthHash.new({ 
    provider: :facebook, 
    uid:'12345', 
    info: { 
     name: "Joe" 
    } 
    }) 
    User.stub(:from_omniauth).and_return(current_user) 
end 

Tôi đã điều chỉnh điều này từ xác thực của google, vì vậy, facebook có thể yêu cầu nhiều trường hơn, nhưng đó là những trường duy nhất required by omniauth docs. Bạn sẽ có thể tìm thấy các trường chính xác bằng cách xem lược đồ cơ sở dữ liệu của bạn và tìm các trường phù hợp với tài liệu.

Trong trường hợp của tôi, mức tối thiểu đủ để vượt qua giai đoạn yêu cầu và chuyển sang phương thức được gỡ bỏ trả về người dùng của tôi.

Ví dụ này cũng sử dụng FactoryGirl.

Nó có thể không hoàn hảo, nhưng tôi hy vọng nó sẽ giúp. Chúc may mắn!

-Dan

+0

Perfect. Hữu ích trên nhiều cấp độ, không kém phần quan trọng là tôi đã nghĩ về điều này như một đặc tính của bộ điều khiển hơn là một đặc điểm kỹ thuật. Nhiều đánh giá cao! –

+1

Rất vui được trợ giúp! Điều này đưa tôi đến đầu gối của tôi trong một ngày rưỡi. Tôi rất vui vì ai đó có thể hưởng lợi từ sự thất vọng của tôi! Cú pháp có xa không? Nếu có, vui lòng chỉnh sửa với giải pháp đúng. Cảm ơn! –

+1

Cú pháp hoạt động hoàn hảo. Sự thay đổi duy nhất tôi thực hiện đã được kéo một chút vào spec_helper.rb sau [câu trả lời này] (http://stackoverflow.com/a/9915796/1450420) mà tôi tìm thấy nhờ câu trả lời của bạn. –

1

Tôi đang gặp vấn đề cho quằn quại RSpec cho OmniauthCallbacksController, làm một số nghiên cứu về vấn đề này và nó làm việc cho tôi. Đây là mã của tôi, nếu có ai tìm thấy cần thiết. Các xét nghiệm được cho con đường hạnh phúc và nó sẽ làm việc cho phiên bản tin tức về RSpec eg. 3.x

require 'spec_helper' 

    describe OmniauthCallbacksController, type: :controller do 
     describe "#linkedin" do 
     let(:current_user) { Fabricate(:user) } 

     before(:each) do 
      OmniAuth.config.test_mode = true 
      OmniAuth.config.mock_auth[:linkedin] = OmniAuth::AuthHash.new({provider: :linkedin, uid: '12345', credentials: {token: 'linkedin-token', secret: 'linkedin-secret'}}) 
      request.env["devise.mapping"] = Devise.mappings[:user] 

      @controller.stub!(:env).and_return({"omniauth.auth" => OmniAuth.config.mock_auth[:linkedin]}) 
      User.stub(:from_auth).and_return(current_user) 
     end 

     describe "#linkedin" do 
      context "with a new linkedin user" do 
      before { get :linkedin } 

      it "authenticate user" do 
       expect(warden.authenticated?(:user)).to be_truthy 
      end 

      it "set current_user" do 
       expect(subject.current_user).not_to be_nil 
      end 

      it "redirect to root_path" do 
       expect(response).to redirect_to(root_path) 
      end 
      end 
     end 

     end 
    end 
+0

bạn đã điều chỉnh điều này để làm việc trong rspec 3.4 chưa? –

+0

Có điều chỉnh và chỉnh sửa. –

3

Nếu bạn nhấn này và bạn đang chạy rspec 3.4 ví dụ này nên làm việc cho bạn:

describe Users::OmniauthCallbacksController, type: :controller do 
    let(:current_user) { FactoryGirl.create(:user) } 

    before do 
    OmniAuth.config.test_mode = true 
    OmniAuth.config.mock_auth[:your_oauth_provider_here] = OmniAuth::AuthHash.new(
     provider: :your_oauth_provider_here, 
     uid: rand(5**10), 
     credentials: { token: ENV['CLIENT_ID'], secret: ENV['CLIENT_SECRET'] } 
    ) 
    request.env['devise.mapping'] = Devise.mappings[:user] 
    allow(@controller).to receive(:env) { { 'omniauth.auth' => OmniAuth.config.mock_auth[:your_oauth_provider_here] } } 
    allow(User).to receive(:from_omniauth) { current_user } 
    end 

    describe '#your_oauth_provider_here' do 
    context 'new user' do 
     before { get :your_oauth_provider_here } 

     it 'authenticate user' do 
     expect(warden.authenticated?(:user)).to be_truthy 
     end 

     it 'set current_user' do 
     expect(current_user).not_to be_nil 
     end 

     it 'redirect to root_path' do 
     expect(response).to redirect_to(root_path) 
     end 
    end 
    end 
end 
Các vấn đề liên quan