Skip to content
Jon Snow edited this page Jun 15, 2016 · 4 revisions

The page-object gem provides a way to declare items are within frames or iframes. In fact, these frames can be nested infinitely. Let's look at a simple case.

class RegistrationPage
  include PageObject

  in_frame(:id => 'left-frame') do |frame|
    text_field(:address, :id => 'address_id', :frame => frame)
  end
end

As you see in this example, we are declaring that the text field resides within a frame with an id of 'left-frame'. You can identify frames or iframes by :id, :name, or :index. Also note that a frame variable is passed into the block and that it is added as an additional identifier in the call to text_field.

If you have an iframe you simply use the in_iframe call instead of the in_frame call.

Let's take another look at how the code would look if we have nested frames. We'll take the same example from above except we assume there is another nested frame.

class RegistrationPage
  include PageObject

  in_frame(:id => 'left-frame') do |outer_frame|
    in_frame({:id => 'left-top-frame'}, outer_frame) do |inner_frame|
      text_field(:address, :id => 'address_id', :frame => inner_frame)
    end
  end
end

Notice that we had to pass the frame from the outer frame to the second call to in_frame. This also forced us to place {} around the identifier in this call.

After the declaration of the nested frames you can use the elements directly. For example, to set the value in the address field you would have to do this:

@page.address = 'Some Address'

When describing nested frames in this manner, you have the ability to declare elements in each frame without affecting the scope of elements in other frames. This means that you can safely and concisely declare elements in any level of nested frames. Let's modify the previous example yet again -- this time, let's assume there is another text field in the top-level outer_frame:

class RegistrationPage
  include PageObject

  in_frame(:id => 'left-frame') do |outer_frame|
    text_field(:username, :id => 'username_id', :frame => outer_frame)

    in_frame({:id => 'left-top-frame'}, outer_frame) do |inner_frame|
      text_field(:address, :id => 'address_id', :frame => inner_frame)
    end
  end
end

This behaves as you would expect: the RegistrationPage should now be able to use the @page.username element that is in the left-frame in addition to the @page.address element located within the left-top-frame. This feature of the in_frame and in_iframe methods affords you the power to describe any arbitrary nested frame/iframe structure.