Рельсы 4 + разработать: Как написать тест для разработки сброс пароля без вас?


По причинам, не зависящим от меня, я не могу использовать RSpec для тестирования в моем текущем проекте. Я пытаюсь проверить, как сбросить пароль, и не могу придумать что-то, что работает.

Вот что у меня есть до сих пор:

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

Я добавил несколько комментариев выше, где вещи, кажется, не работают. Есть ли у кого-нибудь понимание или идея о том, как лучше это проверить?

3 8

3 ответа:

Devise тестирует PasswordsController внутренне. Я хотел протестировать мой PasswordsController с дополнительной функциональностью и обратился к контроллерным тестам Device за помощью в построении тестов для функциональности Device по умолчанию, а затем добавил утверждения для моей новой функциональности в тестовый случай.

Как отмечалось в других ответах, вы должны получить reset_password_token. Вместо разбора доставленного сообщения электронной почты, как в другом решении здесь, вы можете получить маркер тем же способом, что и 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

Проверьте Devise решение для PasswordControllerTest:

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

Я понял, что вам нужно перезагрузить пользователя при отправке электронной почты сброса пароля и при putтинге маршрута /user/password. Вам также необходимо получить маркер пароля из электронной почты, так как он отличается от того, который хранится в базе данных.

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

Этот код требует email_spec и FactoryGirl gems.