RSpec 测试 ActiveAdmin member_action

RSpec test for ActiveAdmin member_action

我的活动管理面板中有自定义 member_action,负责重新发送设备重置密码说明。

admin/users.rb

ActiveAdmin.register User do

  member_action :reset_password do
    user = User.find(params[:id])
    user.send_reset_password_instructions
    redirect_to(admin_user_path(user),
                notice: "Password reset email sent to #{user.email}")
  end
end

如何为这样的操作编写 RSpec 测试?我唯一找到的是 this one,我认为它与我的问题不太相关。

我正在尝试如下所示:

require 'rails_helper'

describe Admin::UsersController, type: :controller do
  include Devise::TestHelpers

  let!(:admin) { create(:admin_user) }

  before(:each) do
    sign_in admin
  end

  describe 'GET user' do
    let(:user) { create(:user, :random_email) }

    before(:each) do
      User.should_receive(:find).at_least(:once).and_return(user)
      get :show
    end

    it 'sends email' do
      get :reset_password
      expect(user).should_receive(:send_reset_password_instructions)
    end
  end
end

但是我收到一个错误:

 ActionController::UrlGenerationError:
   No route matches {:action=>"reset_password", :controller=>"admin/users"}

我个人更喜欢使用功能测试,因为在使用活动管理员时,UI 由框架处理的内容:

RSpec.feature 'Reset Password', type: :feature do
  let(:user) { create :user }
  
  before do
    login_as(user, scope: :user)
  end

  scenario 'can delete future episode' do
    visit some_path
    click_link 'Reset Password'
    expect(page.current_path).to eq(admin_user_path(user))
    expect(page).to have_content("Password reset email sent to #{user.email}")
  end
end

好的,事实证明,小的调整(在参数中传递 user.id)就可以解决问题。

describe Admin::UsersController, type: :controller do
  include Devise::Test::ControllerHelpers

  before { sign_in admin }

  let!(:admin) { create(:admin_user) }

  describe 'GET user' do
    let(:user) { create(:user, :random_email) }

    before do
      allow(User).to receive(:find).at_least(:once) { user }
      get :show, params: { id: user.id }
    end

    it 'sends email' do
      get :reset_password, params: { id: user.id }
      expect(flash[:notice]).to match("Password reset email sent to #{user.email}")
    end
  end
end