Case Study: User Reset Password via Email in Selenium WebDriver

Using emails in tests is quite common. Typical cases are user-sign-up (confirm email address) and user-reset password(get password reset link). In a previous article, I went through how to use a temporary online mail service to complete the user sign up test case. This article will cover the user-reset password test case by clicking the reset link in the reset email.

The sample site I will use is WhenWise (https://whenwise.agileway.net/).

Table of Contents:
· Test Design
· MailCatcher
· TempMailo
Complete test script

Using a newly registered user for this test case. If using an existing user, changing its password might affect other testing activities.

If do use an existing user, learn more on how to clean up after reset password tests in this article.

  1. Register a new user by email
    a random email address.
  2. Enter your email on the ‘Reset Password’ page then click the “Reset” button
  3. Wait for the reset password email with the reset link and visit the reset link
  4. Enter the new password
  5. Login with email and new password successfully

There are two “gotchas” for this test case:

  1. Register a brand new user just for this test case only
    Essentially, include the ‘User Sign up’ test steps first. Because other team members are not aware of this new user, we don’t need to worry about the effect of password change.
  2. Receiving and reading emails
    This is covered in the previous article, but we can use a fake SMTP server or a temporary online mail service to receive emails.

With MailCatcher

Using a fake SMTP server.

  1. Register a new user

I won’t go into detail here; see the below article for how to register a new user and confirm their account via MailCatcher.

driver.find_element(:link_text, "Register").click
sign_up_page = SignUpPage.new(browser)
new_email = Faker::Internet.emailtry_for(2) { sign_up_page.enter_email(new_email) }
sign_up_page.enter_password("test02")
# on test server, the captcha is fixed to "wise"
sign_up_page.enter_captcha("wise")
sign_up_page.click_create_account
activate_url = niltry_for(10, 5) {
open_email("Account activation") { |email_body_html|
activate_url = Nokogiri::HTML(email_body_html).at_css("a#activate-link")["href"]
}
driver.get(activate_url)
try_for(3, 0.5) { expect(toast_text).to include("Account activated, you can sign in now.") }
}

2. Visit WhenWise password reset page, and submit a reset request.

visit("/sign-in")
driver.find_element(:link_text, "Forgot password?").click
reset_password_page = ResetPasswordPage.new(browser)
reset_password_page.enter_email(new_email)
reset_password_page.click_reset_button

3. Open the reset password email and click the reset link

The email will be displayed in MailCatcher’s web interface.

sleep 0.75
reset_url = nil
open_email("Password Reset for WhenWise") { |email_body_html|
reset_url = Nokogiri::HTML(email_body_html).at_css("a#reset-url")["href"]
}
driver.get(reset_url)

4. Set a new password

expect(page_text).to include("Password Confirmation")
change_password_page = ChangePasswordPage.new(browser)
change_password_page.enter_new_password("pass02")
change_password_page.enter_password_confirmation("pass02")
change_password_page.click_change_password
expect(toast_text).to include("Password has been reset!")

5. Verify can sign in with the new password successfully

sign_in(new_email, "pass02")
expect(toast_text).to include("You have signed in successfully")

With TempMailo

I did the below last week and it was successful. However, TempMailo has changed and added Cloudflare browser validation since. Cloudflare auto-blocks Selenium so this test will no longer run successfully. I’ve left this section in this article as a lot of the code can be reused for other temp mail sites and the concept is still valid.

It is definitely something to be aware of with using external dependencies — there’s no guarantee how long they’ll continue to be available/work for 🥲.

https://tempmailo.com/. This is one temporary mail provider I quite like. When you navigate to this page, it will have a different email address every time. See my previous article on how to use TempMailo in an automated test.

The steps in my automated test:

  1. Extract the email address from TempMailo

I extract the one-use-only email out and save it as email_address , so that I can continue to use it later in the test script.

driver.get("https://tempmailo.com/")
email_address = driver.find_element(:id, "i-email")["value"]

2. Register a new user account with this email

This is really another automated test using email checking that I covered in the below article:

3. Visit WhenWise (in a new browser tab) password reset page, and submit a reset request.

driver.execute_script("window.open('https://whenwise.agileway.net/password_resets/new?locale=en-AU', '_blank')")
driver.switch_to.window(driver.window_handles[-1]) # last tab

The switch_to.window line changes the focus to the last tab.

From here, we can enter the email address of our user and request a password reset. Close the tab and focus back on the mail tab.

forgot_password_page = ForgotPasswordPage.new(driver)
try_for(2) { forgot_password_page.enter_email(email_address) }
forgot_password_page.click_reset_password
try_for(2) { expect(page_text).to include("Email sent with password reset instructions.") }
driver.close

4. Switch back to TempMailo, and wait for the reset password email (sent from WhenWise)

driver.switch_to.window(driver.window_handles[0]) # first tab

Back at TempMailo, refresh the inbox, and the password reset email will come in. Click the email on the sidebar to open it.

driver.find_element(:xpath, "//button[@class='prim-btn']").click
driver.find_element(:xpath, "//ul[@class='mail-items-list']/li[1]").click

5. Click the password reset link in the email.

The actual email’s contents (right panel) are inside an iFrame (for more on testing with iFrames, check out Automated Testing Frames in Selenium WebDriver), so, switch to the iFrame to click the link. The link will open in a new tab:

frame = driver.find_element(:id, "fullmessage")
driver.switch_to.frame(frame)
driver.find_element(:partial_link_text, "password_resets").click

6. Follow the standard password change process, …

driver.switch_to.default_content
# switch to new tab
driver.switch_to.window(driver.window_handles[-1])

From here, the rest of the test is quite straightforward. Enter the new password and verify you can sign in with the new credentials:

reset_password_page = ResetPasswordPage.new(driver)
reset_password_page.enter_password("test02")
reset_password_page.enter_password_confirmation("test02")
reset_password_page.click_change_password
expect(page_text).to include("Password has been reset!")

sign_in_page = SignInPage.new(driver)
sign_in_page.enter_email(email_address)
sign_in_page.enter_password("test02")
sign_in_page.click_login

expect(page_text).to include("You have signed in successfully")

By the way, the above test scripts have been refactored to use Maintainable Automated Test Design.

Complete test script

it "Reset Password" do
driver.get("https://tempmailo.com/")
email_address = driver.find_element(:id, "i-email")["value"]
puts "Updated: #{email_address}"
# sign up with this account (manually)
sleep 10
driver.execute_script("window.open('https://whenwise.agileway.net/password_resets/new?locale=en-AU', '_blank')")
driver.switch_to.window(driver.window_handles[-1])
forgot_password_page = ForgotPasswordPage.new(driver)
try_for(2) { forgot_password_page.enter_email(email_address) }
forgot_password_page.click_reset_password
try_for(2) { expect(page_text).to include("Email sent with password reset instructions.") }
driver.close
driver.switch_to.window(driver.window_handles[0])

temp_mail_page = TempMailPage.new(driver)
temp_mail_page.click_refresh_emails
temp_mail_page.click_first_email
frame = driver.find_element(:id, "fullmessage")
driver.switch_to.frame(frame)
driver.find_element(:partial_link_text, "password_resets").click
driver.switch_to.default_content
driver.switch_to.window(driver.window_handles[-1])
reset_password_page = ResetPasswordPage.new(driver)
reset_password_page.enter_password("test02")
reset_password_page.enter_password_confirmation("test02")
reset_password_page.click_change_password
expect(page_text).to include("Password has been reset!")

sign_in_page = SignInPage.new(driver)
sign_in_page.enter_email(email_address)
sign_in_page.enter_password("test02")
sign_in_page.click_login

expect(page_text).to include("You have signed in successfully")
end

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store