Case Study: User Reset Password via Email in Selenium WebDriver
A typical user reset password test scenario by email.
This is also included in my “How to in Selenium WebDriver” series.
Checking emails in automated tests is quite common. Typical cases are user-sign-up (confirm email address) and user-reset password (get a password reset link). In a previous article, I went through how to use MailCatcher, or 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:
· With 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.
Register a new user by email
a random email address.Enter your email on the ‘Reset Password’ page then click the “Reset” button
Wait for the reset password email and visit the reset link in it
Enter the new password
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. I won’t go into detail here; see this article for how to register a new user and confirm their account via MailCatcher.
1. Register a new user
driver.find_element(:link_text, "Register").click
sign_up_page = SignUpPage.new(browser)
new_email = Faker::Internet.email
try_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 = nil
try_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 the WhenWise password reset page, and submit a reset request.
visit("/sign-in")
driver.find_element(:link_text, "Forgot password?").clickreset_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_passwordexpect(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")
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/ is one temporary mail provider I recently discovered and liked it. 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 this 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