Skip to main content

_ruby

Example

First let's include our dependent libraries (e.g., selenium-webdriver to control the browser, rspec/expectations and RSpec::Matchers for assertions, and gmail to access a Gmail account headless) and create some simple setup, teardown, and run methods to handle our test configuration.

# filename: forgot_password.rb

require 'selenium-webdriver'
require 'rspec-expectations'
include RSpec::Matchers
require 'gmail'

def setup
@driver = Selenium::WebDriver.for :firefox
end

def teardown
@driver.quit
end

def run
setup
yield
teardown
end

Once triggered, the forgot password e-mail should be received quickly. But since we're dealing with a third-party provider we'll want to build in some resiliency. So let's create a simple mechanism to retry our email lookup a configurable number of times and make it wait a handful of seconds in-between each attempt.

def try(number_of_times)
count = 0 ; item_of_interest = nil
until item_of_interest != nil || count == number_of_times
item_of_interest = yield
sleep 10
count += 1
end
end

When calling this method, we will need to specify an integer for the number of times that we'd like to retry an action. And we'll specify the action by passing it to the method through the use of yield (which enables us to pass a block of code into the method just like we're doing for the run method). Between each attempt, the method will wait for 10 seconds.

Now let's wire up our test.

run do
@driver.get 'https://the-internet.herokuapp.com/forgot_password'
@driver.find_element(id: 'email').send_keys(ENV['EMAIL_USERNAME'])
@driver.find_element(id: 'form_submit').click

gmail = Gmail.new(ENV['EMAIL_USERNAME'], ENV['EMAIL_PASSWORD'])
try(6) { @email = gmail.inbox.emails(:unread, from: 'no-reply@the-internet.herokuapp.com').last }
message_body = @email.message.body.raw_source

url = message_body.scan(/https?:\/\/[\S]+/).last
username = message_body.scan(/username: (.*)$/)[0][0].strip
password = message_body.scan(/password: (.*)$/)[0][0].strip

@driver.get url
@driver.find_element(id: 'username').send_keys username
@driver.find_element(id: 'password').send_keys password
@driver.find_element(id: 'login').submit
expect(@driver.current_url.include?('/secure')).to eql true
end

We initiate the forgot password workflow by loading the page with the forgot password form, providing an email address, and submitting the form. We then access the Gmail account headless. Notice that the username and password credentials are specified with environment variables, but you could just as easily hard-code your credentials here.

After connecting we attempt to retrieve the message body. Here is where we employ our try method (retrying the lookup action up to 6 times). If the inbox lookup doesn't find what it's looking for, it will return nil, which will trigger the try loop to run again after waiting 10 seconds. If it finds what we're looking for, then the loop will stop running and the test will proceed.

Once the forgot password email is found we parse it's body with regular expressions to find the URL & user credentials in it. We then put these values to use with our browser session (which is still active) by visiting the URL and logging in. Once done we assert that login was successful by checking to see if we gained access to a secure part of the site.

Expected Behavior

If you save this file and run it (e.g., ruby forgot_password.rb from the command-line) here is what will happen:

  • Open the browser
  • Visit the page and initiate the forgot password workflow
  • Headless access Gmail and retrieve the email message body
  • Parse the message body for user credentials
  • Visit the site and login with the user credentials
  • Check that login was successful
  • Close the browser

NOTE: When running this script you can pass in the Gmail account username and password at runtime (e.g., EMAIL_USERNAME=youremail@gmail.com EMAIL_PASSWORD=yourpassword ruby forgot_password.rb).

Summary

Your forgot password workflow might be different, so adapt as needed. And if you have other things in an e-mail message body that you need to parse for and aren't sure of the regular expressions you need -- give Rubular a try.

Happy Testing!