简体   繁体   English

Rails 4 +设计:如何在没有RSpec的情况下为Devise重置密码编写测试?

[英]Rails 4 + Devise: How to write a test for Devise Reset Password without RSpec?

For reasons outside of my control, I can't use RSpec for testing in my current project. 由于我无法控制的原因,我无法在当前项目中使用RSpec进行测试。 I'm trying to test Devise Reset Password, and I can't seem to come up with something that works. 我正在尝试测试Devise重置密码,我似乎无法想出一些有用的东西。

Here's what I have so far: 这是我到目前为止所拥有的:

require 'test_helper'

class ResetPasswordTest < ActionDispatch::IntegrationTest
  setup do
    @user = users(:example)
  end

  test "reset user's password" do 
    old_password = @user.encrypted_password

    puts @user.inspect

    # This assertion works
    assert_difference('ActionMailer::Base.deliveries.count', 1) do
      post user_password_path, user: {email: @user.email}
    end

    # puts @user.reset_password_token => nil
    # Not sure why this doesn't assign a reset password token to @user

    patch "/users/password", user: {
      reset_password_token: @user.reset_password_token, 
      password: "new-password", 
      password_confirmation: "new-password",
    }

    # I get a success here, but I'm not sure why, since reset password token is nil.
    assert_response :success

    # This assertion doesn't work. 
    assert_not_equal(@user.encrypted_password, old_password)
  end

end

I've added some comments above to where things don't seem to be working. 我在上面添加了一些注释,似乎没有用。 Does anyone have an insight, or an idea about how better to test this? 有没有人有一个洞察力,或者有关如何更好地测试这个的想法?

Devise tests the PasswordsController internally. 设计内部测试PasswordsController I wanted to test my PasswordsController with extra functionality and went to Devise's controller tests for help in building tests for Devise's default functionality, then adding assertions for my new functionality into the test case. 我想用额外的功能测试我的PasswordsController ,然后去Devise的控制器测试,以帮助构建Devise默认功能的测试,然后将新功能的断言添加到测试用例中。

As noted in other answers, you must obtain the reset_password_token . 如其他答案中所述,您必须获取reset_password_token Instead of parsing a delivered email as in another solution here, you could obtain the token in the same way as Devise: 您可以使用与Devise相同的方式获取令牌,而不是像在另一个解决方案中解析已发送的电子邮件一样:

setup do
  request.env["devise.mapping"] = Devise.mappings[:user]
  @user = users(:user_that_is_defined_in_fixture)
  @reset_password_token  = @user.send_reset_password_instructions
end

Check out Devise's solution for the PasswordControllerTest : 查看Devise的PasswordControllerTest解决方案:

https://github.com/plataformatec/devise/blob/master/test/controllers/passwords_controller_test.rb . https://github.com/plataformatec/devise/blob/master/test/controllers/passwords_controller_test.rb

I figured out that you need to reload the user upon sending the password reset email and when put ting the /user/password route. 我发现你需要在发送密码重置电子邮件时以及put /user/password路由时重新加载用户。 You also need to get the password token from the email as it is different from the one stored in the database. 您还需要从电子邮件中获取密码令牌,因为它与存储在数据库中的密码令牌不同。

require 'test_helper'

class ResetPasswordTest < ActionDispatch::IntegrationTest
  setup do
    @user = users(:example)
  end

  test "reset user's password" do 
    # store old encrypted password
    old_password = @user.encrypted_password

    # check to ensure mailer sends reset password email
    assert_difference('ActionMailer::Base.deliveries.count', 1) do
      post user_password_path, user: {email: @user.email}
      assert_redirected_to new_user_session_path
    end

    # Get the email, and get the reset password token from it
    message = ActionMailer::Base.deliveries[0].to_s
    rpt_index = message.index("reset_password_token")+"reset_password_token".length+1
    reset_password_token = message[rpt_index...message.index("\"", rpt_index)]

    # reload the user and ensure user.reset_password_token is present
    # NOTE: user.reset_password_token and the token pulled from the email
    # are DIFFERENT
    @user.reload
    assert_not_nil @user.reset_password_token

    # Ensure that a bad token won't reset the password
    put "/users/password", user: {
      reset_password_token: "bad reset token", 
      password: "new-password", 
      password_confirmation: "new-password",
    }

    assert_match "error", response.body
    assert_equal @user.encrypted_password, old_password

    # Valid password update
    put "/users/password", user: {
      reset_password_token: reset_password_token, 
      password: "new-password", 
      password_confirmation: "new-password",
    }

    # After password update, signed in and redirected to root path
    assert_redirected_to root_path

    # Reload user and ensure that the password is updated.
    @user.reload
    assert_not_equal(@user.encrypted_password, old_password)
  end

end
require 'rails_helper'

feature 'User' do
  let(:user) { create(:user) }
  let(:new_password) { 'Passw0rd!' }

  it 'reset password' do
    visit '/'

    click_link 'Forgot password?'
    fill_in 'E-mail', with: user.email

    expect do
      click_button 'Send me reset password instructions'
    end.to change(ActionMailer::Base.deliveries, :count).by(1)

    expect(unread_emails_for(user.email)).to be_present
    open_email(user.email, with_subject: 'Reset password instructions')
    click_first_link_in_email
    fill_in 'New password', with: new_password
    fill_in 'Confirm new password', with: new_password
    click_button 'Change password'

    expect(page).to have_notice 'Your password has changed'
    click_link 'Logout'

    fill_in 'E-mail', with: user.email
    fill_in 'Password', with: new_password

    click_button 'Sign in'
    expect(page).to have_notice 'Wellcome!'
  end
end

This code require email_spec and FactoryGirl gems. 此代码需要email_spec和FactoryGirl宝石。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM