Skip to main content

_ruby

TL;DR - Show Me The Code

3-work-with-frames/code/ruby/frames.rb
require 'selenium-webdriver'
require 'rspec/expectations'
include RSpec::Matchers

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

def teardown
@driver.quit
end

def run
setup
yield
teardown
end

run do
@driver.get 'https://the-internet.herokuapp.com/nested_frames'
frame_top = @driver.find_element(name: 'frame-top')
@driver.switch_to.frame(frame_top)
frame_middle = @driver.find_element(name: 'frame-middle')
@driver.switch_to.frame(frame_middle)
expect(@driver.find_element(id: 'content').text).to eql 'MIDDLE'
end

run do
@driver.get 'https://the-internet.herokuapp.com/tinymce'
@driver.switch_to.frame(@driver.find_element(id: 'mce_0_ifr'))
editor = @driver.find_element(id: 'tinymce')
before_text = editor.text
editor.clear
editor.send_keys 'Hello World!'
after_text = editor.text
expect(after_text).not_to eql before_text

@driver.switch_to.default_content
expect(@driver.find_element(css: 'h3').text).not_to be_empty
end

Code Walkthrough

Importing Libraries, Setup and Teardown

We'll first need to pull in our requisite libraries (selenium-webdriver to drive the browser, and rspec/expecations & RSpec::Matchers to perform our assertions) and wire up some simple setup, teardown, and run methods.

Example 1

Line 20 shows our first test. In it, we'll step through an example of nested frames from the-internet.

With Selenium's .switch_to.frame method we can simply switch to the frame we want. It accepts either an ID or name attribute, but in order to get the text of the middle frame (e.g., a frame nested within another frame), we need to switch to the parent frame (e.g., the top frame) and then switch to the child frame (e.g., the middle frame).

Once we've done that we're able to find the element we need, grab it's text, and assert that it's what we expect.

While this example helps illustrate the point of frame switching, it's not very practical.

Example 2

Here is a more likely example you'll run into -- working with a WYSIWYG Editor like TinyMCE. You can see the page we're testing here.

Once the page loads we switch into the frame that contains TinyMCE and...

  • grab the original text and store it
  • clear and input new text
  • grab the new text value
  • assert that the original and new texts are not the same

Keep in mind that if we need to access a part of the page outside the frame we are currently in we'll need to switch to it. Thankfully Selenium has a method that enables us to quickly jump back to the top level of the page -- switch_to.default_content.

Executing the Test

Before executing the test, we need to make sure the required dependencies are declared on the Gemfile file.

Toggle to see the Gemfile file.
3-work-with-frames/code/ruby/Gemfile
source 'https://rubygems.org'

gem 'rspec', '~> 3.10'
gem 'selenium-webdriver', '~> 4.24.0'

Finally, we can run the test by executing ruby frames.rb from the command-line.