19 |
20 |
--------------------------------------------------------------------------------
/spec/page-object/elements/label_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 | require 'page-object/elements'
3 |
4 | describe PageObject::Elements::Label do
5 | let(:label) { PageObject::Elements::Label }
6 |
7 | describe "interface" do
8 | it "should register with tag :label" do
9 | expect(::PageObject::Elements.element_class_for(:label)).to eql ::PageObject::Elements::Label
10 | end
11 | end
12 | end
13 |
14 |
--------------------------------------------------------------------------------
/spec/page-object/elements/file_field_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 | require 'page-object/elements'
3 |
4 | describe PageObject::Elements::FileField do
5 |
6 | describe "interface" do
7 | let(:filefield) { double('file_field') }
8 |
9 | it "should register as type :file" do
10 | expect(::PageObject::Elements.element_class_for(:input, :file)).to eql ::PageObject::Elements::FileField
11 | end
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/spec/page-object/elements/paragraph_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 | require 'page-object/elements'
3 |
4 | describe PageObject::Elements::Paragraph do
5 | let(:paragraph) { PageObject::Elements::Paragraph }
6 |
7 | describe "interface" do
8 | it "should register with type :checkbox" do
9 | expect(::PageObject::Elements.element_class_for(:p)).to eql ::PageObject::Elements::Paragraph
10 | end
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/spec/page-object/elements/list_item_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 | require 'page-object/elements'
3 |
4 | describe PageObject::Elements::ListItem do
5 | let(:list_item) { PageObject::Elements::ListItem }
6 |
7 | describe "interface" do
8 | it "should register as tag_name :li" do
9 | expect(::PageObject::Elements.element_class_for(:li)).to eql ::PageObject::Elements::ListItem
10 | end
11 |
12 | end
13 | end
14 |
15 |
--------------------------------------------------------------------------------
/spec/page-object/elements/text_area_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 | require 'page-object/elements'
3 |
4 | describe PageObject::Elements::TextArea do
5 | let(:textarea) { PageObject::Elements::TextArea }
6 |
7 | describe "interface" do
8 | it "should register with tag_name :textarea" do
9 | expect(::PageObject::Elements.element_class_for(:textarea)).to eql ::PageObject::Elements::TextArea
10 | end
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/spec/page-object/elements/hidden_field_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 | require 'page-object/elements'
3 |
4 | describe PageObject::Elements::HiddenField do
5 | let(:hiddenfield) { PageObject::Elements::HiddenField }
6 |
7 | describe "interface" do
8 | it "should register with type :hidden" do
9 | expect(::PageObject::Elements.element_class_for(:input, :hidden)).to eql ::PageObject::Elements::HiddenField
10 | end
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/features/modal_dialog.feature:
--------------------------------------------------------------------------------
1 | Feature: handing modal dialogs
2 |
3 | Background:
4 | Given I am on the modal page
5 |
6 |
7 | Scenario: Interacting with a modal dialog
8 | When I open a modal dialog
9 | Then I should be able to close the modal
10 |
11 | Scenario: Nested modal dialogs
12 | When I open a modal dialog
13 | And I open another modal dialog from that one
14 | #Then I should be able to close both modals
15 |
16 |
--------------------------------------------------------------------------------
/spec/page-object/elements/link_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 | require 'page-object/elements'
3 |
4 | describe PageObject::Elements::Link do
5 | let(:link) { PageObject::Elements::Link }
6 |
7 | describe "interface" do
8 | let(:link_element) { double('link_element') }
9 |
10 | it "should register with tag :a" do
11 | expect(::PageObject::Elements.element_class_for(:a)).to eql ::PageObject::Elements::Link
12 | end
13 | end
14 | end
15 |
--------------------------------------------------------------------------------
/lib/page-object/elements/button.rb:
--------------------------------------------------------------------------------
1 | module PageObject
2 | module Elements
3 | class Button < Element
4 |
5 | end
6 |
7 | ::PageObject::Elements.type_to_class[:submit] = ::PageObject::Elements::Button
8 | ::PageObject::Elements.type_to_class[:image] = ::PageObject::Elements::Button
9 | ::PageObject::Elements.type_to_class[:button] = ::PageObject::Elements::Button
10 | ::PageObject::Elements.type_to_class[:reset] = ::PageObject::Elements::Button
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/lib/page-object/section_collection.rb:
--------------------------------------------------------------------------------
1 | module PageObject
2 | class SectionCollection < Array
3 | def find_by(values_hash)
4 | find do |section|
5 | values_hash.all? { |key, value| value === section.public_send(key) }
6 | end
7 | end
8 |
9 | def select_by(values_hash)
10 | matches = select do |section|
11 | values_hash.all? { |key, value| value === section.public_send(key) }
12 | end
13 | self.class[*matches]
14 | end
15 | end
16 | end
17 |
--------------------------------------------------------------------------------
/lib/page-object/javascript/yui.rb:
--------------------------------------------------------------------------------
1 | module PageObject
2 | module Javascript
3 |
4 | module YUI
5 | #
6 | # return the number of pending ajax requests
7 | #
8 | def self.pending_requests
9 | "var inProgress=0
10 | for(var i=0; i < YAHOO.util.Connect._transaction_id; i++) {
11 | if(YAHOO.util.Connect.isCallInProgress(i))
12 | inProgress++;
13 | }
14 | return inProgress;"
15 | end
16 | end
17 |
18 | end
19 | end
--------------------------------------------------------------------------------
/lib/page-object/element_locators.rb:
--------------------------------------------------------------------------------
1 | require 'page-object/locator_generator'
2 |
3 | module PageObject
4 | module ElementLocators
5 |
6 | def self.included(cls)
7 | ::PageObject::LocatorGenerator.generate_locators(cls)
8 | end
9 |
10 | def element(tag, identifier={:index => 0})
11 | platform.element_for(tag, identifier.clone)
12 | end
13 |
14 | private
15 |
16 | def locator(identifier)
17 | identifier[0] ? identifier[0] : {:index => 0}
18 | end
19 |
20 | end
21 | end
22 |
--------------------------------------------------------------------------------
/features/html/modal.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | modal dialog test page
4 |
5 |
6 |
7 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/spec/page-object/elements/table_cell_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 | require 'page-object/elements'
3 |
4 | describe PageObject::Elements::TableCell do
5 |
6 | context "interface" do
7 | it "should register with tag_name :td" do
8 | expect(::PageObject::Elements.element_class_for(:td)).to eql ::PageObject::Elements::TableCell
9 | end
10 |
11 | it "should register with tag_name :th" do
12 | expect(::PageObject::Elements.element_class_for(:th)).to eql ::PageObject::Elements::TableCell
13 | end
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/spec/page-object/platforms/watir/watir_page_object_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe PageObject::Platforms::Watir do
4 | describe "is for?" do
5 | it "should be true when the browser is Watir::Browser" do
6 | browser = mock_watir_browser
7 | expect(PageObject::Platforms::Watir.is_for?(browser)).to be true
8 | end
9 |
10 | it "should be false at any other point" do
11 | browser = 'asdf'
12 | expect(PageObject::Platforms::Watir.is_for?('asdf')).to be false
13 | end
14 | end
15 | end
16 |
17 |
--------------------------------------------------------------------------------
/features/step_definitions/table_cell_steps.rb:
--------------------------------------------------------------------------------
1 | When /^I search for the table cell by "([^\"]*)"$/ do |how|
2 | @cell_data = @page.send "cell_#{how}"
3 | end
4 |
5 | When /^I retrieve a table cell element by "([^"]*)" and "([^"]*)"$/ do |param1, param2|
6 | @cell_data = @page.send "cell_#{param1}_#{param2}"
7 | end
8 |
9 | When /^I retrieve a table cell element while the script is executing$/ do
10 | @cell_data = @page.cell_element(:id => 'cell_id').text
11 | end
12 |
13 | Then /^I should see that the cell exists$/ do
14 | expect(@page.cell_id?).to be true
15 | end
--------------------------------------------------------------------------------
/spec/page-object/elements/check_box_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 | require 'page-object/elements'
3 |
4 | describe PageObject::Elements::CheckBox do
5 | let(:checkbox) { PageObject::Elements::CheckBox }
6 |
7 | describe "interface" do
8 | let(:check_box) { double('check_box') }
9 | let(:selenium_cb) { PageObject::Elements::CheckBox.new(check_box) }
10 |
11 | it "should register with type :checkbox" do
12 | expect(::PageObject::Elements.element_class_for(:input, :checkbox)).to eql ::PageObject::Elements::CheckBox
13 | end
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/features/step_definitions/area_steps.rb:
--------------------------------------------------------------------------------
1 | When /^I search for the area by "([^\"]*)"$/ do |how|
2 | @how = how
3 | end
4 |
5 | Then /^I should be able to click the area$/ do
6 | @page.send("area_#{@how}")
7 | end
8 |
9 | Then /^I should see the coordinates are "([^\"]*)"$/ do |coords|
10 | expect(@element.coords).to eql coords
11 | end
12 |
13 | Then /^I should see the shape is "([^\"]*)"$/ do |shape|
14 | expect(@element.shape).to eql shape
15 | end
16 |
17 | Then /^I should see the href is "([^\"]*)"$/ do |href|
18 | expect(@element.href).to include href
19 | end
20 |
--------------------------------------------------------------------------------
/features/bold.feature:
--------------------------------------------------------------------------------
1 | Feature: Bold
2 |
3 | Background:
4 | Given I am on the static elements page
5 |
6 | Scenario: Getting the text of headings
7 | When I get the bold text for the "b" element
8 | Then I should see "some text in bold" in bold
9 |
10 | Scenario Outline: Locating b on the Page
11 | When I search bold text for the b by ""
12 | Then I should see "some text in bold" in bold
13 |
14 | Scenarios:
15 | | search_by |
16 | | id |
17 | | class |
18 | | xpath |
19 | | index |
20 | | css |
21 |
--------------------------------------------------------------------------------
/features/step_definitions/canvas_steps.rb:
--------------------------------------------------------------------------------
1 | When /^I search for the canvas by "([^\"]*)"$/ do |how|
2 | @element = @page.send "canvas_#{how}_element"
3 | end
4 |
5 | Then /^I should see that the canvas width is "([^\"]*)"$/ do |width|
6 | expect(@element.width).to eql width.to_i
7 | end
8 |
9 | Then /^I should see that the canvas height is "([^\"]*)"$/ do |height|
10 | expect(@element.height).to eql height.to_i
11 | end
12 |
13 | When /^I search for the canvas element by "([^"]*)" and "([^"]*)"$/ do |param1, param2|
14 | @element = @page.send "canvas_#{param1}_#{param2}_element"
15 | end
16 |
--------------------------------------------------------------------------------
/features/italic.feature:
--------------------------------------------------------------------------------
1 | Feature: Italic
2 |
3 | Background:
4 | Given I am on the static elements page
5 |
6 | Scenario: Getting the text of headings
7 | When I get the italic text for the "i" element
8 | Then I should see "some text in italic" in italic
9 |
10 | Scenario Outline: Locating i on the Page
11 | When I search italic text for the i by ""
12 | Then I should see "some text in italic" in italic
13 |
14 | Scenarios:
15 | | search_by |
16 | | id |
17 | | class |
18 | | xpath |
19 | | index |
20 | | css |
21 |
--------------------------------------------------------------------------------
/features/html/modal_2.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Modal 2
5 |
6 |
15 |
16 |
17 |
18 |
19 |
20 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/features/step_definitions/form_steps.rb:
--------------------------------------------------------------------------------
1 | Then /^I should be able to submit the form$/ do
2 | @element.submit
3 | end
4 |
5 | When /^I locate the form by "([^\"]*)"$/ do |how|
6 | @element = @page.send "form_#{how}_element"
7 | end
8 |
9 | When /^I locate the form using "([^"]*)" and "([^"]*)"$/ do |param1, param2|
10 | @element = @page.send "form_#{param1}_#{param2}_element"
11 | end
12 |
13 | When /^I locate a form while the script is executing$/ do
14 | @element = @page.form_element(:id => 'form_id')
15 | end
16 |
17 | Then /^I should see that the form exists$/ do
18 | expect(@page.form_id?).to be true
19 | end
--------------------------------------------------------------------------------
/features/step_definitions/div_steps.rb:
--------------------------------------------------------------------------------
1 | When /^I get the text from the div$/ do
2 | @text = @page.div_id
3 | end
4 |
5 | When /^I search for the div by "([^\"]*)"$/ do |how|
6 | @text = @page.send "div_#{how}".to_sym
7 | end
8 |
9 | When /^I search for the div by "([^"]*)" and "([^"]*)"$/ do |param1, param2|
10 | @text = @page.send "div_#{param1}_#{param2}".to_sym
11 | end
12 |
13 | When /^I get the text from a div while the script is executing$/ do
14 | @text = @page.div_element(:id => 'div_id').text
15 | end
16 |
17 | Then /^I should see that the div exists$/ do
18 | expect(@page.div_id?).to be true
19 | end
20 |
--------------------------------------------------------------------------------
/features/html/frames.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Frames
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/features/step_definitions/span_steps.rb:
--------------------------------------------------------------------------------
1 | When /^I get the text from the span$/ do
2 | @text = @page.span_id
3 | end
4 |
5 | When /^I search for the span by "([^\"]*)"$/ do |how|
6 | @text = @page.send "span_#{how}".to_sym
7 | end
8 |
9 | When /^I search for the span by "([^"]*)" and "([^"]*)"$/ do |param1, param2|
10 | @text = @page.send "span_#{param1}_#{param2}".to_sym
11 | end
12 |
13 | When /^I get the text from a span while the script is executing$/ do
14 | @text = @page.span_element(:id => 'span_id').text
15 | end
16 |
17 | Then /^I should see that the span exists$/ do
18 | expect(@page.span_id?).to eql true
19 | end
20 |
--------------------------------------------------------------------------------
/features/step_definitions/label_steps.rb:
--------------------------------------------------------------------------------
1 | When /^I get the text from the label$/ do
2 | @text = @page.label_id
3 | end
4 |
5 | When /^I search for the label by "([^\"]*)"$/ do |how|
6 | @text = @page.send "label_#{how}".to_sym
7 | end
8 |
9 | When /^I search for the label by "(.*)" and "(.*)"$/ do |param1, param2|
10 | @text = @page.send "label_#{param1}_#{param2}".to_sym
11 | end
12 |
13 | When /^I get the text from a label while the script is executing$/ do
14 | @text = @page.label_element(:id => 'label_id').text
15 | end
16 |
17 | Then /^I should see that the label exists$/ do
18 | expect(@page.label_id?).to be true
19 | end
20 |
--------------------------------------------------------------------------------
/features/step_definitions/list_item_steps.rb:
--------------------------------------------------------------------------------
1 | When /^I get the text from the list item$/ do
2 | @text = @page.li_id
3 | end
4 |
5 | When /^I search for the list item by "([^\"]*)"$/ do |how|
6 | @text = @page.send "li_#{how}"
7 | end
8 |
9 | When /^I search for the list item by "([^"]*)" and "([^"]*)"$/ do |param1, param2|
10 | @text = @page.send "li_#{param1}_#{param2}"
11 | end
12 |
13 | When /^I search for the list item while the script is executing$/ do
14 | @text = @page.list_item_element(:id => 'li_id').text
15 | end
16 |
17 | Then /^I should see that the list item exists$/ do
18 | expect(@page.li_id?).to eql true
19 | end
20 |
--------------------------------------------------------------------------------
/features/step_definitions/file_field_steps.rb:
--------------------------------------------------------------------------------
1 | When /^I set the file field to the step definition file$/ do
2 | @page.file_field_id = __FILE__
3 | end
4 |
5 | Then /^its\' value should equal that file$/ do
6 | expect(__FILE__).to include @page.file_field_id_element.value[/[^\\]*$/]
7 | end
8 |
9 | When /^I search for the file field by "([^\"]*)"$/ do |how|
10 | @how = how
11 | end
12 |
13 | When /^I search for the file field by "([^\"]*)" and "([^\"]*)"$/ do |param1, param2|
14 | @how = "#{param1}_#{param2}"
15 | end
16 |
17 | Then /^I should be able to set the file field$/ do
18 | @page.send "file_field_#{@how}=", __FILE__
19 | end
20 |
--------------------------------------------------------------------------------
/lib/page-object/elements/heading.rb:
--------------------------------------------------------------------------------
1 | module PageObject
2 | module Elements
3 | class Heading < Element
4 |
5 | end
6 |
7 | ::PageObject::Elements.tag_to_class[:h1] = ::PageObject::Elements::Heading
8 | ::PageObject::Elements.tag_to_class[:h2] = ::PageObject::Elements::Heading
9 | ::PageObject::Elements.tag_to_class[:h3] = ::PageObject::Elements::Heading
10 | ::PageObject::Elements.tag_to_class[:h4] = ::PageObject::Elements::Heading
11 | ::PageObject::Elements.tag_to_class[:h5] = ::PageObject::Elements::Heading
12 | ::PageObject::Elements.tag_to_class[:h6] = ::PageObject::Elements::Heading
13 | end
14 | end
15 |
--------------------------------------------------------------------------------
/features/support/ajax_text_environment.rb:
--------------------------------------------------------------------------------
1 | require File.dirname(__FILE__) + "/../sample-app/sample_app"
2 |
3 | class AjaxTestEnvironment
4 | def run
5 | Thread.abort_on_exception = true
6 | @example_app = Thread.new { SampleApp.start("127.0.0.1", 4567) }
7 | poller = Selenium::WebDriver::SocketPoller.new("127.0.0.1", 4567, 60)
8 | unless poller.connected?
9 | raise "timed out waiting for SampleApp to launch"
10 | end
11 |
12 | self
13 | end
14 |
15 | def stop
16 | @example_app.kill
17 | end
18 |
19 | end
20 |
21 | @server = AjaxTestEnvironment.new
22 | @server.run
23 |
24 | at_exit do
25 | @server.stop
26 | end
27 |
--------------------------------------------------------------------------------
/spec/page-object/elements/form_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 | require 'page-object/elements'
3 |
4 | describe PageObject::Elements::Form do
5 | describe "interface" do
6 | let(:form_element) { double('form_element') }
7 |
8 | it "should register with tag_name :form" do
9 | expect(::PageObject::Elements.element_class_for(:form)).to eql ::PageObject::Elements::Form
10 | end
11 |
12 | context "for watir" do
13 | it "should submit a form" do
14 | form = PageObject::Elements::Form.new(form_element)
15 | expect(form_element).to receive(:submit)
16 | form.submit
17 | end
18 | end
19 | end
20 | end
21 |
--------------------------------------------------------------------------------
/spec/page-object/elements/option_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 | require 'page-object/elements'
3 |
4 | describe PageObject::Elements::Option do
5 |
6 | describe "interface" do
7 | it "should register as tag_name :option" do
8 | expect(::PageObject::Elements.element_class_for(:option)).to eql ::PageObject::Elements::Option
9 | end
10 | end
11 |
12 | describe "interacting with the option" do
13 | let(:wd) { double('') }
14 | let(:native) { double(wd: wd) }
15 | let(:element) { PageObject::Elements::Option.new(native) }
16 |
17 | it 'should know if it is selected' do
18 | expect(native).to receive(:selected?).and_return true
19 | expect(element.selected?).to be true
20 | end
21 | end
22 | end
23 |
--------------------------------------------------------------------------------
/features/step_definitions/table_row_steps.rb:
--------------------------------------------------------------------------------
1 | When /^I search for the table row by "([^\"]*)"$/ do |how|
2 | @row_data = @page.send "tr_#{how}"
3 | end
4 |
5 | When /^I retrieve a table row element by "([^"]*)" and "([^"]*)"$/ do |param1, param2|
6 | @row_data = @page.send "tr_#{param1}_#{param2}"
7 | end
8 |
9 | When /^I retrieve a table row element while the script is executing$/ do
10 | @row_data = @page.row_element(:id => 'tr_id').text
11 | end
12 |
13 | Then /^I should see that the row exists$/ do
14 | expect(@page.tr_id?).to be true
15 | end
16 |
17 | When /^I retrieve the data from the table row/ do
18 | @row_data = @page.tr_id
19 | end
20 |
21 | Then /^the row data should be '([^"]*)'$/ do |expected|
22 | expect(@row_data).to eql expected
23 | end
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | require 'rubygems'
2 | require 'bundler'
3 | require 'rspec/core/rake_task'
4 | require 'cucumber'
5 | require 'cucumber/rake/task'
6 | require 'coveralls/rake/task'
7 |
8 | Coveralls::RakeTask.new
9 | Bundler::GemHelper.install_tasks
10 |
11 | RSpec::Core::RakeTask.new(:spec) do |spec|
12 | spec.ruby_opts = "-I lib:spec"
13 | spec.pattern = 'spec/**/*_spec.rb'
14 | end
15 | task :spec
16 |
17 | Cucumber::Rake::Task.new(:features, "Run the cucumber features")
18 |
19 |
20 | desc 'Run all specs and cukes'
21 | task :test => ['spec', 'features']
22 |
23 | task :lib do
24 | $LOAD_PATH.unshift(File.expand_path("lib", File.dirname(__FILE__)))
25 | end
26 |
27 | task :test_with_coveralls => [:test, 'coveralls:push']
28 |
29 | task :default => :test_with_coveralls
30 |
--------------------------------------------------------------------------------
/features/sample-app/public/audio_video.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Audio and Video
4 |
5 |
6 |
7 |
Audio & Video
8 |
15 |
16 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/features/async.feature:
--------------------------------------------------------------------------------
1 | Feature: Handling Asynch calls
2 |
3 | Background:
4 | Given I am on the async elements page
5 |
6 | Scenario: Click a button when it is visible
7 | When I make the button invisible
8 | Then I should be able to click it when it becomses visible
9 |
10 | Scenario: Wait until something is not visible
11 | Then I should be able to wait until the button becomes invisible
12 |
13 | Scenario: Wait for an element to appear on the page
14 | When I add a button a few seconds from now
15 | Then I should be able to click it when it gets added
16 |
17 | Scenario: Wait for an element to disappear from the page
18 | When I add a button a few seconds from now
19 | And I remove a button a few seconds from now
20 | Then I should not be able to find the button
21 |
22 |
--------------------------------------------------------------------------------
/features/step_definitions/ordered_list_steps.rb:
--------------------------------------------------------------------------------
1 | When /^I get the first item from the ordered list$/ do
2 | @element = @page.ol_id_element[0]
3 | end
4 |
5 | When /^I search for the ordered list by "([^\"]*)"$/ do |how|
6 | @list = @page.send "ol_#{how}_element"
7 | end
8 |
9 | When /^I search for the ordered list by "([^"]*)" and "([^"]*)"$/ do |param1, param2|
10 | @list = @page.send "ol_#{param1}_#{param2}_element"
11 | end
12 |
13 | When /^I search for the ordered list while the script is executing$/ do
14 | @list = @page.ordered_list_element(:id => 'ol_id')
15 | end
16 |
17 | Then /^I should see that the ordered list exists$/ do
18 | expect(@page.ol_id?).to eql true
19 | end
20 |
21 | Then /^the text for the ordered list should contain "(.*)"$/ do |text|
22 | expect(@page.send("ol_id")).to include text
23 | end
24 |
--------------------------------------------------------------------------------
/features/step_definitions/generic_element_steps.rb:
--------------------------------------------------------------------------------
1 | When /^I get the text from the article$/ do
2 | @text = @page.article_id
3 | end
4 |
5 | When /^I get the text from the header$/ do
6 | @text = @page.header_id
7 | end
8 |
9 | When /^I get the text from the footer$/ do
10 | @text = @page.footer_id
11 | end
12 |
13 | When /^I get the text from the summary$/ do
14 | @text = @page.summary_id
15 | end
16 |
17 | When /^I get the text from the details$/ do
18 | @text = @page.details_id
19 | end
20 |
21 | When /^I get the svg element$/ do
22 | @svg = @page.svg_id_element
23 | end
24 |
25 | Then /^the svg width should be "(.*?)"$/ do |width|
26 | expect(@svg.attribute('width')).to eql width
27 | end
28 |
29 | Then /^the svg height should be "(.*?)"$/ do |height|
30 | expect(@svg.attribute('height')).to eql height
31 | end
32 |
--------------------------------------------------------------------------------
/features/step_definitions/unordered_list_steps.rb:
--------------------------------------------------------------------------------
1 | When /^I get the first item from the unordered list$/ do
2 | @element = @page.ul_id_element[0]
3 | end
4 |
5 | When /^I search for the unordered list by "([^\"]*)"$/ do |how|
6 | @list = @page.send "ul_#{how}_element"
7 | end
8 |
9 | When /^I search for the unordered list by "([^"]*)" and "([^"]*)"$/ do |param1, param2|
10 | @list = @page.send "ul_#{param1}_#{param2}_element"
11 | end
12 |
13 | When /^I search for the unordered list while the script is executing$/ do
14 | @list = @page.unordered_list_element(:id => 'ul_id')
15 | end
16 |
17 | Then /^I should see that the unordered list exists$/ do
18 | expect(@page.ul_id?).to be true
19 | end
20 |
21 | Then /^the text for the unordered list should contain "(.*)"$/ do |text|
22 | expect(@page.send("ul_id")).to include text
23 | end
24 |
--------------------------------------------------------------------------------
/features/step_definitions/radio_button_steps.rb:
--------------------------------------------------------------------------------
1 | When /^I select the "([^\"]*)" radio button$/ do |how|
2 | @page.send "select_#{how.downcase}_id".to_sym
3 | end
4 |
5 | Then /^the "([^\"]*)" radio button should be selected$/ do |how|
6 | @page.send "#{how.downcase}_id_selected?".to_sym
7 | end
8 |
9 | When /^I search for the radio button by "([^\"]*)"$/ do |how|
10 | @how = how
11 | end
12 |
13 | When /^I search for the radio button by "([^"]*)" and "([^"]*)"$/ do |param1, param2|
14 | @how = "#{param1}_#{param2}"
15 | end
16 |
17 | When /^I select the radio button$/ do
18 | @page.send "select_milk_#{@how}".to_sym
19 | end
20 |
21 | When /^I select the radio button while the script is executing$/ do
22 | @page.radio_button_element(:id => 'milk_id').select
23 | end
24 |
25 | Then /^I should see that the radio button exists$/ do
26 | expect(@page.milk_id?).to eql true
27 | end
--------------------------------------------------------------------------------
/features/step_definitions/audio_steps.rb:
--------------------------------------------------------------------------------
1 | When /^I search for the audio element by "([^\"]*)"$/ do |how|
2 | @element = @avpage.send "audio_#{how}_element"
3 | end
4 |
5 | When /^I search for the audio element by "([^"]*)" and "([^"]*)"$/ do |param1, param2|
6 | @element = @avpage.send "audio_#{param1}_#{param2}_element"
7 | end
8 |
9 | When /^I retrieve the audio element from the page$/ do
10 | @element = @avpage.audio_id_element
11 | end
12 |
13 | Then /^I should know the audio is not autoplay$/ do
14 | expect(@element).not_to be_autoplay
15 | end
16 |
17 | Then /^I should know that the controls are displayed$/ do
18 | expect(@element).to have_controls
19 | end
20 |
21 | Then /^I should know that the audio is paused$/ do
22 | expect(@element).to be_paused
23 | end
24 |
25 | Then /^I should know that its volume is (\d+)$/ do |volume|
26 | expect(@element.volume).to eql volume.to_f
27 | end
28 |
--------------------------------------------------------------------------------
/features/support/audio_video_page.rb:
--------------------------------------------------------------------------------
1 | class AudioVideoPage
2 | include PageObject
3 |
4 | page_url "http://localhost:4567/audio_video.html"
5 |
6 | audio(:audio_id, :id => 'audio')
7 | audio(:audio_name, :name => 'audio')
8 | audio(:audio_class, :class => 'audio')
9 | audio(:audio_css, :css => '.audio')
10 | audio(:audio_index, :index => 0)
11 | audio(:audio_xpath, :xpath => '//audio')
12 | audio(:audio_class_index, :class => 'audio', :index => 0)
13 | audio(:audio_name_index, :name => 'audio', :index => 0)
14 |
15 | video(:video_id, :id => 'video')
16 | video(:video_name, :name => 'video')
17 | video(:video_class, :class => 'video')
18 | video(:video_css, :css => '.video')
19 | video(:video_index, :index => 0)
20 | video(:video_xpath, :xpath => '//video')
21 | video(:video_class_index, :class => 'video', :index => 0)
22 | video(:video_name_index, :name => 'video', :index => 0)
23 |
24 | end
25 |
--------------------------------------------------------------------------------
/Guardfile:
--------------------------------------------------------------------------------
1 | # A sample Guardfile
2 | # More info at https://github.com/guard/guard#readme
3 |
4 |
5 | guard :rspec, cmd: 'rspec --color --format documentation' do
6 | watch(%r{^spec/.+_spec\.rb$})
7 | watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
8 | watch(%r{^lib/page-object/platforms/(.+)/.+\.rb$}) do |m|
9 | ["spec/page-object/platforms/#{m[1]}/", "spec/page-object/page-object_spec.rb"]
10 | end
11 | watch('spec/spec_helper.rb') { "spec" }
12 | end
13 |
14 | guard 'cucumber', notification: true, all_after_pass: false, cli: '--profile focus' do
15 | watch(%r{^features/.+\.feature$})
16 | watch(%r{^features/support/.+$}) { "features" }
17 | watch(%r{^features/step_definitions/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'features' }
18 | watch(%r{^lib/.+\.rb$}) { "features" }
19 | watch(%r{^cucumber.yml$}) { "features" }
20 | end
21 |
--------------------------------------------------------------------------------
/features/gxt_table_extension.feature:
--------------------------------------------------------------------------------
1 | Feature: Gxt Table Extension
2 | As a Quality Engineer working on a Gxt or Gwt project
3 | In order to easily create test widgets to interact with application widgets
4 | I need to define, register and use widgets as if they were normal elements
5 |
6 | Background:
7 | Given I have defined a GxtTable class extending Table
8 | And I have registered the GxtTable with PageObject
9 | And I define a page-object using that widget
10 | And I am on the Gxt Examples page
11 |
12 | Scenario: Retrieve a GxtTable
13 | When I retrieve a GxtTable widget
14 | Then I should know it is visible
15 |
16 | Scenario: Determine if a GxtTable exists
17 | When I retrieve a GxtTable widget
18 | Then I should know it exists
19 |
20 | Scenario: Confirm a correct row count from a GxtTable
21 | When I retrieve a GxtTable widget
22 | Then the GxtTable should have "3" rows
23 |
--------------------------------------------------------------------------------
/features/step_definitions/paragraph_steps.rb:
--------------------------------------------------------------------------------
1 |
2 | When /^I get the text from the paragraph$/ do
3 | @text = @page.p_id
4 | end
5 |
6 | When /^I search for the paragraph by "([^"]*)"$/ do |how|
7 | @text = @page.send "p_#{how}".to_sym
8 | end
9 |
10 | When /^I search for the paragraph by "([^"]*)" and "([^"]*)"$/ do |param1, param2|
11 | @text = @page.send "p_#{param1}_#{param2}"
12 | end
13 |
14 | When /^I get the text from a paragraph while the script is executing$/ do
15 | @text = @page.paragraph_element(:id => 'p_id').text
16 | end
17 |
18 | Then /^I should see that the paragraph exists$/ do
19 | expect(@page.p_id?).to eql true
20 | end
21 |
22 | Then(/^I should know the paragraph class is "(.*?)"$/) do |class_name|
23 | expect(@page.p_id_element.class_name).to eql class_name
24 | end
25 |
26 | Then(/^I should be able to select "(.*?)" from the paragraph$/) do |text|
27 | @page.p_id_element.select_text text
28 | end
29 |
--------------------------------------------------------------------------------
/features/sample-app/sample_app.rb:
--------------------------------------------------------------------------------
1 | require 'rubygems'
2 | require 'rack'
3 | require 'webrick'
4 |
5 |
6 | class SampleApp
7 |
8 | def self.start(host, port)
9 | Rack::Handler::WEBrick.run new,
10 | :Host => host,
11 | :Port => port,
12 | :Logger => ::WEBrick::Log.new(RUBY_PLATFORM =~ /mswin|mingw/ ? 'NUL:' : '/dev/null'),
13 | :AccessLog => [nil, nil]
14 | end
15 |
16 | def initialize
17 | @public = Rack::File.new(File.expand_path("../public", __FILE__))
18 | end
19 |
20 | def call(env)
21 | req = Rack::Request.new(env)
22 |
23 | case req.path
24 | when "/"
25 | [200, {}, ["Sample Application"]]
26 | when "/compute"
27 | sleep 3
28 | resp = eval(req.params['calculator-expression']).to_s
29 | [200, {}, [resp]]
30 | else
31 | @public.call(env)
32 | end
33 | end
34 |
35 | end
36 |
--------------------------------------------------------------------------------
/features/file_field.feature:
--------------------------------------------------------------------------------
1 | Feature: File Field
2 |
3 | Background:
4 | Given I am on the static elements page
5 |
6 | Scenario: Setting the value on the file field
7 | When I set the file field to the step definition file
8 | Then its' value should equal that file
9 |
10 | Scenario Outline: Locating file fields on the Page
11 | When I search for the file field by ""
12 | Then I should be able to set the file field
13 |
14 | Examples:
15 | | search_by |
16 | | id |
17 | | class |
18 | | name |
19 | | xpath |
20 | | title |
21 | | index |
22 | | label |
23 | | css |
24 |
25 | Scenario Outline: Locating file fields using multiple parameters
26 | When I search for the file field by "" and ""
27 | Then I should be able to set the file field
28 |
29 | Examples:
30 | | param1 | param2 |
31 | | class | index |
32 | | name | index |
33 |
--------------------------------------------------------------------------------
/features/html/modal_1.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Modal 1
5 |
6 |
23 |
24 |
25 |
26 |
27 |
28 |
Modal 1
29 |
30 |
Close buttons
31 |
32 |
33 |
34 |
Nested modal
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/features/step_definitions/hidden_field_steps.rb:
--------------------------------------------------------------------------------
1 | When /^I retrieve the hidden field element$/ do
2 | @element = @page.hidden_field_id_element
3 | end
4 |
5 | Then /^I should see the hidden field contains "([^\"]*)"$/ do |text|
6 | expect(@page.hidden_field_id).to eql text
7 | end
8 |
9 | When /^I search for the hidden field by "([^\"]*)"$/ do |how|
10 | @element = @page.send "hidden_field_#{how}_element"
11 | end
12 |
13 | Then /^the hidden field element should contain "([^\"]*)"$/ do |text|
14 | expect(@element.value).to eql text
15 | end
16 |
17 | When /^I search for the hidden field by "([^"]*)" and "([^"]*)"$/ do |param1, param2|
18 | @element = @page.send "hidden_field_#{param1}_#{param2}_element"
19 | end
20 |
21 | When /^I find a hidden field while the script is executing$/ do
22 | @element = @page.hidden_field_element(:id => 'hidden_field_id')
23 | end
24 |
25 | Then /^I should see that the hidden field exists$/ do
26 | expect(@page.hidden_field_id?).to eql true
27 | end
--------------------------------------------------------------------------------
/features/area.feature:
--------------------------------------------------------------------------------
1 | Feature: Area
2 |
3 | Background:
4 | Given I am on the static elements page
5 |
6 | Scenario: Retrieve an area element
7 | When I retrieve the area element
8 | Then I should know it exists
9 | And I should know it is visible
10 |
11 | Scenario Outline: Locating areas on the page
12 | When I search for the area by ""
13 | Then I should be able to click the area
14 |
15 | Examples:
16 | | search_by |
17 | | id |
18 | | class |
19 | | xpath |
20 | | index |
21 | | css |
22 |
23 | Scenario: Getting the coordinates for the area
24 | When I retrieve the area element
25 | Then I should see the coordinates are "0,0,82,126"
26 |
27 | Scenario: Getting the shape for the area
28 | When I retrieve the area element
29 | Then I should see the shape is "rect"
30 |
31 | Scenario: Getting the href from the area
32 | When I retrieve the area element
33 | Then I should see the href is "sun.html"
34 |
35 |
--------------------------------------------------------------------------------
/spec/page-object/elements/button_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 | require 'page-object/elements'
3 |
4 | describe PageObject::Elements::Button do
5 | let(:button) { PageObject::Elements::Button }
6 |
7 | describe "interface" do
8 | let(:button_element) { double('button_element') }
9 |
10 | it "should register with type :submit" do
11 | expect(::PageObject::Elements.element_class_for(:input, :submit)).to eql ::PageObject::Elements::Button
12 | end
13 |
14 | it "should register with type :image" do
15 | expect(::PageObject::Elements.element_class_for(:input, :image)).to eql ::PageObject::Elements::Button
16 | end
17 |
18 | it "should register with type :button" do
19 | expect(::PageObject::Elements.element_class_for(:input, :button)).to eql ::PageObject::Elements::Button
20 | end
21 |
22 | it "should register with type :reset" do
23 | expect(::PageObject::Elements.element_class_for(:input, :reset)).to eql ::PageObject::Elements::Button
24 | end
25 | end
26 | end
27 |
--------------------------------------------------------------------------------
/features/step_definitions/check_box_steps.rb:
--------------------------------------------------------------------------------
1 | When /^I select the First check box$/ do
2 | @page.check_cb_id
3 | end
4 |
5 | Then /^the First check box should be selected$/ do
6 | expect(@page.cb_id_checked?).to be true
7 | end
8 |
9 | When /^I unselect the First check box$/ do
10 | @page.uncheck_cb_id
11 | end
12 |
13 | Then /^the First check box should not be selected$/ do
14 | expect(@page.cb_id_checked?).to be false
15 | end
16 |
17 | When /^I search for the check box by "([^\"]*)"$/ do |how|
18 | @how = how
19 | end
20 |
21 | When /^I search for the check box by "([^"]*)" and "([^"]*)"$/ do |param1, param2|
22 | @how = "#{param1}_#{param2}"
23 | end
24 |
25 | Then /^I should be able to check the check box$/ do
26 | @page.send "check_cb_#{@how}".to_sym
27 | end
28 |
29 | When /^I select the first check box while the script is executing$/ do
30 | @page.checkbox_element(:id => 'cb_id').check
31 | end
32 |
33 | Then /^I should see that the checkbox exists$/ do
34 | expect(@page.button_id?).to be true
35 | end
36 |
--------------------------------------------------------------------------------
/features/sample-app/public/jquery.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | jQuery - Sample App
4 |
5 |
6 |
7 |
Nam accumsan. Donec nisi pede, interdum eget, ultrices ac, vulputate vitae, nunc. Nulla lorem. Duis cursus pharetra dolor. Nulla accumsan hendrerit leo. Vivamus commodo. Nullam dignissim adipiscing est. Aliquam vitae orci in risus lobortis luctus. Ut luctus fermentum ligula. Nullam ipsum. Suspendisse sit amet nisi.
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/features/form.feature:
--------------------------------------------------------------------------------
1 | Feature: Form
2 |
3 | Background:
4 | Given I am on the static elements page
5 |
6 | Scenario: Submitting a form
7 | When I locate the form by "id"
8 | Then I should be able to submit the form
9 |
10 | Scenario Outline: Locating a form on the page
11 | When I locate the form by ""
12 | Then I should be able to submit the form
13 |
14 | Scenarios:
15 | | search_by |
16 | | id |
17 | | class |
18 | | xpath |
19 | | index |
20 | | action |
21 | | css |
22 |
23 | Scenario Outline: Locating table using multiple parameters
24 | When I locate the form using "" and ""
25 | Then I should be able to submit the form
26 |
27 | Scenarios:
28 | | param1 | param2 |
29 | | class | index |
30 | | name | index |
31 |
32 | Scenario: Finding a form dynamically
33 | When I locate a form while the script is executing
34 | Then I should see that the form exists
35 | And I should be able to submit the form
36 |
--------------------------------------------------------------------------------
/features/span.feature:
--------------------------------------------------------------------------------
1 | Feature: Span
2 |
3 | Background:
4 | Given I am on the static elements page
5 |
6 | Scenario: Getting the text from a span
7 | When I get the text from the span
8 | Then the text should be "My alert"
9 |
10 | Scenario Outline: Locating spans on the page
11 | When I search for the span by ""
12 | Then the text should be "My alert"
13 |
14 | Scenarios:
15 | | search_by |
16 | | id |
17 | | class |
18 | | xpath |
19 | | index |
20 | | text |
21 | | title |
22 | | css |
23 |
24 | Scenario Outline: Locating span using multiple parameters
25 | When I search for the span by "" and ""
26 | Then the text should be "My alert"
27 |
28 | Scenarios:
29 | | param1 | param2 |
30 | | class | index |
31 |
32 | Scenario: Finding a span dynamically
33 | When I get the text from a span while the script is executing
34 | Then I should see that the span exists
35 | And the text should be "My alert"
36 |
--------------------------------------------------------------------------------
/features/html/frame_2.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Frame 2
5 |
6 |
7 |
8 |
Frame 2
9 |
Vestibulum dignissim mauris id tellus. Nulla volutpat bibendum ante. Nam malesuada, lacus vel ultrices luctus, lorem purus tristique magna, quis pharetra leo ipsum nec neque. Cras ornare tincidunt sem. In hac habitasse platea dictumst. Suspendisse commodo turpis at est. Sed quis tortor. Aenean non massa. Phasellus scelerisque nulla vel lectus. Quisque lorem. Praesent volutpat dignissim risus. Fusce vulputate ligula eu ipsum.
10 |
15 |
16 |
--------------------------------------------------------------------------------
/features/list_item.feature:
--------------------------------------------------------------------------------
1 | Feature: List item
2 |
3 | Background:
4 | Given I am on the static elements page
5 |
6 | Scenario: Getting the text from a list item
7 | When I get the text from the list item
8 | Then the text should be "Item One"
9 |
10 | Scenario Outline: Locating list items on the page
11 | When I search for the list item by ""
12 | Then the text should be "Item One"
13 |
14 | Scenarios:
15 | | search_by |
16 | | id |
17 | | class |
18 | | xpath |
19 | | index |
20 | | text |
21 | | css |
22 |
23 | Scenario Outline: Locating list items using multiple parameters
24 | When I search for the list item by "" and ""
25 | Then the text should be "Item One"
26 |
27 | Scenarios:
28 | | param1 | param2 |
29 | | class | index |
30 |
31 | Scenario: Finding a list item dynamically
32 | When I search for the list item while the script is executing
33 | Then I should see that the list item exists
34 | And the text should be "Item One"
35 |
--------------------------------------------------------------------------------
/features/generic_elements.feature:
--------------------------------------------------------------------------------
1 | Feature: Generic Elements
2 |
3 | Background:
4 | Given I am on the static elements page
5 |
6 | Scenario: Getting the text from the article element
7 | When I get the text from the article
8 | Then the text should be "HTML 5 Article"
9 |
10 | Scenario: Getting the text from the header element
11 | When I get the text from the header
12 | Then the text should be "HTML 5 Header"
13 |
14 | Scenario: Getting the text from the footer element
15 | When I get the text from the footer
16 | Then the text should be "HTML 5 Footer"
17 |
18 | Scenario: Getting the text from the summary element
19 | When I get the text from the summary
20 | Then the text should be "The summary"
21 |
22 | Scenario: Getting the text from the details element
23 | When I get the text from the details
24 | Then the text should be "The summary The details"
25 |
26 | Scenario: getting properties from a svg element
27 | When I get the svg element
28 | Then the svg width should be "100"
29 | And the svg height should be "100"
30 |
--------------------------------------------------------------------------------
/features/canvas.feature:
--------------------------------------------------------------------------------
1 | Feature: Support for the canvas element
2 |
3 | Background:
4 | Given I am on the static elements page
5 |
6 | Scenario: Retrieve a canvas element
7 | When I retrieve the canvas element
8 | Then I should know it exists
9 | And I should know it is visible
10 |
11 | Scenario Outline: Locating a canvas on the page
12 | When I search for the canvas by ""
13 | Then I should know it is visible
14 |
15 | Examples:
16 | | search_by |
17 | | id |
18 | | class |
19 | | xpath |
20 | | index |
21 | | css |
22 |
23 | Scenario: Determining the width and height of the canvas
24 | When I retrieve the canvas element
25 | Then I should see that the canvas width is "200"
26 | And I should see that the canvas height is "100"
27 |
28 | Scenario Outline: Locating canvases using multiple parameters
29 | When I search for the canvas element by "" and ""
30 | Then I should know it is visible
31 |
32 | Scenarios:
33 | | param1 | param2 |
34 | | class | index |
35 |
36 |
--------------------------------------------------------------------------------
/features/paragraph.feature:
--------------------------------------------------------------------------------
1 | Feature: Paragraph
2 |
3 | Background:
4 | Given I am on the static elements page
5 |
6 | Scenario: Getting the text from a paragraph
7 | When I get the text from the paragraph
8 | Then the text should be "Static Elements Page"
9 |
10 | Scenario Outline: Locating paragraphs on the page
11 | When I search for the paragraph by ""
12 | Then the text should be "Static Elements Page"
13 |
14 | Scenarios:
15 | | search_by |
16 | | id |
17 | | class |
18 | | xpath |
19 | | index |
20 | | css |
21 |
22 | Scenario Outline: Locating paragraphs using multiple parameters
23 | When I search for the paragraph by "" and ""
24 | Then the text should be "Static Elements Page"
25 |
26 | Scenarios:
27 | | param1 | param2 |
28 | | class | index |
29 |
30 | Scenario: Finding a paragraph dynamically
31 | When I get the text from a paragraph while the script is executing
32 | Then I should see that the paragraph exists
33 | And the text should be "Static Elements Page"
34 |
--------------------------------------------------------------------------------
/features/step_definitions/text_area_steps.rb:
--------------------------------------------------------------------------------
1 | When /^I type "([^\"]*)" into the text area$/ do |text|
2 | @page.text_area_id = text
3 | end
4 |
5 | Then /^the text area should contain "([^\"]*)"$/ do |expected_text|
6 | expect(@page.text_area_id).to eql expected_text
7 | end
8 |
9 | When /^I search for the text area by "([^\"]*)"$/ do |how|
10 | @how = how
11 | end
12 |
13 | When /^I search for the text area by "([^"]*)" and "([^"]*)"$/ do |param1, param2|
14 | @how = "#{param1}_#{param2}"
15 | end
16 |
17 | Then /^I should be able to type "([^\"]*)" into the area$/ do |value|
18 | @page.send "text_area_#{@how}=".to_sym, value
19 | end
20 |
21 | When /^I find a text area while the script is executing$/ do
22 | @text_area = @page.text_area_element(:id => 'text_area_id')
23 | end
24 |
25 | Then /^I should be able to type "([^"]*)" into the area element$/ do |value|
26 | @text_area.value = value
27 | end
28 |
29 | When /^I clear the text area$/ do
30 | @page.text_area_id_element.clear
31 | end
32 |
33 | Then /^I should see that the text area exists$/ do
34 | expect(@page.text_area_id?).to be true
35 | end
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2011-2012 Jeff Morgan
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining
4 | a copy of this software and associated documentation files (the
5 | "Software"), to deal in the Software without restriction, including
6 | without limitation the rights to use, copy, modify, merge, publish,
7 | distribute, sublicense, and/or sell copies of the Software, and to
8 | permit persons to whom the Software is furnished to do so, subject to
9 | the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be
12 | included in all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/spec/page-object/elements/image_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 | require 'page-object/elements'
3 |
4 | describe PageObject::Elements::Image do
5 | let(:image) { PageObject::Elements::Image }
6 |
7 | describe "interface" do
8 | let(:image_element) { double('image_element') }
9 |
10 | before(:each) do
11 | allow(image_element).to receive(:size).and_return(image_element)
12 | end
13 |
14 | it "should register with tag_name :img" do
15 | expect(::PageObject::Elements.element_class_for(:img)).to eql ::PageObject::Elements::Image
16 | end
17 |
18 | context "for watir" do
19 | it "should know the images width" do
20 | image = PageObject::Elements::Image.new(image_element)
21 | expect(image_element).to receive(:width).and_return(100)
22 | expect(image.width).to eql 100
23 | end
24 |
25 | it "should know the images height" do
26 | image = PageObject::Elements::Image.new(image_element)
27 | expect(image_element).to receive(:height).and_return(120)
28 | expect(image.height).to eql 120
29 | end
30 | end
31 | end
32 | end
33 |
--------------------------------------------------------------------------------
/features/step_definitions/link_steps.rb:
--------------------------------------------------------------------------------
1 | When /^I select the link labeled "([^\"]*)"$/ do |text|
2 | @page.google_search_id
3 | end
4 |
5 | When /^I search for the link by "([^\"]*)"$/ do |how|
6 | @how = how
7 | end
8 |
9 | Then /^I should be able to select the link$/ do
10 | @page.send "google_search_#{@how}".to_sym
11 | end
12 |
13 | When /^I select a link labeled "([^"]*)" and index "([^"]*)"$/ do |label, index|
14 | @page.send "#{label.downcase}#{index}".to_sym
15 | end
16 |
17 | When /^I select a link while the script is executing$/ do
18 | link = @page.link_element(:id => 'link_id')
19 | link.click
20 | end
21 |
22 | Then(/^I should see that the link exists$/) do
23 | expect(@page.link_id?).to be true
24 | end
25 |
26 | When(/^I get the href for the link$/) do
27 | @href = @page.google_search_id_element.href
28 | end
29 |
30 | Then(/^I should know it was "(.*?)"$/) do |href|
31 | expect(@href).to include href
32 | end
33 |
34 | When(/^I get the link using the href success$/) do
35 | @link = @page.link_element(:href => /succ.*html/)
36 | end
37 |
38 | Then(/^I should be able to click the link$/) do
39 | @link.click
40 | end
41 |
--------------------------------------------------------------------------------
/features/populate_page_with.feature:
--------------------------------------------------------------------------------
1 | Feature: Populate Page With
2 | In order to quickly fill out forms on a page
3 | A tester will use the populate_page_with method
4 | To fill in text, select options, check boxes, and select radio buttons
5 |
6 |
7 | Background:
8 | Given I am on the static elements page
9 |
10 | Scenario:
11 | When I populate the page with the data:
12 | | text_field_id | abcDEF |
13 | | text_area_id | abcdefghijklmnop |
14 | | sel_list_id | Test 2 |
15 | | cb_id | check |
16 | | butter_id | check |
17 | | favorite_cheese | muen |
18 | Then the text field should contain "abcDEF"
19 | And the text area should contain "abcdefghijklmnop"
20 | And the selected option should be "Test 2"
21 | And the First check box should be selected
22 | And the "Butter" radio button should be selected
23 | And the "muen" radio button should be selected in the group
24 | When I populate the page with the data:
25 | | sel_list_id | option3 |
26 | Then the selected option should be "Test/Test 3"
27 |
--------------------------------------------------------------------------------
/lib/page-object/elements/ordered_list.rb:
--------------------------------------------------------------------------------
1 |
2 | module PageObject
3 | module Elements
4 | class OrderedList < Element
5 | include Enumerable
6 |
7 | #
8 | # iterator that yields with a PageObject::Elements::ListItem
9 | #
10 | # @return [PageObject::Elements::ListItem]
11 | #
12 | def each(&block)
13 | list_items.each(&block)
14 | end
15 |
16 | #
17 | # Return the PageObject::Elements::ListItem for the index provided. Index
18 | # is zero based.
19 | #
20 | # @return [PageObject::Elements::ListItem]
21 | #
22 | def [](idx)
23 | list_items[idx]
24 | end
25 |
26 | #
27 | # Return the number of items contained in the ordered list
28 | #
29 | def items
30 | list_items.size
31 | end
32 |
33 | #
34 | # Return Array of ListItem objects that are children of the OrderedList
35 | #
36 | def list_items
37 | @list_items ||= children(tag_name: 'li')
38 | end
39 | end
40 |
41 | ::PageObject::Elements.tag_to_class[:ol] = ::PageObject::Elements::OrderedList
42 | end
43 | end
44 |
--------------------------------------------------------------------------------
/lib/page-object/elements/unordered_list.rb:
--------------------------------------------------------------------------------
1 | module PageObject
2 | module Elements
3 | class UnorderedList < Element
4 | include Enumerable
5 |
6 | #
7 | # iterator that yields with a PageObject::Elements::ListItem
8 | #
9 | # @return [PageObject::Elements::ListItem]
10 | #
11 | def each(&block)
12 | list_items.each(&block)
13 | end
14 |
15 | #
16 | # Return the PageObject::Elements::ListItem for the index provided. Index
17 | # is zero based.
18 | #
19 | # @return [PageObject::Elements::ListItem]
20 | #
21 | def [](idx)
22 | list_items[idx]
23 | end
24 |
25 | #
26 | # Return the number of items contained in the unordered list
27 | #
28 | def items
29 | list_items.size
30 | end
31 |
32 | #
33 | # Return Array of ListItem objects that are children of the UnorderedList
34 | #
35 | def list_items
36 | @list_items ||= children(tag_name: 'li')
37 | end
38 | end
39 |
40 | ::PageObject::Elements.tag_to_class[:ul] = ::PageObject::Elements::UnorderedList
41 | end
42 | end
43 |
--------------------------------------------------------------------------------
/features/step_definitions/text_field_steps.rb:
--------------------------------------------------------------------------------
1 | When /^I type "([^\"]*)" into the text field$/ do |text|
2 | @page.text_field_id = text
3 | end
4 |
5 | Then /^the text field should contain "([^\"]*)"$/ do |expected_text|
6 | expect(@page.text_field_id).to eql expected_text
7 | end
8 |
9 | When /^I search for the text field by "([^\"]*)"$/ do |how|
10 | @how = how
11 | end
12 |
13 | When /^I search for the text field by "([^"]*)" and "([^"]*)"$/ do |param1, param2|
14 | @how = "#{param1}_#{param2}"
15 | end
16 |
17 | Then /^I should be able to type "([^\"]*)" into the field$/ do |value|
18 | @page.send "text_field_#{@how}=".to_sym, value
19 | end
20 |
21 | When /^I find a text field while the script is executing$/ do
22 | @text_field = @page.text_field_element(:id => 'text_field_id')
23 | end
24 |
25 | Then /^I should be able to type "([^\"]*)" into the field element$/ do |value|
26 | @text_field.value = value
27 | end
28 |
29 | Then /^I should see that the text field exists$/ do
30 | expect(@page.text_field_id?).to be true
31 | end
32 |
33 | When /^I append "([^\"]*)" to the text field$/ do |text|
34 | @page.text_field_id_element.append text
35 | end
36 |
--------------------------------------------------------------------------------
/features/javascript.feature:
--------------------------------------------------------------------------------
1 | Feature: Handling javascript events
2 |
3 | Background:
4 |
5 | Scenario: Waiting for ajax to complete with jQuery
6 | Given I am on jQuery example page
7 | When I ask to compute "2 + 2"
8 | Then I should be able to wait for the answer "4"
9 |
10 | Scenario: Waiting for ajax to complete with Prototype
11 | Given I am on the Prototype example page
12 | When I ask to compute "2 + 2"
13 | Then I should be able to wait for the answer "4"
14 |
15 | Scenario: Executing javascript in the browser
16 | Given I am on the static elements page
17 | Given I execute the javascript "return 2 + 2;"
18 | Then I should get the answer "4"
19 |
20 | Scenario: Executing javascript in the browser with value argument
21 | Given I am on the static elements page
22 | Given I execute the javascript "return 2 + Number(arguments[0]);" with an argument of "2"
23 | Then I should get the answer "4"
24 |
25 | Scenario: Executing javascript in the browser with element argument
26 | Given I am on the static elements page
27 | Given I execute the javascript "arguments[0].value = 'abcDEF';" with a text field argument
28 | Then the text field should contain "abcDEF"
--------------------------------------------------------------------------------
/spec/page-object/elements/heading_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 | require 'page-object/elements'
3 |
4 | describe PageObject::Elements::Heading do
5 | let(:heading) { PageObject::Elements::Heading }
6 |
7 | describe "interface" do
8 | it "should register with tag :h1" do
9 | expect(::PageObject::Elements.element_class_for(:h1)).to eql ::PageObject::Elements::Heading
10 | end
11 |
12 | it "should register with tag :h2" do
13 | expect(::PageObject::Elements.element_class_for(:h2)).to eql ::PageObject::Elements::Heading
14 | end
15 |
16 | it "should register with tag :h3" do
17 | expect(::PageObject::Elements.element_class_for(:h3)).to eql ::PageObject::Elements::Heading
18 | end
19 |
20 | it "should register with tag :h4" do
21 | expect(::PageObject::Elements.element_class_for(:h4)).to eql ::PageObject::Elements::Heading
22 | end
23 |
24 | it "should register with tag :h5" do
25 | expect(::PageObject::Elements.element_class_for(:h5)).to eql ::PageObject::Elements::Heading
26 | end
27 |
28 | it "should register with tag :h6" do
29 | expect(::PageObject::Elements.element_class_for(:h6)).to eql ::PageObject::Elements::Heading
30 | end
31 | end
32 | end
33 |
--------------------------------------------------------------------------------
/features/html/frame_1.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Frame 1
5 |
6 |
7 |
8 |
Frame 1
9 |
Nam accumsan. Donec nisi pede, interdum eget, ultrices ac, vulputate vitae, nunc. Nulla lorem. Duis cursus pharetra dolor. Nulla accumsan hendrerit leo. Vivamus commodo. Nullam dignissim adipiscing est. Aliquam vitae orci in risus lobortis luctus. Ut luctus fermentum ligula. Nullam ipsum. Suspendisse sit amet nisi.
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/features/hidden_field.feature:
--------------------------------------------------------------------------------
1 | Feature: Hidden Fields
2 |
3 | Background:
4 | Given I am on the static elements page
5 |
6 | Scenario: Setting and getting a value from a hidden field
7 | When I retrieve the hidden field element
8 | Then I should see the hidden field contains "12345"
9 |
10 | Scenario Outline: Locating hidden fields on the Page
11 | When I search for the hidden field by ""
12 | Then the hidden field element should contain "12345"
13 |
14 | Scenarios:
15 | | search_by |
16 | | id |
17 | | class |
18 | | name |
19 | | xpath |
20 | | index |
21 | | text |
22 | | value |
23 | | css |
24 |
25 | Scenario Outline: Locating a hidden field using multiple parameters
26 | When I search for the hidden field by "" and ""
27 | Then the hidden field element should contain "12345"
28 |
29 | Scenarios:
30 | | param1 | param2 |
31 | | class | index |
32 | | name | index |
33 |
34 | Scenario: Finding a hidden field dynamically
35 | When I find a hidden field while the script is executing
36 | Then I should see that the hidden field exists
37 | And the hidden field element should contain "12345"
38 |
--------------------------------------------------------------------------------
/page-object.gemspec:
--------------------------------------------------------------------------------
1 | # -*- encoding: utf-8 -*-
2 | $:.push File.expand_path("../lib", __FILE__)
3 | require "page-object/version"
4 |
5 |
6 | Gem::Specification.new do |s|
7 | s.name = "page-object"
8 | s.version = PageObject::VERSION
9 | s.platform = Gem::Platform::RUBY
10 | s.authors = ["Jeff Morgan", 'Alexis Andersen']
11 | s.email = ["jeff.morgan@leandog.com", 'alexis.t.andersen@gmail.com']
12 | s.license = 'MIT'
13 | s.homepage = "http://github.com/cheezy/page-object"
14 | s.summary = %q{Page Object DSL for browser testing}
15 | s.description = %q{Page Object DSL that works with both Watir and Selenium}
16 |
17 | s.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(pkg|spec|features|coverage)/}) }
18 | s.require_paths = ["lib"]
19 |
20 | s.add_dependency 'watir', '>= 6.10.3'
21 | s.add_dependency 'page_navigation', '>= 0.10'
22 |
23 | s.add_development_dependency 'rspec', '~> 3.0'
24 | s.add_development_dependency 'cucumber', '~> 2.0'
25 | s.add_development_dependency 'yard', '>= 0.7.2'
26 | s.add_development_dependency 'rack', '~> 1.0'
27 | s.add_development_dependency 'coveralls', '~> 0.8.1'
28 | s.add_development_dependency 'net-http-persistent'
29 | s.add_development_dependency 'webdrivers'
30 |
31 | end
32 |
--------------------------------------------------------------------------------
/lib/page-object/elements/select_list.rb:
--------------------------------------------------------------------------------
1 | module PageObject
2 | module Elements
3 | class SelectList < Element
4 |
5 | #
6 | # Return the PageObject::Elements::Option for the index provided. Index
7 | # is zero based.
8 | #
9 | # @return [PageObject::Elements::Option]
10 | #
11 | def [](idx)
12 | options[idx]
13 | end
14 |
15 | #
16 | # Return an array of Options contained in the select list.
17 | #
18 | # @return [array of PageObject::Elements::Option]
19 | #
20 | def options
21 | element.options.map { |e| PageObject::Elements::Option.new(e) }
22 | end
23 |
24 | #
25 | # @return [Array] An array of strings representing the text of the currently selected options.
26 | #
27 | def selected_options
28 | element.selected_options.map(&:text).compact
29 | end
30 |
31 | #
32 | # @return [Array] An array of strings representing the value of the currently selected options.
33 | #
34 | def selected_values
35 | element.selected_options.map(&:value).compact
36 | end
37 |
38 | end
39 |
40 | ::PageObject::Elements.tag_to_class[:select] = ::PageObject::Elements::SelectList
41 | end
42 | end
43 |
--------------------------------------------------------------------------------
/spec/page-object/elements/unordered_list_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 | require 'page-object/elements'
3 |
4 | describe PageObject::Elements::UnorderedList do
5 | let(:ul) { PageObject::Elements::UnorderedList.new(ul_element) }
6 |
7 | describe "interface" do
8 | let(:ul_element) { double('ul_element').as_null_object }
9 | let(:li_element) { double('li_element').as_null_object }
10 |
11 | it "should register with tag_name :ul" do
12 | expect(::PageObject::Elements.element_class_for(:ul)).to eql ::PageObject::Elements::UnorderedList
13 | end
14 |
15 | context "for watir" do
16 | before(:each) do
17 | allow(ul_element).to receive(:children).and_return([li_element, li_element])
18 | allow(li_element).to receive(:tag_name).and_return(:li)
19 | end
20 |
21 | it "should return a list item when indexed" do
22 | expect(ul[1]).to be_instance_of PageObject::Elements::ListItem
23 | end
24 |
25 | it "should know how many items it contains" do
26 | expect(ul.items).to eql 2
27 | end
28 |
29 | it "should know how to iterate over the items" do
30 | count = 0
31 | ul.each { |item| count += 1 }
32 | expect(count).to eql 2
33 | end
34 | end
35 |
36 | end
37 | end
38 |
--------------------------------------------------------------------------------
/features/step_definitions/modal_dialog_steps.rb:
--------------------------------------------------------------------------------
1 | class ModalPage
2 | include PageObject
3 |
4 | button(:launch_modal, :id => 'launch_modal_button')
5 | end
6 |
7 | class ModalDialog
8 | include PageObject
9 |
10 | button(:close_window, :id => 'close_window')
11 | button(:close_window_with_delay, :id => 'delayed_close')
12 | button(:launch_another_modal, :id => 'launch_modal_button')
13 | end
14 |
15 | class AnotherModalDialog
16 | include PageObject
17 |
18 | button(:close_window, :id => 'close_window2')
19 | button(:close_window_with_delay, :id => 'delayed_close2')
20 | end
21 |
22 |
23 | Given /^I am on the modal page$/ do
24 | ModalPage.new(@browser).navigate_to(UrlHelper.modal)
25 | end
26 |
27 | When /^I open a modal dialog$/ do
28 | page = ModalPage.new(@browser)
29 | page.modal_dialog do
30 | page.launch_modal
31 | end
32 | end
33 |
34 | Then /^I should be able to close the modal$/ do
35 | dialog = ModalDialog.new(@browser)
36 | dialog.attach_to_window(:title => 'Modal 1') do
37 | dialog.close_window
38 | end
39 | end
40 |
41 | When /^I open another modal dialog from that one$/ do
42 | dialog = ModalDialog.new(@browser)
43 | dialog.attach_to_window(:title => 'Modal 1')
44 | dialog.modal_dialog
45 | dialog.launch_another_modal
46 | end
47 |
--------------------------------------------------------------------------------
/spec/page-object/elements/table_row_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 | require 'page-object/elements'
3 |
4 | describe PageObject::Elements::TableRow do
5 | let(:table_cell) { double('table_cell') }
6 | let(:table_row_driver) { double('table_row_driver') }
7 | let(:table_row) { PageObject::Elements::TableRow.new(table_row_driver) }
8 |
9 | describe "interface" do
10 |
11 | it "should register with tag_name :tr" do
12 | expect(::PageObject::Elements.element_class_for(:tr)).to eql ::PageObject::Elements::TableRow
13 | end
14 |
15 | context "for watir" do
16 | before(:each) do
17 | allow(table_row_driver).to receive(:find_elements).and_return(table_row_driver)
18 | allow(table_row_driver).to receive(:cells).and_return(Array.new(2, Watir::TableCell))
19 | end
20 |
21 | it "should return a table cell when indexed" do
22 | expect(table_row[1]).to be_instance_of PageObject::Elements::TableCell
23 | end
24 |
25 | it "should return the number of columns" do
26 | expect(table_row.columns).to eql 2
27 | end
28 |
29 | it "should iterate over the table columns" do
30 | count = 0
31 | table_row.each { count += 1 }
32 | expect(count).to eql 2
33 | end
34 | end
35 | end
36 | end
37 |
--------------------------------------------------------------------------------
/features/step_definitions/button_steps.rb:
--------------------------------------------------------------------------------
1 | When /^I click the button$/ do
2 | @page.button_id
3 | end
4 |
5 | When /^I click the button with type image$/ do
6 | @page.button_image_id
7 | end
8 |
9 | When /^I click the image button using src$/ do
10 | @page.button_image_src
11 | end
12 |
13 | When /^I click the image button using alt$/ do
14 | @page.button_image_alt
15 | end
16 |
17 | When /^I search for the button by "([^\"]*)"$/ do |how|
18 | @how = how
19 | end
20 |
21 | When /^I search for the button by "([^"]*)" and "([^"]*)"$/ do |param1, param2|
22 | @how = "#{param1}_#{param2}"
23 | end
24 |
25 | Then /^I should be able to click the button$/ do
26 | @page.send "button_#{@how}"
27 | end
28 |
29 | Then /^I should be able to click the real button$/ do
30 | @page.send "btn_#{@how}"
31 | end
32 |
33 | When /^I find a button while the script is executing$/ do
34 | @button = @page.button_element(:id => 'button_id')
35 | end
36 |
37 | Then /^I should be able to click the button element$/ do
38 | @button.click
39 | end
40 |
41 | Then /^I should see that the button exists$/ do
42 | expect(@page.button_id?).to be true
43 | end
44 |
45 |
46 | When(/^I get the text for a button that is a "([^"]*)"$/) do |tagname|
47 | @text = @page.button_element(:id => "#{tagname}_button").text
48 | end
--------------------------------------------------------------------------------
/features/step_definitions/radio_button_group_steps.rb:
--------------------------------------------------------------------------------
1 | When /^no radio buttons have been selected$/ do
2 | # nothing to do here
3 | end
4 |
5 | Then /^no radio buttons should be selected in the group$/ do
6 | expect(@page.favorite_cheese_selected?).to be false
7 | end
8 |
9 | When /^I select the "([^\"]*)" radio button in the group$/ do |how|
10 | @page.select_favorite_cheese("#{how}")
11 | end
12 |
13 | Then /^the "([^\"]*)" radio button should be selected in the group$/ do |how|
14 | expect(@page.favorite_cheese_selected?).to eql "#{how}"
15 | end
16 |
17 | Then /^the "([^\"]*)" radio button should not be selected$/ do |how|
18 | expect(@page.favorite_cheese_selected?).not_to eql "#{how}"
19 | end
20 |
21 | Then /^I should see that the radio button group exists$/ do
22 | expect(@page.favorite_cheese?).to be true
23 | end
24 |
25 | When /^I ask for the elements of a radio button group$/ do
26 | @elems = @page.favorite_cheese_elements
27 | end
28 |
29 | Then /^I should have an array with elements for each radio button$/ do
30 | expect(@elems.length).to eql 3
31 | end
32 |
33 | And /^the radio button element values should be "([^\"]*)", "([^\"]*)", "([^\"]*)"$/ do |val1, val2, val3|
34 | elem_arr = @elems.collect { |elem| elem.value }
35 | expect(elem_arr).to eql [val1, val2, val3]
36 | end
--------------------------------------------------------------------------------
/features/step_definitions/image_steps.rb:
--------------------------------------------------------------------------------
1 | When /^I get the image element$/ do
2 | @element = @page.image_id_element
3 | end
4 |
5 | When /^I get the image element load status$/ do
6 | @status = @page.image_id_loaded?
7 | end
8 |
9 | When /^I get the broken image element load status$/ do
10 | @status = @page.image_broken_loaded?
11 | end
12 |
13 | Then /^the image should be "([^\"]*)" pixels wide$/ do |width|
14 | expect(@element.width).to eql width.to_i
15 | end
16 |
17 | Then /^the image should be "([^\"]*)" pixels tall$/ do |height|
18 | expect(@element.height).to eql height.to_i
19 | end
20 |
21 | When /^I get the image element by "([^\"]*)"$/ do |how|
22 | @element = @page.send "image_#{how}_element"
23 | end
24 |
25 | When /^I get the image element by "([^"]*)" and "([^"]*)"$/ do |param1, param2|
26 | @element = @page.send "image_#{param1}_#{param2}_element"
27 | end
28 |
29 | When /^I get the image element while the script is executing$/ do
30 | @element = @page.image_element(:id => 'image_id')
31 | end
32 |
33 | Then /^I should see that the image exists$/ do
34 | expect(@page.image_id?).to be true
35 | end
36 |
37 | Then /^I should see that the image loaded$/ do
38 | expect(@status).to be true
39 | end
40 |
41 | Then /^I should see that the image is not loaded$/ do
42 | expect(@status).to be false
43 | end
44 |
--------------------------------------------------------------------------------
/features/step_definitions/video_steps.rb:
--------------------------------------------------------------------------------
1 |
2 | When /^I retrieve the video element$/ do
3 | @element = @avpage.video_id_element
4 | end
5 |
6 | When /^I search for the video element by "([^\"]*)"$/ do |how|
7 | @element = @avpage.send "video_#{how}_element"
8 | end
9 |
10 | When /^I search for the video element by "([^\"]*)" and "([^\"]*)"$/ do |param1, param2|
11 | @element = @avpage.send "video_#{param1}_#{param2}_element"
12 | end
13 |
14 | Then /^I should know the video is not autoplay$/ do
15 | expect(@element).not_to be_autoplay
16 | end
17 |
18 | Then /^I should know that the video is paused$/ do
19 | expect(@element).to be_paused
20 | end
21 |
22 | Then /^I should know that its height is (\d+) pixels$/ do |height|
23 | expect(@element.height).to eql height.to_i
24 | end
25 |
26 | Then /^I should knot what its width is (\d+) pixels$/ do |width|
27 | expect(@element.width).to eql width.to_i
28 | end
29 |
30 | Then /^I should know that it has not ended$/ do
31 | expect(@element).not_to be_ended
32 | end
33 |
34 | Then /^I should know that it is not seeking$/ do
35 | expect(@element).not_to be_seeking
36 | end
37 |
38 | Then /^I should know that it is not in a loop$/ do
39 | expect(@element).not_to be_loop
40 | end
41 |
42 | Then /^I should know that it is muted$/ do
43 | expect(@element).not_to be_muted
44 | end
45 |
--------------------------------------------------------------------------------
/features/table_cell.feature:
--------------------------------------------------------------------------------
1 | Feature: Table Cell
2 |
3 |
4 | Background:
5 | Given I am on the static elements page
6 |
7 | Scenario: Retrieving the text from a table cell
8 | When I retrieve the data from the table cell
9 | Then the cell data should be 'Data4'
10 |
11 | Scenario Outline: Locating table cells on the Page
12 | When I search for the table cell by ""
13 | Then the cell data should be 'Data4'
14 |
15 | Scenarios:
16 | | search_by |
17 | | id |
18 | | class |
19 | | xpath |
20 | | text |
21 | | css |
22 |
23 | Scenario Outline: Locating table cells on the Page with watir
24 | When I search for the table cell by ""
25 | Then the cell data should be 'Data4'
26 |
27 | Scenarios:
28 | | search_by |
29 | | index |
30 |
31 | Scenario Outline: Locating table cell using multiple parameters
32 | When I retrieve a table cell element by "" and ""
33 | Then the cell data should be 'Data4'
34 |
35 | Scenarios:
36 | | param1 | param2 |
37 | | class | index |
38 |
39 | Scenario: Finding a table cell dynamically
40 | When I retrieve a table cell element while the script is executing
41 | Then I should see that the cell exists
42 | And the cell data should be 'Data4'
43 |
--------------------------------------------------------------------------------
/features/div.feature:
--------------------------------------------------------------------------------
1 | Feature: Div
2 | In order to interact with divs
3 | Testers will need access and interrogation ability
4 |
5 |
6 | Background:
7 | Given I am on the static elements page
8 |
9 | Scenario: Getting the text from a div
10 | When I get the text from the div
11 | Then the text should be "page-object rocks!"
12 |
13 | Scenario: Getting the div element
14 | When I retrieve the div element
15 | Then I should know it exists
16 | And I should know it is visible
17 |
18 | Scenario Outline: Locating divs on the page
19 | When I search for the div by ""
20 | Then the text should be "page-object rocks!"
21 |
22 | Scenarios:
23 | | search_by |
24 | | id |
25 | | class |
26 | | xpath |
27 | | index |
28 | | text |
29 | | title |
30 | | css |
31 |
32 | Scenario Outline: Locating divs using multiple parameters
33 | When I search for the div by "" and ""
34 | Then the text should be "page-object rocks!"
35 |
36 | Scenarios:
37 | | param1 | param2 |
38 | | class | index |
39 |
40 | Scenario: Finding a div dynamically
41 | When I get the text from a div while the script is executing
42 | Then I should see that the div exists
43 | And the text should be "page-object rocks!"
44 |
--------------------------------------------------------------------------------
/features/support/url_helper.rb:
--------------------------------------------------------------------------------
1 | module UrlHelper
2 | class << self
3 | def html
4 | File.expand_path("#{File.dirname(__FILE__)}/../html")
5 | end
6 |
7 | def files
8 | target = ENV['BROWSER']
9 | return "file://#{html}" if target.nil? or target.include? 'local'
10 | 'http://ec2-107-22-131-88.compute-1.amazonaws.com'
11 | end
12 |
13 | def static_elements
14 | "#{files}/static_elements.html"
15 | end
16 |
17 | def frame_elements
18 | "#{files}/frames.html"
19 | end
20 |
21 | def iframe_elements
22 | "#{files}/iframes.html"
23 | end
24 |
25 | def nested_frame_elements
26 | "#{files}/nested_frames.html"
27 | end
28 |
29 | def nested_elements
30 | "#{files}/nested_elements.html"
31 | end
32 |
33 | def modal
34 | "#{files}/modal.html"
35 | end
36 |
37 | def async
38 | "#{files}/async.html"
39 | end
40 |
41 | def multi
42 | "#{files}/multi_elements.html"
43 | end
44 |
45 | def indexed
46 | "#{files}/indexed_property.html"
47 | end
48 |
49 | def hover
50 | "#{files}/hover.html"
51 | end
52 |
53 | def double_click
54 | "#{files}/double_click.html"
55 | end
56 |
57 | def widgets
58 | "#{files}/widgets.html"
59 | end
60 | end
61 | end
62 |
--------------------------------------------------------------------------------
/spec/page-object/accessors_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | class GenericPage
4 | include PageObject
5 |
6 | wait_for_expected_title 'expected title'
7 | end
8 |
9 | describe 'accessors' do
10 | let(:browser) { mock_watir_browser }
11 | let(:page) { GenericPage.new browser }
12 |
13 | context '#wait_for_expected_title' do
14 | before(:each) do
15 | allow(browser).to receive(:wait_until).and_yield
16 | end
17 |
18 | it 'true if already there' do
19 | allow(browser).to receive(:title).and_return 'expected title'
20 | expect(page.wait_for_expected_title?).to be_truthy
21 | end
22 |
23 | it 'does not wait if it already is there' do
24 | allow(browser).to receive(:title).and_return 'expected title'
25 | expect(browser).to_not receive(:wait_until)
26 |
27 | expect(page.wait_for_expected_title?).to be_truthy
28 | end
29 |
30 | it 'errors when it does not match' do
31 | allow(browser).to receive(:title).and_return 'wrong title'
32 | expect { page.wait_for_expected_title? }.to raise_error "Expected title 'expected title' instead of 'wrong title'"
33 | end
34 |
35 | it 'picks up when the title changes' do
36 | allow(browser).to receive(:title).and_return 'wrong title', 'expected title'
37 | expect(page.wait_for_expected_title?).to be_truthy
38 | end
39 | end
40 | end
41 |
--------------------------------------------------------------------------------
/spec/spec_helper.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | $LOAD_PATH.unshift(File.dirname(__FILE__))
3 | $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
4 |
5 | require 'simplecov'
6 | require 'coveralls'
7 | SimpleCov.start { add_filter 'spec/' }
8 |
9 | require 'rspec'
10 | require 'watir'
11 | require 'webdrivers'
12 | require 'selenium-webdriver'
13 |
14 | require 'page-object'
15 |
16 | def mock_watir_browser
17 | watir_browser = double('watir')
18 | allow(watir_browser).to receive(:is_a?).with(anything).and_return(false)
19 | allow(watir_browser).to receive(:is_a?).with(Watir::Browser).and_return(true)
20 | allow(watir_browser).to receive(:exists?).and_return(true)
21 | allow(watir_browser).to receive(:to_subtype).and_return(watir_browser)
22 | watir_browser
23 | end
24 |
25 |
26 | def mock_adapter(browser, page_object)
27 | adapter = double('adapter')
28 | allow(adapter).to receive(:is_for?).with(anything()).and_return false
29 | allow(adapter).to receive(:is_for?).with(browser).and_return true
30 | allow(adapter).to receive(:create_page_object).and_return page_object
31 | allow(adapter).to receive(:root_element_for).and_return browser
32 | allow(adapter).to receive(:browser_for).and_return browser
33 | adapter
34 | end
35 |
36 | def mock_adapters(adapters)
37 | allow(PageObject::Platforms).to receive(:get).and_return adapters
38 | end
39 |
--------------------------------------------------------------------------------
/features/html/async.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Async Page
4 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/features/radio_button_group.feature:
--------------------------------------------------------------------------------
1 | Feature: Radio Button Groups
2 | In order to interact with radio button groups
3 | Testers will need access and interrogation ability
4 |
5 |
6 | Background:
7 | Given I am on the static elements page
8 |
9 | Scenario: Confirm existence of a radio button group
10 | Then I should see that the radio button group exists
11 |
12 | Scenario: No radio buttons in the group have been selected
13 | When no radio buttons have been selected
14 | Then no radio buttons should be selected in the group
15 |
16 | Scenario: Selecting grouped radio buttons by value
17 | When I select the "ched" radio button in the group
18 | Then the "ched" radio button should be selected in the group
19 | And the "emmen" radio button should not be selected
20 | And the "muen" radio button should not be selected
21 | When I select the "muen" radio button in the group
22 | Then the "ched" radio button should not be selected
23 | And the "emmen" radio button should not be selected
24 | And the "muen" radio button should be selected in the group
25 |
26 | Scenario: Getting an array of elements for each radio button in the group
27 | When I ask for the elements of a radio button group
28 | Then I should have an array with elements for each radio button
29 | And the radio button element values should be "ched", "emmen", "muen"
30 |
--------------------------------------------------------------------------------
/features/table_row.feature:
--------------------------------------------------------------------------------
1 | Feature: Table Row
2 |
3 | Background:
4 | Given I am on the static elements page
5 |
6 | Scenario: Retrieving the text from a table row
7 | When I retrieve the data from the table row
8 | Then the row data should be 'Data1 Data2'
9 |
10 | Scenario Outline: Locating table rows on the Page
11 | When I search for the table row by ""
12 | Then the row data should be 'Data1 Data2'
13 |
14 | Scenarios:
15 | | search_by |
16 | | id |
17 | | class |
18 | | xpath |
19 | | css |
20 |
21 |
22 | Scenario: Locating table rows on the Page by text
23 | When I search for the table row by "text"
24 | Then the row data should be 'Data1 Data2'
25 |
26 | Scenario Outline: Locating table rows on the Page with watir
27 | When I search for the table row by ""
28 | Then the row data should be 'Data1 Data2'
29 |
30 | Scenarios:
31 | | search_by |
32 | | index |
33 |
34 | Scenario: Locating table row using multiple parameters
35 | When I retrieve a table row element by "class" and "index"
36 | Then the row data should be 'Data1 Data2'
37 |
38 | Scenario: Finding a table row dynamically
39 | When I retrieve a table row element while the script is executing
40 | Then I should see that the row exists
41 | And the row data should be 'Data1 Data2'
42 |
--------------------------------------------------------------------------------
/features/step_definitions/gxt_table_steps.rb:
--------------------------------------------------------------------------------
1 |
2 | def class_exists?(class_name)
3 | begin
4 | klass = Module.const_get(class_name)
5 | return klass.is_a?(Class)
6 | rescue NameError
7 | return false
8 | end
9 | end
10 |
11 | Given /^I am on the Gxt Examples page$/ do
12 | visit GxtSamplePageObject
13 | end
14 |
15 | When /^I have defined a GxtTable class extending Table$/ do
16 | class GxtTable < PageObject::Elements::Table
17 |
18 | def self.accessor_methods(accessor, name)
19 | accessor.send :define_method, "#{name}_rows" do
20 | self.send("#{name}_element").rows
21 | end
22 | end
23 |
24 | protected
25 |
26 | def strategy
27 | :descendants
28 | end
29 | end
30 | end
31 |
32 | When /^I define a page-object using that widget$/ do
33 | class GxtSamplePageObject
34 | include PageObject
35 |
36 | page_url UrlHelper.widgets
37 |
38 | gxt_table(:gxt_table, :class => "x-grid3")
39 | end unless class_exists? 'GxtSamplePageObject'
40 | end
41 |
42 | When /^I have registered the GxtTable with PageObject$/ do
43 | PageObject.register_widget :gxt_table, GxtTable, 'div'
44 | end
45 |
46 | When /^I retrieve a GxtTable widget$/ do
47 | @element = on(GxtSamplePageObject).gxt_table_element
48 | end
49 |
50 |
51 | When /^the GxtTable should have "(\d+)" rows$/ do |rows|
52 | expect(on(GxtSamplePageObject).gxt_table_rows).to eql rows.to_i
53 | end
54 |
55 |
--------------------------------------------------------------------------------
/features/label.feature:
--------------------------------------------------------------------------------
1 | Feature: Handling labels with page object
2 |
3 | In order to interact with labels,
4 | Testers will need to access the element
5 | and the ability to interrogate
6 |
7 | Background:
8 | Given I am on the static elements page
9 |
10 | Scenario: Getting the text from a label
11 | When I get the text from the label
12 | Then the text should be "page-object is the best!"
13 |
14 | Scenario: Getting the label element
15 | When I retrieve the label element
16 | Then I should know it exists
17 | And I should know it is visible
18 |
19 | Scenario Outline: Locating labels on the page
20 | When I search for the label by ""
21 | Then the text should be "page-object is the best!"
22 |
23 | Scenarios:
24 | | search_by |
25 | | id |
26 | | class |
27 | | xpath |
28 | | index |
29 | | text |
30 | | css |
31 |
32 | Scenario Outline: Locating labels using multiple parameters
33 | When I search for the label by "" and ""
34 | Then the text should be "page-object is the best!"
35 |
36 | Scenarios:
37 | | param1 | param2 |
38 | | class | index |
39 |
40 | Scenario: Finding a label dynamically
41 | When I get the text from a label while the script is executing
42 | Then I should see that the label exists
43 | And the text should be "page-object is the best!"
44 |
45 |
--------------------------------------------------------------------------------
/spec/page-object/elements/table_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 | require 'page-object/elements'
3 |
4 | describe PageObject::Elements::Table do
5 | describe "interface" do
6 | let(:table_element) { double('table_element') }
7 |
8 | before(:each) do
9 | allow(table_element).to receive(:rows).and_return(Array.new(2, Watir::TableRow))
10 | end
11 |
12 | it "should register with tag_name :table" do
13 | expect(::PageObject::Elements.element_class_for(:table)).to eql ::PageObject::Elements::Table
14 | end
15 |
16 | context "for watir" do
17 | let(:watir_table) { PageObject::Elements::Table.new(table_element) }
18 |
19 | it "should return a table row when indexed" do
20 | expect(watir_table[1]).to be_instance_of PageObject::Elements::TableRow
21 | end
22 |
23 | it "should return the first row" do
24 | expect(watir_table.first_row).to be_instance_of PageObject::Elements::TableRow
25 | end
26 |
27 | it "shoudl return the last row" do
28 | expect(watir_table.last_row).to be_instance_of PageObject::Elements::TableRow
29 | end
30 |
31 | it "should return the number of rows" do
32 | expect(watir_table.rows).to eql 2
33 | end
34 |
35 | it "should iterate over the table rows" do
36 | count = 0
37 | watir_table.each { |e| count += 1 }
38 | expect(count).to eql 2
39 | end
40 | end
41 |
42 | end
43 | end
44 |
--------------------------------------------------------------------------------
/features/text_area.feature:
--------------------------------------------------------------------------------
1 | Feature: Text Area
2 |
3 |
4 | Background:
5 | Given I am on the static elements page
6 |
7 | Scenario: Setting and getting a value from a text area
8 | When I type "abcdefghijklmnop" into the text area
9 | Then the text area should contain "abcdefghijklmnop"
10 |
11 | Scenario Outline: Locating text area on the Page
12 | When I search for the text area by ""
13 | Then I should be able to type "I found it" into the area
14 |
15 | Scenarios:
16 | | search_by |
17 | | id |
18 | | class |
19 | | name |
20 | | xpath |
21 | | index |
22 | | label |
23 | | css |
24 |
25 | Scenario Outline: Locating a text area using multiple parameters
26 | When I search for the text area by "" and ""
27 | Then I should be able to type "I found it" into the area
28 |
29 | Scenarios:
30 | | param1 | param2 |
31 | | class | index |
32 | | name | index |
33 |
34 | Scenario: Finding a text area dynamically
35 | When I find a text area while the script is executing
36 | Then I should see that the text area exists
37 | And I should be able to type "I found it" into the area element
38 |
39 | Scenario: Clearing the text area
40 | When I type "abcdefghijklmnop" into the text area
41 | Then the text area should contain "abcdefghijklmnop"
42 | When I clear the text area
43 | Then the text area should contain ""
44 |
--------------------------------------------------------------------------------
/lib/page-object/elements/table_row.rb:
--------------------------------------------------------------------------------
1 | require 'watir/elements/html_elements'
2 |
3 | module PageObject
4 | module Elements
5 | class TableRow < Element
6 | include Enumerable
7 |
8 | #
9 | # iterator that yields with a PageObject::Elements::TableCell
10 | #
11 | def each(&block)
12 | cell_items.each(&block)
13 | end
14 |
15 | #
16 | # Return the PageObject::Elements::TableCell for the index provided. Index
17 | # is zero based. If the index provided is a String then it
18 | # will be matched with the text from the columns in the first row.
19 | # The text can be a substring of the full column text.
20 | #
21 | def [](what)
22 | idx = find_index(what)
23 | idx && cell_items[idx]
24 | end
25 |
26 | #
27 | # Returns the number of columns in the table.
28 | #
29 | def columns
30 | cell_items.size
31 | end
32 |
33 | protected
34 |
35 | def cell_items
36 | @cell_items ||= element.cells.map do |obj|
37 | ::PageObject::Elements::TableCell.new(obj)
38 | end
39 | end
40 |
41 | def find_index(what)
42 | return what if what.is_a? Integer
43 |
44 | parent(tag_name: 'table').headers.find_index do |header|
45 | header.text.include? what
46 | end
47 | end
48 | end
49 |
50 | ::PageObject::Elements.tag_to_class[:tr] = ::PageObject::Elements::TableRow
51 | end
52 | end
53 |
--------------------------------------------------------------------------------
/spec/page-object/elements/ordered_list_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 | require 'page-object/elements'
3 |
4 | describe PageObject::Elements::OrderedList do
5 | let(:ol) { PageObject::Elements::OrderedList }
6 |
7 | describe "interface" do
8 | let(:ol_element) { double('ol_element').as_null_object }
9 | let(:li_element) { double('li_element') }
10 |
11 | it "should register as tag_name :ol" do
12 | expect(::PageObject::Elements.element_class_for(:ol)).to eql ::PageObject::Elements::OrderedList
13 | end
14 |
15 | context "for watir" do
16 | before(:each) do
17 | allow(ol_element).to receive(:tag_name).and_return(:ol)
18 | end
19 |
20 | it "should return a list item when indexed" do
21 | ol = PageObject::Elements::OrderedList.new(ol_element)
22 | expect(ol_element).to receive(:children).
23 | and_return([ol_element, ol_element])
24 | ol[1]
25 | end
26 |
27 | it "should know how many list items it contains" do
28 | ol = PageObject::Elements::OrderedList.new(ol_element)
29 | expect(ol_element).to receive(:children).and_return([ol_element])
30 | expect(ol.items).to eql 1
31 | end
32 |
33 | it "should iterate over the list items" do
34 | ol = PageObject::Elements::OrderedList.new(ol_element)
35 | allow(ol).to receive(:list_items).and_return(Array.new(5, ol_element))
36 | expect(ol.items).to eql 5
37 | end
38 | end
39 | end
40 | end
41 |
--------------------------------------------------------------------------------
/lib/page-object/indexed_properties.rb:
--------------------------------------------------------------------------------
1 | module PageObject
2 | module IndexedProperties
3 | class TableOfElements
4 | include PageObject
5 |
6 | def initialize (browser, identifier_list)
7 | initialize_browser(browser)
8 | @identifier_list = identifier_list
9 | @indexed_property_class = Class.new {
10 | include PageObject
11 | extend Accessors
12 |
13 | def initialize (browser, index, identifier_list)
14 | initialize_browser(browser)
15 |
16 | identifier_list.each do |identifier|
17 | type = identifier[0]
18 | name = identifier[1]
19 | how_and_what = identifier[2].clone # Cannot modify the original...
20 | how_and_what.each do |key, value|
21 | next if value.is_a? Regexp # Cannot format Regexp with %
22 | if key == :index
23 | how_and_what[key] = (value % index).to_i
24 | elsif key == :frame
25 | how_and_what[key] = value #passthrough frame without modification
26 | else
27 | how_and_what[key] = value % index
28 | end
29 | end
30 | self.class.send type, name, how_and_what unless Class.instance_methods.include? name
31 | end
32 | end
33 | }
34 | end
35 |
36 | def [] (index)
37 | @indexed_property_class.new(@browser, index, @identifier_list)
38 | end
39 | end
40 | end
41 | end
42 |
--------------------------------------------------------------------------------
/features/check_box.feature:
--------------------------------------------------------------------------------
1 | Feature: Check Box
2 | In order to interact with check boxes
3 | Testers will need access and interrogation ability
4 |
5 |
6 | Background:
7 | Given I am on the static elements page
8 |
9 | Scenario: Selecting a check box
10 | When I select the First check box
11 | Then the First check box should be selected
12 | When I unselect the First check box
13 | Then the First check box should not be selected
14 |
15 | Scenario Outline: Locating check boxes on the page
16 | When I search for the check box by ""
17 | Then I should be able to check the check box
18 |
19 | Scenarios:
20 | | search_by |
21 | | id |
22 | | class |
23 | | name |
24 | | xpath |
25 | | index |
26 | | value |
27 | | label |
28 | | css |
29 |
30 | Scenario Outline: Locating check boxes using multiple parameters
31 | When I search for the check box by "" and ""
32 | Then I should be able to check the check box
33 |
34 | Scenarios:
35 | | param1 | param2 |
36 | | class | index |
37 | | name | index |
38 |
39 | Scenario: Retrieve a CheckBox
40 | When I retrieve a check box element
41 | Then I should know it exists
42 | And I should know it is visible
43 |
44 | Scenario: Finding a check box dynamically
45 | When I select the first check box while the script is executing
46 | Then I should see that the checkbox exists
47 | And the First check box should be selected
48 |
--------------------------------------------------------------------------------
/lib/page-object/platforms/watir.rb:
--------------------------------------------------------------------------------
1 | module PageObject
2 | module Platforms
3 | module Watir
4 |
5 | def self.create_page_object(browser)
6 | browser = selenium_browser(browser) unless watir?(browser)
7 | return Watir::PageObject.new(browser)
8 | end
9 |
10 | def self.is_for?(browser)
11 | require 'watir'
12 | watir?(browser) || selenium?(browser)
13 | end
14 |
15 | def self.browser_for root
16 | return watir_browser(root) if watir?(root)
17 | return selenium_browser(root) if selenium?(root)
18 | nil
19 | end
20 |
21 | def self.root_element_for root
22 | Elements::Element.new(root) if is_for?(root)
23 | end
24 |
25 | def self.browser_root_for browser
26 | browser.element
27 | end
28 |
29 | private
30 |
31 | def self.watir_browser(root)
32 | return root if root.is_a?(::Watir::Browser)
33 | root.browser
34 | end
35 |
36 | def self.selenium_browser(root)
37 | return ::Watir::Browser.new(root) if root.is_a?(::Selenium::WebDriver::Driver)
38 | ::Watir::Browser.new(Selenium::WebDriver::Driver.new(root.send(:bridge)))
39 | end
40 |
41 | def self.watir?(browser)
42 | browser.is_a?(::Watir::Browser) || browser.is_a?(::Watir::HTMLElement)
43 | end
44 |
45 | def self.selenium?(browser)
46 | browser.is_a?(::Selenium::WebDriver::Driver) || browser.is_a?(::Selenium::WebDriver::Element)
47 | end
48 | end
49 | end
50 | end
51 |
--------------------------------------------------------------------------------
/features/image.feature:
--------------------------------------------------------------------------------
1 | Feature: Image
2 |
3 | Background:
4 | Given I am on the static elements page
5 |
6 | Scenario: Getting the image element
7 | When I get the image element
8 | Then the image should be "106" pixels wide
9 | And the image should be "106" pixels tall
10 |
11 | Scenario Outline: Locating an image on the page
12 | When I get the image element by ""
13 | Then the image should be "106" pixels wide
14 | And the image should be "106" pixels tall
15 |
16 | Scenarios:
17 | | search_by |
18 | | id |
19 | | class |
20 | | name |
21 | | xpath |
22 | | index |
23 | | alt |
24 | | src |
25 | | css |
26 |
27 | Scenario Outline: Locating an image using multiple parameters
28 | When I get the image element by "" and ""
29 | Then the image should be "106" pixels wide
30 | And the image should be "106" pixels tall
31 |
32 | Scenarios:
33 | | param1 | param2 |
34 | | class | index |
35 | | name | index |
36 |
37 | Scenario: Finding an image dynamically
38 | When I get the image element while the script is executing
39 | Then I should see that the image exists
40 | And the image should be "106" pixels wide
41 | And the image should be "106" pixels tall
42 |
43 | Scenario: Check an image loaded
44 | When I get the image element load status
45 | Then I should see that the image loaded
46 |
47 | Scenario: Check an image is not loaded
48 | When I get the broken image element load status
49 | Then I should see that the image is not loaded
50 |
--------------------------------------------------------------------------------
/features/ordered_list.feature:
--------------------------------------------------------------------------------
1 | Feature: Ordered list
2 |
3 | Background:
4 | Given I am on the static elements page
5 |
6 | Scenario: Getting the first element from the ordered list
7 | When I get the first item from the ordered list
8 | Then the list items text should be "Number One"
9 |
10 | Scenario Outline: Locating ordered lists on the page
11 | When I search for the ordered list by ""
12 | And I get the first item from the list
13 | Then the list items text should be "Number One"
14 | And the list should contain 3 items
15 | And each item should contain "Number"
16 |
17 | Scenarios:
18 | | search_by |
19 | | id |
20 | | class |
21 | | xpath |
22 | | index |
23 | | css |
24 |
25 | Scenario Outline: Locating ordered lists using multiple parameters
26 | When I search for the ordered list by "" and ""
27 | And I get the first item from the list
28 | Then the list items text should be "Number One"
29 |
30 | Scenarios:
31 | | param1 | param2 |
32 | | class | index |
33 |
34 | Scenario: Finding a ordered list dynamically
35 | When I search for the ordered list while the script is executing
36 | Then I should see that the ordered list exists
37 | When I get the first item from the list
38 | Then the list items text should be "Number One"
39 |
40 | Scenario: Getting the test for an ordered list
41 | Then the text for the ordered list should contain "Number One"
42 | And the text for the ordered list should contain "Number Two"
43 | And the text for the ordered list should contain "Number Three"
44 |
--------------------------------------------------------------------------------
/features/unordered_list.feature:
--------------------------------------------------------------------------------
1 | Feature: Unordered list
2 |
3 | Background:
4 | Given I am on the static elements page
5 |
6 | Scenario: Getting the first element from the unordered list
7 | When I get the first item from the unordered list
8 | Then the list items text should be "Item One"
9 |
10 | Scenario Outline: Locating unordered lists on the page
11 | When I search for the unordered list by ""
12 | And I get the first item from the list
13 | Then the list items text should be "Item One"
14 | And the list should contain 3 items
15 | And each item should contain "Item"
16 |
17 | Scenarios:
18 | | search_by |
19 | | id |
20 | | class |
21 | | xpath |
22 | | index |
23 | | css |
24 |
25 | Scenario Outline: Locating unordered lists using multiple parameters
26 | When I search for the unordered list by "" and ""
27 | And I get the first item from the list
28 | Then the list items text should be "Item One"
29 |
30 | Scenarios:
31 | | param1 | param2 |
32 | | class | index |
33 |
34 | Scenario: Finding a unordered list dynamically
35 | When I search for the unordered list while the script is executing
36 | Then I should see that the unordered list exists
37 | When I get the first item from the list
38 | Then the list items text should be "Item One"
39 |
40 | Scenario: Getting the text from an unordered list
41 | Then the text for the unordered list should contain "Item One"
42 | And the text for the unordered list should contain "Item Two"
43 | And the text for the unordered list should contain "Item Three"
44 |
--------------------------------------------------------------------------------
/features/radio_button.feature:
--------------------------------------------------------------------------------
1 | Feature: Radio Buttons
2 | In order to interact with radio buttons
3 | Testers will need access and interrogation ability
4 |
5 |
6 | Background:
7 | Given I am on the static elements page
8 |
9 | Scenario: Selecting and clearing a radio button
10 | When I select the "Milk" radio button
11 | Then the "Milk" radio button should be selected
12 | When I select the "Butter" radio button
13 | Then the "Butter" radio button should be selected
14 |
15 | Scenario Outline: Locating radio buttons on the Page
16 | When I search for the radio button by ""
17 | And I select the radio button
18 | Then the "Milk" radio button should be selected
19 |
20 | Scenarios:
21 | | search_by |
22 | | id |
23 | | class |
24 | | name |
25 | | xpath |
26 | | value |
27 | | index |
28 | | label |
29 | | css |
30 |
31 | Scenario Outline: Locating radio buttons using multiple parameters
32 | When I search for the radio button by "" and ""
33 | And I select the radio button
34 | Then the "Milk" radio button should be selected
35 |
36 | Scenarios:
37 | | param1 | param2 |
38 | | class | index |
39 | | name | index |
40 |
41 | Scenario: Retrieve a radio button
42 | When I retrieve a radio button
43 | Then I should know it exists
44 | And I should know it is visible
45 |
46 | Scenario: Finding a radio button dynamically
47 | When I select the radio button while the script is executing
48 | Then I should see that the radio button exists
49 | And the "Milk" radio button should be selected
50 |
--------------------------------------------------------------------------------
/features/link.feature:
--------------------------------------------------------------------------------
1 | Feature: Links
2 | In order to interact with links
3 | Testers will need access and interrogation ability
4 |
5 | Background:
6 | Given I am on the static elements page
7 |
8 | Scenario: Selecting a link
9 | When I select the link labeled "Google Search"
10 | Then the page should contain the text "Success"
11 |
12 | Scenario Outline: Locating links on the Page
13 | When I search for the link by ""
14 | Then I should be able to select the link
15 |
16 | Scenarios:
17 | | search_by |
18 | | id |
19 | | class |
20 | | name |
21 | | xpath |
22 | | text |
23 | | index |
24 | | href |
25 | | css |
26 | | title |
27 |
28 | Scenario: Support for multiple parameters
29 | When I select a link labeled "Hello" and index "0"
30 | Then the page should contain the text "Success"
31 | Given I am on the static elements page
32 | When I select a link labeled "Hello" and index "1"
33 | Then the page should contain the text "Success"
34 |
35 | Scenario: Retrieve a Link
36 | When I retrieve a link element
37 | Then I should know it exists
38 | And I should know it is visible
39 |
40 | Scenario: Finding a link dynamically
41 | When I select a link while the script is executing
42 | And the page should contain the text "Success"
43 |
44 | Scenario: Getting the href for a link
45 | When I get the href for the link
46 | Then I should know it was "success.html"
47 |
48 | Scenario: Locating a link using a partial href
49 | When I get the link using the href success
50 | Then I should be able to click the link
51 |
--------------------------------------------------------------------------------
/features/step_definitions/javascript_steps.rb:
--------------------------------------------------------------------------------
1 | class JavascriptPage
2 | include PageObject
3 |
4 | text_field(:expression, :id => 'calculator-expression')
5 | text_field(:results, :id => 'calculator-result')
6 | button(:compute, :value => 'Compute')
7 |
8 | end
9 |
10 | def build_url(page)
11 | target = ENV['BROWSER']
12 | return "http://localhost:4567/#{page}" if target.nil? or target.include? 'local'
13 | "http://ec2-107-22-131-88.compute-1.amazonaws.com:4567/#{page}"
14 | end
15 |
16 | Given /^I am on jQuery example page$/ do
17 | PageObject.javascript_framework = :jquery
18 | @page = JavascriptPage.new(@browser)
19 | @page.navigate_to build_url("jquery.html")
20 | end
21 |
22 | Given /^I am on the Prototype example page$/ do
23 | PageObject.javascript_framework = :prototype
24 | @page = JavascriptPage.new(@browser)
25 | @page.navigate_to build_url('prototype.html')
26 | end
27 |
28 | When /^I ask to compute "([^\"]*)"$/ do |expression|
29 | @page.expression = expression
30 | @page.compute
31 | end
32 |
33 | Then /^I should be able to wait for the answer "([^\"]*)"$/ do |answer|
34 | @page.wait_for_ajax
35 | expect(@page.results).to eql answer
36 | end
37 |
38 | Given /^I execute the javascript "([^\"]*)"$/ do |script|
39 | @answer = @page.execute_script script
40 | end
41 |
42 | Given /^I execute the javascript "([^\"]*)" with an argument of "([^\"]*)"$/ do |script, arg|
43 | @answer = @page.execute_script script, arg
44 | end
45 |
46 | Given /^I execute the javascript "([^\"]*)" with a text field argument$/ do |script|
47 | text_field = @page.text_field_element(:id => 'text_field_id')
48 | @page.execute_script(script, text_field)
49 | end
50 |
51 | Then /^I should get the answer "([^\"]*)"$/ do |answer|
52 | expect(@answer).to eql answer.to_i
53 | end
--------------------------------------------------------------------------------
/features/html/nested_elements.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Nested Elements
4 |
5 |
6 |
7 |
74 |
75 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/features/support/persistent_browser.rb:
--------------------------------------------------------------------------------
1 | require 'selenium/webdriver/remote/http/persistent'
2 |
3 | module PageObject
4 | module PersistentBrowser
5 | @@browser = false
6 | def self.get_browser
7 | if !@@browser
8 | target = ENV['BROWSER'] || 'local_chrome'
9 |
10 | if is_remote?(target)
11 | require File.dirname(__FILE__) + "/targets/#{target}"
12 | extend Target
13 | end
14 |
15 | @@browser = ENV['DRIVER'] == 'SELENIUM' ? selenium_browser(target) : watir_browser(target)
16 | end
17 | @@browser
18 | end
19 |
20 | def self.quit
21 | @@browser.quit
22 | end
23 |
24 | private
25 |
26 | def self.is_remote?(target)
27 | not target.include? 'local'
28 | end
29 |
30 | def self.watir_browser(target)
31 | if is_remote?(target)
32 | Watir::Browser.new(:remote,
33 | :url => url,
34 | :desired_capabilities => desired_capabilities)
35 | else
36 | browser = target.gsub('local_', '').to_sym
37 | Watir::Browser.new browser
38 | end
39 | end
40 |
41 | def self.selenium_browser(target)
42 | if is_remote?(target)
43 | Selenium::WebDriver.for(:remote,
44 | :url => url,
45 | :desired_capabilities => desired_capabilities)
46 | else
47 | browser = target.gsub('local_', '').to_sym
48 | Selenium::WebDriver.for browser
49 | end
50 | end
51 |
52 | def self.capabilities(browser, version, platform, name)
53 | caps = Selenium::WebDriver::Remote::Capabilities.send browser
54 | caps.version = version
55 | caps.platform = platform
56 | caps[:name] = name
57 | caps
58 | end
59 |
60 | def self.url
61 | "http://pageobject:18002ee8-963b-472e-9425-2baf0a2b6d95@ondemand.saucelabs.com:80/wd/hub"
62 | end
63 | end
64 | end
65 |
--------------------------------------------------------------------------------
/features/text_field.feature:
--------------------------------------------------------------------------------
1 | Feature: Text Fields
2 | In order to interact with text fields
3 | Testers will need access and interrogation ability
4 |
5 |
6 | Background:
7 | Given I am on the static elements page
8 |
9 | Scenario: Setting and getting a value from a text field
10 | When I type "abcDEF" into the text field
11 | Then the text field should contain "abcDEF"
12 |
13 | Scenario Outline: Locating text fields on the Page
14 | When I search for the text field by ""
15 | Then I should be able to type "I found it" into the field
16 |
17 | Examples:
18 | | search_by |
19 | | id |
20 | | class |
21 | | name |
22 | | xpath |
23 | | index |
24 | | title |
25 | | label |
26 | | css |
27 |
28 |
29 | Scenario Outline: Locating text fields on the Page using Watir
30 | When I search for the text field by ""
31 | Then I should be able to type "I found it" into the field
32 | Examples:
33 | | search_by |
34 | | data_field |
35 |
36 | Scenario Outline: Locating a text field using multiple parameters
37 | When I search for the text field by "" and ""
38 | Then I should be able to type "I found it" into the field
39 |
40 | Examples:
41 | | param1 | param2 |
42 | | class | index |
43 | | name | index |
44 |
45 | Scenario: Retrieve a text field
46 | When I retrieve a text field
47 | Then I should know it exists
48 | And I should know it is visible
49 |
50 | Scenario: Finding a text field dynamically
51 | When I find a text field while the script is executing
52 | Then I should see that the text field exists
53 | And I should be able to type "I found it" into the field element
54 |
55 | Scenario: Appending text to a text field
56 | When I type "abcd" into the text field
57 | And I append "efg" to the text field
58 | Then the text field should contain "abcdefg"
59 |
60 |
--------------------------------------------------------------------------------
/features/step_definitions/accessor_steps.rb:
--------------------------------------------------------------------------------
1 | Then /^the current item should be "([^\"]*)"$/ do |expected_text|
2 | expect(@page.sel_list_id).to eql expected_text
3 | end
4 |
5 | Then /^the text should be "([^\"]*)"$/ do |expected_text|
6 | expect(@text.tr("\n", ' ')).to eql expected_text
7 | end
8 |
9 | Then /^the text should include "([^\"]*)"$/ do |expected_text|
10 | expect(@text).to include expected_text
11 | end
12 |
13 | Then /^I should be on the success page$/ do
14 | expect(@page.text).to include 'Success'
15 | expect(@page.title).to eql 'Success'
16 | end
17 |
18 | Then /^the list items text should be "([^\"]*)"$/ do |expected_text|
19 | expect(@element.text).to eql expected_text
20 | end
21 |
22 | When /^I get the first item from the list$/ do
23 | @element = @list[0]
24 | end
25 |
26 | Then /^the table should have "([^\"]*)" rows$/ do |rows|
27 | expect(@element.rows).to eql rows.to_i
28 | end
29 |
30 | Then /^each row should contain "([^\"]*)"$/ do |text|
31 | @element.each do |row|
32 | expect(row.text).to include text
33 | end
34 | end
35 |
36 | Then /^row "([^\"]*)" should have "([^\"]*)" columns$/ do |row, cols|
37 | expect(@element[row.to_i - 1].columns).to eql cols.to_i
38 | end
39 |
40 | Then /^each column should contain "([^\"]*)"$/ do |text|
41 | row = @element[0]
42 | row.each do |column|
43 | expect(column.text).to include text
44 | end
45 | end
46 |
47 | Then /^the list should contain (\d+) items$/ do |items|
48 | expect(@list.items).to eql items.to_i
49 | end
50 |
51 | Then /^each item should contain "([^\"]*)"$/ do |text|
52 | @list.each { |item| expect(item.text).to include text }
53 | end
54 |
55 | Then /^option "([^\"]*)" should contain "([^\"]*)"$/ do |opt_num, text|
56 | @element = @page.send "sel_list_#{@how}_element".to_sym
57 | expect(@element[opt_num.to_i - 1].text).to eql text
58 | end
59 |
60 | Then /^each option should contain "([^\"]*)"$/ do |text|
61 | @element.options.each do |option|
62 | expect(option.text).to include text
63 | end
64 | end
65 |
--------------------------------------------------------------------------------
/lib/page-object/elements.rb:
--------------------------------------------------------------------------------
1 | module PageObject
2 | module Elements
3 | class << self
4 |
5 | #
6 | # method to return the collection of tag_name to class mappings
7 | #
8 | def tag_to_class
9 | @tag_to_class ||= {}
10 | end
11 |
12 | def type_to_class
13 | @type_to_class ||= {}
14 | end
15 |
16 | #
17 | # method to return the element for a tag_name
18 | #
19 | def element_class_for(tag_name, type=nil)
20 | return type_to_class[type.to_sym] if type
21 | tag_to_class[tag_name.to_sym] || ::PageObject::Elements::Element
22 | end
23 |
24 | end
25 | end
26 | end
27 |
28 |
29 | require 'page-object/elements/element'
30 | require 'page-object/elements/link'
31 | require 'page-object/elements/text_field'
32 | require 'page-object/elements/date_field'
33 | require 'page-object/elements/select_list'
34 | require 'page-object/elements/check_box'
35 | require 'page-object/elements/button'
36 | require 'page-object/elements/radio_button'
37 | require 'page-object/elements/div'
38 | require 'page-object/elements/table'
39 | require 'page-object/elements/table_cell'
40 | require 'page-object/elements/table_row'
41 | require 'page-object/elements/span'
42 | require 'page-object/elements/image'
43 | require 'page-object/elements/hidden_field'
44 | require 'page-object/elements/form'
45 | require 'page-object/elements/text_area'
46 | require 'page-object/elements/list_item'
47 | require 'page-object/elements/unordered_list'
48 | require 'page-object/elements/ordered_list'
49 | require 'page-object/elements/option'
50 | require 'page-object/elements/heading'
51 | require 'page-object/elements/paragraph'
52 | require 'page-object/elements/label'
53 | require 'page-object/elements/file_field'
54 | require 'page-object/elements/area'
55 | require 'page-object/elements/canvas'
56 | require 'page-object/elements/media'
57 | require 'page-object/elements/audio'
58 | require 'page-object/elements/video'
59 | require 'page-object/elements/bold'
60 | require 'page-object/elements/italic'
61 |
62 |
63 |
--------------------------------------------------------------------------------
/spec/page-object/javascript_framework_facade_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | class TestClass
4 | include PageObject::JavascriptFrameworkFacade
5 | end
6 |
7 |
8 | describe PageObject::JavascriptFrameworkFacade do
9 | let(:facade) { PageObject::JavascriptFrameworkFacade }
10 |
11 | it "should allow the selection of a javascript framework" do
12 | facade.framework = :jquery
13 | expect(facade.framework).to eql :jquery
14 | end
15 |
16 | it "should register the jQuery script builder" do
17 | facade.framework = :jquery
18 | expect(facade.script_builder).to eql ::PageObject::Javascript::JQuery
19 | end
20 |
21 | it "should return script for pending requests in jQuery" do
22 | facade.framework = :jquery
23 | expect(facade.pending_requests).to eql 'return jQuery.active'
24 | end
25 |
26 | it "should register the Prototype script builder" do
27 | facade.framework = :prototype
28 | expect(facade.script_builder).to eql ::PageObject::Javascript::Prototype
29 | end
30 |
31 | it "should return script for pending requests in Prototype" do
32 | facade.framework = :prototype
33 | expect(facade.pending_requests).to eql 'return Ajax.activeRequestCount'
34 | end
35 |
36 | it "should not allow you to set the framework to one it does not know about" do
37 | expect{ facade.framework = :blah }.to raise_error "You specified the Javascript framework blah and it is unknown to the system"
38 | end
39 |
40 | it "should allow you to add a new javascript framework" do
41 | module GoodFake
42 | def self.pending_requests
43 | "fake"
44 | end
45 | end
46 |
47 | facade.add_framework(:blah, GoodFake)
48 | facade.framework = :blah
49 | expect(facade.pending_requests).to eql "fake"
50 | end
51 |
52 | it "should not allow you to add a new javascript framework that is invalid" do
53 | module BadFake
54 | def self.blah
55 | end
56 | end
57 |
58 | expect{ facade.add_framework(:blah, BadFake) }.to raise_error "The Javascript framework you provided does not implement the necessary methods"
59 | end
60 | end
61 |
62 |
--------------------------------------------------------------------------------
/features/audio.feature:
--------------------------------------------------------------------------------
1 | Feature: Support for the audio element
2 |
3 | Background:
4 | Given I am on the audio video page
5 |
6 | Scenario: finding an audio element
7 | When I retrieve the audio element from the page
8 | Then I should know it exists
9 | And I should know it is visible
10 |
11 | Scenario Outline: Locating an audio element on the page
12 | When I search for the audio element by ""
13 | Then I should know it is visible
14 |
15 | Examples:
16 | | search_by |
17 | | id |
18 | | class |
19 | | xpath |
20 | | index |
21 | | css |
22 |
23 | Scenario Outline: Locating audios using multiple parameters
24 | When I search for the audio element by "" and ""
25 | Then I should know it is visible
26 |
27 | Examples:
28 | | param1 | param2 |
29 | | class | index |
30 |
31 | Scenario: Should know if it is autoplay
32 | When I retrieve the audio element from the page
33 | Then I should know the audio is not autoplay
34 |
35 | Scenario: Should know if the controls are displayed
36 | When I retrieve the audio element from the page
37 | Then I should know that the controls are displayed
38 |
39 | Scenario: Should know if it is paused
40 | When I retrieve the audio element from the page
41 | Then I should know that the audio is paused
42 |
43 | Scenario: Should know its volume
44 | When I retrieve the audio element from the page
45 | Then I should know that its volume is 1
46 |
47 | Scenario: Should know if it has ended
48 | When I retrieve the audio element from the page
49 | Then I should know that it has not ended
50 |
51 | Scenario: Should know if it is seeking
52 | When I retrieve the audio element from the page
53 | Then I should know that it is not seeking
54 |
55 | Scenario: Should know if it is in a loop
56 | When I retrieve the audio element from the page
57 | Then I should know that it is not in a loop
58 |
59 | Scenario: Should know if it is muted
60 | When I retrieve the audio element from the page
61 | Then I should know that it is muted
62 |
63 |
--------------------------------------------------------------------------------
/features/step_definitions/async_steps.rb:
--------------------------------------------------------------------------------
1 | def success
2 |
3 | end
4 |
5 | Then /^I should be able to wait until it is present$/ do
6 | @element.when_present do
7 | success
8 | end
9 | end
10 |
11 | Then /^I should be able to wait until it is visible$/ do
12 | @element.when_visible do
13 | success
14 | end
15 | end
16 |
17 | Then /^I should be able to wait until it is not visible$/ do
18 | begin
19 | @element.when_not_visible do
20 | fail
21 | end
22 | rescue
23 | success
24 | end
25 | end
26 |
27 | Then /^I should be able to wait until a block returns true$/ do
28 | @element.wait_until do
29 | @element.visible?
30 | end
31 | end
32 |
33 | class AsyncPage
34 | include PageObject
35 | button(:target, :value => 'Target')
36 | button(:hide, :value => 'Hide Button')
37 | button(:unhide, :value => 'Unhide Button')
38 | button(:create_button, :value => 'Create Button')
39 | button(:remove_button, :value => 'Remove Button')
40 | button(:created_button, :value => 'New Button')
41 | end
42 |
43 | Given /^I am on the async elements page$/ do
44 | @page = AsyncPage.new(@browser)
45 | @page.navigate_to(UrlHelper.async)
46 | end
47 |
48 | When /^I make the button invisible$/ do
49 | @page.hide
50 | sleep 2
51 | end
52 |
53 | Then /^I should be able to click it when it becomses visible$/ do
54 | @page.unhide
55 | @page.target_element.when_visible do
56 | @page.target
57 | end
58 | end
59 |
60 | Then /^I should be able to wait until the button becomes invisible$/ do
61 | @page.hide
62 | @page.target_element.when_not_visible do
63 | expect(@page.target_element.attribute("block")).to eql "none"
64 | end
65 | end
66 |
67 | When /^I add a button a few seconds from now$/ do
68 | @page.create_button
69 | end
70 |
71 | Then /^I should be able to click it when it gets added$/ do
72 | @page.created_button_element.when_present.click
73 | end
74 |
75 | When /^I remove a button a few seconds from now$/ do
76 | @page.created_button_element.when_present
77 | @page.remove_button
78 | end
79 |
80 | Then /^I should not be able to find the button$/ do
81 | @page.created_button_element.when_not_present
82 | expect(@page.created_button_element.exists?).to be false
83 | end
84 |
--------------------------------------------------------------------------------
/features/video.feature:
--------------------------------------------------------------------------------
1 | Feature: Support for video element
2 |
3 | Background:
4 | Given I am on the audio video page
5 |
6 | Scenario: finding an video element
7 | When I retrieve the video element
8 | Then I should know it exists
9 | And I should know it is visible
10 |
11 | Scenario Outline: Locating a video element on the page
12 | When I search for the video element by ""
13 | Then I should know it is visible
14 |
15 | Examples:
16 | | search_by |
17 | | id |
18 | | class |
19 | | xpath |
20 | | index |
21 | | css |
22 |
23 | Scenario Outline: Locating videos using multiple parameters
24 | When I search for the video element by "" and ""
25 | Then I should know it is visible
26 |
27 | Examples:
28 | | param1 | param2 |
29 | | class | index |
30 |
31 | Scenario: Should know if it is autoplay
32 | When I retrieve the video element
33 | Then I should know the video is not autoplay
34 |
35 | Scenario: Should know if the controls are displayed
36 | When I retrieve the video element
37 | Then I should know that the controls are displayed
38 |
39 | Scenario: Should know if it is paused
40 | When I retrieve the video element
41 | Then I should know that the video is paused
42 |
43 | Scenario: Should know its volume
44 | When I retrieve the video element
45 | Then I should know that its volume is 1
46 |
47 | Scenario: Should know its height and width
48 | When I retrieve the video element
49 | Then I should know that its height is 240 pixels
50 | And I should knot what its width is 320 pixels
51 |
52 | Scenario: Should know if it has ended
53 | When I retrieve the video element
54 | Then I should know that it has not ended
55 |
56 | Scenario: Should know if it is seeking
57 | When I retrieve the video element
58 | Then I should know that it is not seeking
59 |
60 | Scenario: Should know if it is in a loop
61 | When I retrieve the video element
62 | Then I should know that it is not in a loop
63 |
64 | Scenario: Should know if it is muted
65 | When I retrieve the video element
66 | Then I should know that it is muted
67 |
68 |
--------------------------------------------------------------------------------
/features/step_definitions/select_list_steps.rb:
--------------------------------------------------------------------------------
1 | When /^I select "([^\"]*)" from the select list$/ do |text|
2 | @page.sel_list_id = text
3 | end
4 |
5 | When /^I search for the select list by "([^\"]*)"$/ do |how|
6 | @how = how
7 | end
8 |
9 | When /^I search for the select list by "([^"]*)" and "([^"]*)"$/ do |param1, param2|
10 | @how = "#{param1}_#{param2}"
11 | end
12 |
13 | Then /^I should be able to select "([^\"]*)"$/ do |value|
14 | @page.send "sel_list_#{@how}=".to_sym, value
15 | end
16 |
17 | Then /^the value for the selected item should be "([^\"]*)"$/ do |value|
18 | result = @page.send "sel_list_#{@how}".to_sym
19 | expect(result).to eql value
20 | end
21 |
22 | When /^I find a select list while the script is executing$/ do
23 | @select_list = @page.select_list_element(:id => 'sel_list_id')
24 | end
25 |
26 | Then /^I should be able to select "([^\"]*)" from the list$/ do |value|
27 | @select_list.select(value)
28 | end
29 |
30 | Then /^I should see that the select list exists$/ do
31 | expect(@page.sel_list_id?).to eql true
32 | end
33 |
34 | Then /^the selected option should be "([^\"]*)"$/ do |text|
35 | expect(@page.select_list_element(:id => 'sel_list_id').selected_options[0]).to eql text
36 | end
37 |
38 | Then /^the select list should include "([^\"]*)"$/ do |text|
39 | expect(@page.sel_list_id_element).to include text
40 | end
41 |
42 | Then /^the select list should know that "([^\"]*)" is selected$/ do |text|
43 | expect(@page.sel_list_id_element.selected?(text)).to be true
44 | end
45 |
46 | Then /^the value for the option should be "([^\"]*)"$/ do |value|
47 | element = @page.send "sel_list_#{@how}_element".to_sym
48 | expect(element.value).to eql value
49 | end
50 |
51 | When /^I clear multiple select list$/ do
52 | @page.sel_list_multiple_element.clear
53 | end
54 |
55 | Then /^multiple select list should have no selected options$/ do
56 | expect(@page.sel_list_multiple_element.selected_options).to be_empty
57 | end
58 |
59 | When /^I select an option using the value "([^\"]*)"$/ do |value|
60 | @page.sel_list_id_element.select_value(value)
61 | end
62 |
63 | Then /^the selected option should have a value of "([^\"]*)"$/ do |value|
64 | expect(@page.sel_list_id_element.selected_values[0]).to eql value
65 | end
66 |
67 |
68 | And(/^cleared multiple select list should return nil for value$/) do
69 | expect(@page.sel_list_multiple).to be nil
70 | end
--------------------------------------------------------------------------------
/features/headings.feature:
--------------------------------------------------------------------------------
1 | Feature: Headings
2 |
3 | Background:
4 | Given I am on the static elements page
5 |
6 | Scenario: Getting the text of headings
7 | When I get the text for the "h1" element
8 | Then I should see "h1's are cool"
9 | When I get the text for the "h2" element
10 | Then I should see "h2's are cool"
11 | When I get the text for the "h3" element
12 | Then I should see "h3's are cool"
13 | When I get the text for the "h4" element
14 | Then I should see "h4's are cool"
15 | When I get the text for the "h5" element
16 | Then I should see "h5's are cool"
17 | When I get the text for the "h6" element
18 | Then I should see "h6's are cool"
19 |
20 | Scenario Outline: Locating h1s on the Page
21 | When I search for the heading1 by ""
22 | Then I should see "h1's are cool"
23 |
24 | Scenarios:
25 | | search_by |
26 | | id |
27 | | class |
28 | | xpath |
29 | | index |
30 | | css |
31 |
32 | Scenario Outline: Locating h2s on the Page
33 | When I search for the heading2 by ""
34 | Then I should see "h2's are cool"
35 |
36 | Scenarios:
37 | | search_by |
38 | | id |
39 | | class |
40 | | xpath |
41 | | index |
42 | | css |
43 |
44 | Scenario Outline: Locating h3s on the Page
45 | When I search for the heading3 by ""
46 | Then I should see "h3's are cool"
47 |
48 | Scenarios:
49 | | search_by |
50 | | id |
51 | | class |
52 | | xpath |
53 | | index |
54 | | css |
55 |
56 | Scenario Outline: Locating h4s on the Page
57 | When I search for the heading4 by ""
58 | Then I should see "h4's are cool"
59 |
60 | Scenarios:
61 | | search_by |
62 | | id |
63 | | class |
64 | | xpath |
65 | | index |
66 | | css |
67 |
68 | Scenario Outline: Locating h5s on the Page
69 | When I search for the heading5 by ""
70 | Then I should see "h5's are cool"
71 |
72 | Scenarios:
73 | | search_by |
74 | | id |
75 | | class |
76 | | xpath |
77 | | index |
78 | | css |
79 |
80 | Scenario Outline: Locating h6s on the Page
81 | When I search for the heading6 by ""
82 | Then I should see "h6's are cool"
83 |
84 | Scenarios:
85 | | search_by |
86 | | id |
87 | | class |
88 | | xpath |
89 | | index |
90 | | css |
91 |
92 |
--------------------------------------------------------------------------------
/lib/page-object/elements/table.rb:
--------------------------------------------------------------------------------
1 | module PageObject
2 | module Elements
3 | class Table < Element
4 | include Enumerable
5 |
6 | #
7 | # iterator that yields with a PageObject::Elements::TableRow
8 | #
9 | # @return [PageObject::Elements::TableRow]
10 | #
11 | def each(&block)
12 | row_items.each(&block)
13 | end
14 |
15 | alias_method :first_row, :first
16 |
17 | #
18 | # return the last row
19 | #
20 | # @return PageObject::Elements::TableRow
21 | #
22 | def last_row
23 | self[-1]
24 | end
25 |
26 | #
27 | # Return the PageObject::Elements::TableRow for the index provided. Index
28 | # is zero based. If the index provided is a String then it
29 | # will be matched with the text from any column. The text can be a substring of the full column text.
30 | #
31 | # @return [PageObject::Elements::TableRow]
32 | #
33 | def [](what)
34 | idx = find_index(what)
35 | idx && row_items[idx]
36 | end
37 |
38 | #
39 | # Returns the number of rows in the table.
40 | #
41 | def rows
42 | row_items.size
43 | end
44 |
45 | #
46 | # Returns the Array of values(String) in a column for the index provided. Index
47 | # is zero based. If the index provided is a String then it
48 | # will be matched with the text from the header. The text can be a substring of the full header text.
49 | #
50 | def column_values(what)
51 | idx = find_index_of_header(what)
52 | idx && row_items.drop(1).collect { |row| row.cell(index: idx).text }
53 | end
54 |
55 | protected
56 |
57 | def row_items
58 | meth = strategy == :descendants ? :trs : :rows
59 | @row_items ||= element.send(meth).map do |obj|
60 | ::PageObject::Elements::TableRow.new(obj)
61 | end
62 | end
63 |
64 | def strategy
65 | :children
66 | end
67 |
68 | def find_index_of_header(what)
69 | return what if what.is_a? Integer
70 | row_items[0].cells.find_index do |cell|
71 | cell.text.include? Regexp.escape(what)
72 | end
73 | end
74 |
75 | def find_index(what)
76 | return what if what.is_a? Integer
77 | row_items.find_index do |row|
78 | row.cell(text: /#{Regexp.escape(what)}/).exist?
79 | end
80 | end
81 | end
82 |
83 | ::PageObject::Elements.tag_to_class[:table] = ::PageObject::Elements::Table
84 | end
85 | end
86 |
--------------------------------------------------------------------------------
/spec/page-object/page_section_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 | require 'page-object/elements'
3 |
4 | class Container
5 | include PageObject
6 | end
7 | class SectionsPage
8 | include PageObject
9 |
10 | page_section(:container, Container, :id => 'blah')
11 | page_sections(:containers, Container, :class => 'foo')
12 | end
13 |
14 | describe PageObject::Accessors do
15 | context 'when using watir' do
16 | let(:watir_browser) { mock_watir_browser }
17 | let(:watir_page_object) { SectionsPage.new(watir_browser) }
18 |
19 | it 'it should find a page section' do
20 | expect(watir_browser).to receive(:element).with(:id => 'blah').and_return(watir_browser)
21 | section = watir_page_object.container
22 | expect(section).to be_instance_of Container
23 | end
24 | it 'it should find page sections' do
25 | expect(watir_browser).to receive(:elements).with(:class => 'foo').and_return([watir_browser, watir_browser])
26 | sections = watir_page_object.containers
27 | expect(sections).to be_instance_of(PageObject::SectionCollection)
28 | sections.each do |section|
29 | expect(section).to be_instance_of(Container)
30 | end
31 | end
32 | end
33 | end
34 |
35 | describe PageObject::SectionCollection do
36 | ContainedItem = Struct.new(:type, :name)
37 | let(:section_collection) do
38 | contained_items = [ContainedItem.new(:sandwich, :reuben), ContainedItem.new(:soup, :lobster_bisque), ContainedItem.new(:sandwich, :dagwood)]
39 | PageObject::SectionCollection[*contained_items]
40 | end
41 | it 'should inherit from Array' do
42 | expect(PageObject::SectionCollection.superclass).to eq Array
43 | end
44 | it 'should have functioning array methods' do
45 | expect(section_collection.methods).to include *Array.instance_methods
46 | expect(section_collection.last.type).to eq :sandwich
47 | end
48 | it 'should be indexed to the sections' do
49 | expect(section_collection[0]).to be_an_instance_of ContainedItem
50 | expect(section_collection[-1]).to be_an_instance_of ContainedItem
51 | end
52 | it 'should be able to iterate over the sections' do
53 | section_collection.each do |section|
54 | expect(section).to be_an_instance_of ContainedItem
55 | end
56 | end
57 | it 'should find a section by one of its values' do
58 | expect(section_collection.find_by(name: :dagwood).name).to eq :dagwood
59 | end
60 | it 'should find all sections matching a value' do
61 | expect(section_collection.select_by(type: :sandwich).map(&:type)).to eq [:sandwich, :sandwich]
62 | end
63 | end
64 |
--------------------------------------------------------------------------------
/spec/page-object/elements/select_list_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 | require 'page-object/elements'
3 |
4 | describe PageObject::Elements::SelectList do
5 | let(:selectlist) { PageObject::Elements::SelectList }
6 |
7 | describe "interface" do
8 | let(:sel_list) { double('select_list') }
9 | let(:opts) { [sel_list, sel_list] }
10 |
11 | before(:each) do
12 | allow(sel_list).to receive(:find_elements).and_return(sel_list)
13 | allow(sel_list).to receive(:each)
14 | allow(sel_list).to receive(:wd).and_return(sel_list)
15 | allow(sel_list).to receive(:map).and_return(opts)
16 | allow(sel_list).to receive(:any?)
17 | allow(sel_list).to receive(:include?)
18 | allow(sel_list).to receive(:select).and_return(opts)
19 | allow(sel_list).to receive(:text).and_return('blah')
20 | end
21 |
22 | it "should register with tag_name :select" do
23 | expect(::PageObject::Elements.element_class_for(:select)).to eql ::PageObject::Elements::SelectList
24 | end
25 |
26 | context "for watir" do
27 | let(:watir_sel_list) { PageObject::Elements::SelectList.new(sel_list) }
28 |
29 | it "should return an option when indexed" do
30 | expect(sel_list).to receive(:options).with(no_args).and_return(opts)
31 | expect(watir_sel_list[0]).to be_instance_of PageObject::Elements::Option
32 | end
33 |
34 | it "should return an array of options" do
35 | expect(sel_list).to receive(:options).with(no_args).and_return(opts)
36 | expect(watir_sel_list.options.size).to eql 2
37 | end
38 |
39 | it "should return an array of selected options" do
40 | allow(sel_list).to receive(:selected_options).and_return(opts)
41 | allow(sel_list).to receive(:text).and_return(sel_list)
42 | expect(watir_sel_list.selected_options).to eql opts
43 | end
44 |
45 | it "should know if it includes some value" do
46 | allow(sel_list).to receive(:include?).with('blah').and_return(true)
47 | watir_sel_list.include?('blah')
48 | end
49 |
50 | it "should know if an option is selected" do
51 | allow(sel_list).to receive(:selected?).with('blah').and_return(true)
52 | watir_sel_list.selected?('blah')
53 | end
54 |
55 | it "should be able to get the value for the selected options" do
56 | allow(sel_list).to receive(:selected_options).and_return(opts)
57 | allow(sel_list).to receive(:value).and_return(sel_list)
58 | expect(watir_sel_list.selected_values).to eql opts
59 | end
60 | end
61 | end
62 | end
63 |
--------------------------------------------------------------------------------
/lib/page-object/javascript_framework_facade.rb:
--------------------------------------------------------------------------------
1 | require 'page-object/javascript/jquery'
2 | require 'page-object/javascript/prototype'
3 | require 'page-object/javascript/yui'
4 | require 'page-object/javascript/angularjs'
5 |
6 |
7 | module PageObject
8 | #
9 | # Provide hooks into different common Javascript Frameworks.
10 | # Currently this module only supports jQuery and Prototype but it
11 | # has the ability for you to plug your own framework into it and
12 | # therefore have it work with this gem. You do this by calling the
13 | # #add_framework method. The module you provide must implement the
14 | # necessary methods. Please look at the jQuery or Prototype
15 | # implementations to determine the necessary methods
16 | #
17 | module JavascriptFrameworkFacade
18 |
19 | class << self
20 | #
21 | # Set the framework to use.
22 | #
23 | # @param[Symbol] the framework to use. :jquery, :prototype, :yui,
24 | # and :angularjs are supported
25 | #
26 | def framework=(framework)
27 | initialize_script_builder unless @builder
28 | raise unknown_framework(framework) unless @builder[framework]
29 | @framework = framework
30 | end
31 |
32 | #
33 | # Get the framework that will be used
34 | #
35 | def framework
36 | @framework
37 | end
38 |
39 | #
40 | # Add a framework and make it available to the system.
41 | #
42 | def add_framework(key, value)
43 | raise invalid_framework unless value.respond_to? :pending_requests
44 | initialize_script_builder unless @builder
45 | @builder[key] = value
46 | end
47 |
48 | #
49 | # get the javascript to determine number of pending requests
50 | #
51 | def pending_requests
52 | script_builder.pending_requests
53 | end
54 |
55 | def script_builder
56 | initialize_script_builder unless @builder
57 | @builder[@framework]
58 | end
59 |
60 | private
61 |
62 | def initialize_script_builder
63 | @builder = {
64 | :jquery => ::PageObject::Javascript::JQuery,
65 | :prototype => ::PageObject::Javascript::Prototype,
66 | :yui => ::PageObject::Javascript::YUI,
67 | :angularjs => ::PageObject::Javascript::AngularJS
68 | }
69 | end
70 |
71 | def unknown_framework(framework)
72 | "You specified the Javascript framework #{framework} and it is unknown to the system"
73 | end
74 |
75 | def invalid_framework
76 | "The Javascript framework you provided does not implement the necessary methods"
77 | end
78 | end
79 | end
80 | end
81 |
--------------------------------------------------------------------------------
/features/button.feature:
--------------------------------------------------------------------------------
1 | Feature: Button
2 | In order to interact with buttons
3 | Testers will need access and interrogation ability
4 |
5 |
6 | Background:
7 | Given I am on the static elements page
8 |
9 | Scenario: Clicking a button (type=submit)
10 | When I click the button
11 | Then I should be on the success page
12 |
13 | Scenario: Clicking a button (type=image)
14 | When I click the button with type image
15 | Then I should be on the success page
16 |
17 | Scenario: Clicking an image button by src
18 | When I click the image button using src
19 | Then I should be on the success page
20 |
21 | Scenario: Clicking an image button by alt
22 | When I click the image button using alt
23 | Then I should be on the success page
24 |
25 | Scenario: Retrieve a button element
26 | When I retrieve a button element
27 | Then I should know it exists
28 | And I should know it is visible
29 |
30 | Scenario Outline: Locating buttons on the page
31 | When I search for the button by ""
32 | Then I should be able to click the button
33 |
34 | Scenarios:
35 | | search_by |
36 | | id |
37 | | class |
38 | | name |
39 | | xpath |
40 | | index |
41 | | value |
42 | | css |
43 |
44 | Scenario Outline: Locating real buttons on the page
45 | When I search for the button by ""
46 | Then I should be able to click the real button
47 |
48 | Scenarios:
49 | | search_by |
50 | | id |
51 | | class |
52 | | name |
53 | | index |
54 | | value |
55 |
56 | Scenario Outline: Locating buttons on Watir only
57 | When I search for the button by ""
58 | Then I should be able to click the button
59 |
60 | Scenarios:
61 | | search_by |
62 | | text |
63 |
64 | Scenario Outline: Getting the text from a button
65 | When I get the text for a button that is a ""
66 | Then the text should be "This button is a "
67 |
68 | Scenarios:
69 | | tag |
70 | | button |
71 | | input |
72 |
73 | Scenario Outline: Locating button using multiple parameters
74 | When I search for the button by "" and ""
75 | Then I should be able to click the button
76 |
77 | Scenarios:
78 | | param1 | param2 |
79 | | class | index |
80 | | name | index |
81 |
82 | Scenario Outline: Locating real button using multiple parameters
83 | When I search for the button by "" and ""
84 | Then I should be able to click the real button
85 |
86 | Scenarios:
87 | | param1 | param2 |
88 | | class | index |
89 | | name | index |
90 |
91 |
92 | Scenario: Finding a button dynamically
93 | When I find a button while the script is executing
94 | Then I should see that the button exists
95 | And I should be able to click the button element
96 |
97 |
--------------------------------------------------------------------------------
/features/select_list.feature:
--------------------------------------------------------------------------------
1 | Feature: Select List
2 | In order to interact with select lists
3 | Testers will need access and interrogation ability
4 |
5 |
6 | Background:
7 | Given I am on the static elements page
8 |
9 | Scenario: Selecting an element on the select list
10 | When I select "Test 2" from the select list
11 | Then the current item should be "Test 2"
12 |
13 | Scenario: Selecting an element when there is a forward slash
14 | When I select "Test/Test 3" from the select list
15 | Then the current item should be "Test/Test 3"
16 |
17 | Scenario Outline: Locating select lists on the Page
18 | When I search for the select list by ""
19 | Then I should be able to select "Test 2"
20 | And the value for the selected item should be "Test 2"
21 | And the value for the option should be "option2"
22 |
23 | Scenarios:
24 | | search_by |
25 | | id |
26 | | class |
27 | | name |
28 | | xpath |
29 | | index |
30 | | label |
31 | | css |
32 |
33 | Scenario Outline: Locating a select list using multiple parameters
34 | When I search for the select list by "" and ""
35 | Then I should be able to select "Test 2"
36 | And the value for the selected item should be "Test 2"
37 | And the value for the option should be "option2"
38 |
39 | Scenarios:
40 | | param1 | param2 |
41 | | class | index |
42 | | name | index |
43 |
44 | Scenario: Iterating through the options in the select list
45 | When I search for the select list by "id"
46 | Then option "1" should contain "Test 1"
47 | And option "2" should contain "Test 2"
48 | And each option should contain "Test"
49 |
50 | Scenario: Finding a select list dynamically
51 | When I find a select list while the script is executing
52 | Then I should see that the select list exists
53 | And I should be able to select "Test 2" from the list
54 |
55 | Scenario: Getting the selected option
56 | When I select "Test 2" from the select list
57 | Then the selected option should be "Test 2"
58 |
59 | Scenario: Determining if a select list includes some option
60 | Then the select list should include "Test 2"
61 |
62 | Scenario: It should know if an option is selected
63 | When I select "Test 2" from the select list
64 | Then the select list should know that "Test 2" is selected
65 |
66 | Scenario: Clearing multiple select list
67 | When I clear multiple select list
68 | Then multiple select list should have no selected options
69 | And cleared multiple select list should return nil for value
70 |
71 | Scenario: Selecting an option by its value
72 | When I select an option using the value "option2"
73 | Then the selected option should be "Test 2"
74 |
75 | Scenario: Getting the value from a selected option
76 | When I select an option using the value "option2"
77 | Then the selected option should have a value of "option2"
78 |
--------------------------------------------------------------------------------
/features/step_definitions/table_steps.rb:
--------------------------------------------------------------------------------
1 | Then /^the data for row "([^\"]*)" should be "([^\"]*)" and "([^\"]*)"$/ do |row, col1, col2|
2 | row = (row.to_i - 1) if row.to_i > 0
3 | table_row = @element[row]
4 | expect(table_row[0].text).to eql col1
5 | expect(table_row[1].text).to eql col2
6 | end
7 |
8 | When /^I retrieve the data from the table cell$/ do
9 | @cell_data = @page.cell_id
10 | end
11 |
12 | Then /^the cell data should be '([^"]*)'$/ do |expected|
13 | expect(@cell_data).to eql expected
14 | end
15 |
16 | When /^I retrieve a table element by "([^\"]*)"$/ do |how|
17 | @element = @page.send "table_#{how}_element"
18 | end
19 |
20 | When /^I retrieve a table element by "([^\"]*)" and "([^\"]*)"$/ do |param1, param2|
21 | @element = @page.send "table_#{param1}_#{param2}_element"
22 | end
23 |
24 | When /^I retrieve a table element while the script is executing$/ do
25 | @element = @page.table_element(:id => 'table_id')
26 | end
27 |
28 | Then /^the data for the first row should be "([^\"]*)" and "([^\"]*)"$/ do |col1, col2|
29 | expect(@element.first_row[0].text).to eql col1
30 | expect(@element.first_row[1].text).to eql col2
31 | end
32 |
33 | Then /^the data for the second row should be "([^\"]*)" and "([^\"]*)"$/ do |col1, col2|
34 | expect(@element[1][0].text).to eql col1
35 | expect(@element[1][1].text).to eql col2
36 | end
37 |
38 | Then /^the data for the last row should be "([^\"]*)" and "([^\"]*)"$/ do |col1, col2|
39 | expect(@element.last_row[0].text).to eql col1
40 | expect(@element.last_row[1].text).to eql col2
41 | end
42 |
43 | Then /^I should see that the table exists$/ do
44 | expect(@page.table_id?).to be true
45 | end
46 |
47 | Then /^the data for column "([^\"]*)" and row "([^\"]*)" should be "([^\"]*)"$/ do |column, row, value|
48 | expect(@element[row.to_i - 1][column].text).to eql value
49 | end
50 |
51 | Then /^the data for row "([^\"]*)" and column "([^\"]*)" should be "([^\"]*)"$/ do |row, column, value|
52 | expect(@element[row][column].text).to eql value
53 | end
54 |
55 | Then /^the data for row "([^\"]*)" should be nil$/ do |row|
56 | expect(@element[row]).to be_nil
57 | end
58 |
59 | Then /^the data for row "([^\"]*)" and column "([^\"]*)" should be nil$/ do |row, column|
60 | expect(@element[row][column]).to be_nil
61 | end
62 |
63 | Then /^I should see the text includes "([^"]*)" when I retrieve it by "([^"]*)"$/ do |text, how|
64 | expect(@page.send("table_#{how}")).to include text
65 | end
66 |
67 | Then /^the table should be like the expected one$/ do |expected_table|
68 | expect((expected_table.diff!@element.hashes)).to be_nil
69 | end
70 |
71 | When(/^I ask for the column values for "([^"]*)"$/) do |header|
72 | @values = @page.table_id_element.column_values(header)
73 | end
74 |
75 | Then(/^I should receive:$/) do |table|
76 | expect(@values.size).to eql 2
77 | table.hashes.each do |hsh|
78 | expect(@values).to include hsh['values']
79 | end
80 | end
81 |
82 | When(/^I ask for the column values for column (\d+)$/) do |index|
83 | @values = @page.table_id_element.column_values(index.to_i)
84 | end
--------------------------------------------------------------------------------
/features/html/indexed_property.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Indexed Property Page
4 |
5 |
6 |
54 |
55 |
--------------------------------------------------------------------------------
/features/page_level_actions.feature:
--------------------------------------------------------------------------------
1 | Feature: Page level actions
2 | In order to act on pages from a web site
3 | Testers will need to use the page object to encapsulate access
4 |
5 | Background:
6 | Given I am on the static elements page
7 |
8 |
9 | Scenario: Getting the text from a web page
10 | Then the page should contain the text "Static Elements Page"
11 |
12 | Scenario: Getting the html from a web page
13 | Then the page should contain the html "Static Elements Page"
14 |
15 | Scenario: Getting the title from a web page
16 | Then the page should have the title "Static Elements Page"
17 |
18 | Scenario: Validating the page title
19 | Then the page should have the expected title
20 |
21 | Scenario: Validating the expected element
22 | Then the page should have the expected element
23 |
24 | Scenario: Validating that an expected element does not exist
25 | Then the page should not have the expected element
26 |
27 | Scenario: Waiting for something
28 | Then I should be able to wait for a block to return true
29 |
30 | Scenario: Handling alert popups
31 | When I handle the alert
32 | Then I should be able to get the alert's message
33 |
34 | Scenario: Handling possible alert popups
35 | When I handle the possible alert
36 | Then I should be able to verify the popup didn't have a message
37 |
38 | Scenario: Handling alert popups that reload the page
39 | When I handle the alert that reloads the page
40 | Then I should be able to get the alert's message
41 |
42 | Scenario: Handling confirm popups
43 | When I handle the confirm
44 | Then I should be able to get the confirm message
45 |
46 | Scenario: Handling possible confirm popups
47 | When I handle the possible confirm
48 | Then I should be able to verify the popup didn't have a message
49 |
50 | Scenario: Handling confirm popups that reload the page
51 | When I handle the confirm that reloads the page
52 | Then I should be able to get the confirm message
53 |
54 | Scenario: Handling prompt popups
55 | When I handle the prompt
56 | Then I should be able to get the message and default value
57 |
58 | Scenario: Handling possible prompt popups
59 | When I handle the possible prompt
60 | Then I should be able to verify the popup didn't have a message
61 |
62 | Scenario: Attach to window using title
63 | When I open a second window
64 | Then I should be able to attach to a page object using title
65 |
66 | Scenario: Attach to window using title with multiple windows
67 | When I open a second window
68 | When I open a third window
69 | Then I should be able to attach to a page object using title
70 |
71 | Scenario: Attach to window using url
72 | When I open a second window
73 | Then I should be able to attach to a page object using url
74 |
75 | Scenario: Attach to window using url with multiple windows
76 | When I open a second window
77 | When I open a third window
78 | Then I should be able to attach to a page object using url
79 |
80 | Scenario: Refreshing the page
81 | Then I should be able to refresh the page
82 |
83 | Scenario: Going back and forward
84 | When I select the link labeled "Google Search"
85 | Then the page should contain the text "Success"
86 | When I press the back button
87 | Then the page should contain the text "Static Elements Page"
88 | When I press the forward button
89 | Then the page should contain the text "Success"
90 |
91 |
--------------------------------------------------------------------------------
/features/step_definitions/page_level_actions_steps.rb:
--------------------------------------------------------------------------------
1 | Then /^the page should contain the text "([^\"]*)"$/ do |text|
2 | expect(@page.text).to include text
3 | end
4 |
5 | Then /^the page should contain the html "([^\"]*)"$/ do |html|
6 | expect(@page.html).to include html
7 | end
8 |
9 | Then /^the page should have the title "([^\"]*)"$/ do |title|
10 | expect(@page.title).to include title
11 | end
12 |
13 | Then /^I should be able to wait for a block to return true$/ do
14 | @page.google_search_id
15 | @page.wait_until(10, "too long to display page") do
16 | @page.text.include? 'Success'
17 | end
18 | end
19 |
20 | When /^I handle the alert$/ do
21 | @msg = @page.alert do
22 | @page.alert_button
23 | end
24 | end
25 |
26 | When /^I handle the possible alert$/ do
27 | @msg = @page.alert do
28 | @page.alert_button_element.focus
29 | end
30 | end
31 |
32 | When /^I handle the alert that reloads the page$/ do
33 | @msg = @page.alert do
34 | @page.alert_button_that_reloads
35 | end
36 | end
37 |
38 | Then /^I should be able to get the alert\'s message$/ do
39 | expect(@msg).to eql "I am an alert"
40 | end
41 |
42 | Then /^I should be able to verify the popup didn\'t have a message$/ do
43 | expect(@msg).to be_nil
44 | end
45 |
46 | When /^I handle the confirm$/ do
47 | @msg = @page.confirm(true) do
48 | @page.confirm_button
49 | end
50 | end
51 |
52 | When /^I handle the possible confirm$/ do
53 | @msg = @page.confirm(true) do
54 | @page.confirm_button_element.focus
55 | end
56 | end
57 |
58 | When /^I handle the confirm that reloads the page$/ do
59 | @msg = @page.confirm(true) do
60 | @page.confirm_button_that_reloads
61 | end
62 | end
63 |
64 | Then /^I should be able to get the confirm message$/ do
65 | expect(@msg).to eql 'set the value'
66 | end
67 |
68 | When /^I handle the prompt$/ do
69 | @msg = @page.prompt("Cheezy") do
70 | @page.prompt_button
71 | end
72 | end
73 |
74 | When /^I handle the possible prompt$/ do
75 | @msg = @page.prompt("Cheezy") do
76 | @page.prompt_button_element.focus
77 | end
78 | end
79 |
80 | Then /^I should be able to get the message and default value$/ do
81 | expect(@msg[:message]).to eql "enter your name"
82 | expect(@msg[:default_value]).to eql 'John Doe'
83 | end
84 |
85 | When /^I open a second window$/ do
86 | @page.open_window
87 | end
88 |
89 | When /^I open a third window$/ do
90 | @page.open_another_window
91 | end
92 |
93 | class SecondPage
94 | include PageObject
95 | end
96 |
97 | Then /^I should be able to attach to a page object using title$/ do
98 | @second_page = SecondPage.new(@browser)
99 | @second_page.attach_to_window(:title => "Success")
100 | expect(@second_page.title).to eql "Success"
101 | end
102 |
103 | Then /^I should be able to attach to a page object using url$/ do
104 | @second_page = SecondPage.new(@browser)
105 | @second_page.attach_to_window(:url => "success.html")
106 | expect(@second_page.current_url).to include 'success.html'
107 | end
108 |
109 | Then /^I should be able to refresh the page$/ do
110 | @page.refresh
111 | end
112 |
113 | When /^I press the back button$/ do
114 | @page.back
115 | end
116 |
117 | When /^I press the forward button$/ do
118 | @page.forward
119 | end
120 |
121 | Then /^the page should have the expected title$/ do
122 | expect(@page).to have_expected_title
123 | end
124 |
125 | Then /^the page should have the expected element$/ do
126 | expect(@page).to have_expected_element
127 | end
128 |
129 | Then /^the page should not have the expected element$/ do
130 | class FakePage
131 | include PageObject
132 | expected_element :blah
133 | end
134 | expect(FakePage.new(@browser)).not_to have_expected_element
135 | end
136 |
--------------------------------------------------------------------------------
/spec/page-object/elements/nested_element_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 | require 'page-object/elements'
3 |
4 |
5 | describe "Element with nested elements" do
6 | before(:each) do
7 | @watir_driver = instance_double('Watir::Element')
8 | @watir_element = PageObject::Elements::Element.new(@watir_driver)
9 | end
10 |
11 | it "should find nested links" do
12 | expect(@watir_driver).to receive(:link).with(:id => 'blah')
13 | @watir_element.link_element(:id => 'blah')
14 | end
15 |
16 | it "should find nested buttons" do
17 | expect(@watir_driver).to receive(:button).with(:id => 'blah')
18 | @watir_element.button_element(:id => 'blah')
19 | end
20 |
21 | it "should find nested text fields" do
22 | expect(@watir_driver).to receive(:text_field).with(:id => 'blah')
23 | @watir_element.text_field_element(:id => 'blah')
24 | end
25 |
26 | it "should find nested hidden fields" do
27 | expect(@watir_driver).to receive(:hidden)
28 | @watir_element.hidden_field_element
29 | end
30 |
31 | it "should find nested text areas" do
32 | expect(@watir_driver).to receive(:textarea)
33 | @watir_element.text_area_element
34 | end
35 |
36 | it "should find a nested select list" do
37 | expect(@watir_driver).to receive(:select_list)
38 | @watir_element.select_list_element
39 | end
40 |
41 | it "should find a nested checkbox" do
42 | expect(@watir_driver).to receive(:checkbox)
43 | @watir_element.checkbox_element
44 | end
45 |
46 | it "should find a nested radio button" do
47 | expect(@watir_driver).to receive(:radio)
48 | @watir_element.radio_button_element
49 | end
50 |
51 | it "should find a nested div" do
52 | expect(@watir_driver).to receive(:div)
53 | @watir_element.div_element
54 | end
55 |
56 | it "should find a nested span" do
57 | expect(@watir_driver).to receive(:span)
58 | @watir_element.span_element
59 | end
60 |
61 | it "should find a nested table" do
62 | expect(@watir_driver).to receive(:table)
63 | @watir_element.table_element
64 | end
65 |
66 | it "should find a nested cell" do
67 | expect(@watir_driver).to receive(:td)
68 | @watir_element.cell_element
69 | end
70 |
71 | it "should find a nested image" do
72 | expect(@watir_driver).to receive(:image)
73 | @watir_element.image_element
74 | end
75 |
76 | it "should find a nested form" do
77 | expect(@watir_driver).to receive(:form)
78 | @watir_element.form_element
79 | end
80 |
81 | it "should find a nested ordered list" do
82 | expect(@watir_driver).to receive(:ol)
83 | @watir_element.ordered_list_element
84 | end
85 |
86 | it "should find a nested unordered list" do
87 | expect(@watir_driver).to receive(:ul)
88 | @watir_element.unordered_list_element
89 | end
90 |
91 | it "should find a nested list item" do
92 | expect(@watir_driver).to receive(:li)
93 | @watir_element.list_item_element
94 | end
95 |
96 | it "should find a nested h1" do
97 | expect(@watir_driver).to receive(:h1)
98 | @watir_element.h1_element
99 | end
100 |
101 | it "should find a nested h2" do
102 | expect(@watir_driver).to receive(:h2)
103 | @watir_element.h2_element
104 | end
105 |
106 | it "should find a nested h3" do
107 | expect(@watir_driver).to receive(:h3)
108 | @watir_element.h3_element
109 | end
110 |
111 | it "should find a nested h4" do
112 | expect(@watir_driver).to receive(:h4)
113 | @watir_element.h4_element
114 | end
115 |
116 | it "should find a nested h5" do
117 | expect(@watir_driver).to receive(:h5)
118 | @watir_element.h5_element
119 | end
120 |
121 | it "should find a nested h6" do
122 | expect(@watir_driver).to receive(:h6)
123 | @watir_element.h6_element
124 | end
125 | end
126 |
--------------------------------------------------------------------------------
/lib/page-object/page_populator.rb:
--------------------------------------------------------------------------------
1 | module PageObject
2 | module PagePopulator
3 |
4 | #
5 | # This method will populate all matched page TextFields,
6 | # TextAreas, SelectLists, FileFields, Checkboxes, and Radio Buttons from the
7 | # Hash passed as an argument. The way it find an element is by
8 | # matching the Hash key to the name you provided when declaring
9 | # the element on your page.
10 | #
11 | # Checkbox and Radio Button values must be true or false.
12 | #
13 | # @example
14 | # class ExamplePage
15 | # include PageObject
16 | #
17 | # text_field(:username, :id => 'username_id')
18 | # checkbox(:active, :id => 'active_id')
19 | # end
20 | #
21 | # ...
22 | #
23 | # @browser = Watir::Browser.new :firefox
24 | # example_page = ExamplePage.new(@browser)
25 | # example_page.populate_page_with :username => 'a name', :active => true
26 | #
27 | # @param data [Hash] the data to use to populate this page. The key
28 | # can be either a string or a symbol. The value must be a string
29 | # for TextField, TextArea, SelectList, and FileField and must be true or
30 | # false for a Checkbox or RadioButton.
31 | #
32 | def populate_page_with(data)
33 | data.to_h.each do |key, value|
34 | populate_section(key, value) if value.respond_to?(:to_h)
35 | populate_value(self, key, value)
36 | end
37 | end
38 |
39 | private
40 |
41 | def populate_section(section, data)
42 | return unless self.respond_to? section
43 | data.to_h.each do |key, value|
44 | populate_value(self.send(section), key, value)
45 | end
46 | end
47 |
48 | def populate_value(receiver, key, value)
49 | populate_checkbox(receiver, key, value) if is_checkbox?(receiver, key) and is_enabled?(receiver, key)
50 | populate_radiobuttongroup(receiver, key, value) if is_radiobuttongroup?(receiver, key)
51 | populate_radiobutton(receiver, key, value) if is_radiobutton?(receiver, key) and is_enabled?(receiver, key)
52 | populate_select_list(receiver, key, value) if is_select_list?(receiver, key)
53 | populate_text(receiver, key, value) if is_text?(receiver, key) and is_enabled?(receiver, key)
54 | end
55 |
56 | def populate_text(receiver, key, value)
57 | receiver.send "#{key}=", value
58 | end
59 |
60 | def populate_checkbox(receiver, key, value)
61 | return receiver.send "check_#{key}" if value
62 | receiver.send "uncheck_#{key}"
63 | end
64 |
65 | def populate_radiobutton(receiver, key, value)
66 | receiver.send "select_#{key}" if value
67 | end
68 |
69 | def populate_radiobuttongroup(receiver, key, value)
70 | receiver.send("select_#{key}", value)
71 | end
72 |
73 | def populate_select_list(receiver, key, value)
74 | receiver.send "#{key}=", value
75 | end
76 |
77 | def is_text?(receiver, key)
78 | return false if is_select_list?(receiver, key)
79 | receiver.respond_to?("#{key}=".to_sym)
80 | end
81 |
82 | def is_checkbox?(receiver, key)
83 | receiver.respond_to?("check_#{key}".to_sym)
84 | end
85 |
86 | def is_radiobutton?(receiver, key)
87 | receiver.respond_to?("select_#{key}".to_sym)
88 | end
89 |
90 | def is_radiobuttongroup?(receiver, key)
91 | receiver.respond_to?("select_#{key}".to_sym) and receiver.respond_to?("#{key}_values")
92 | end
93 |
94 | def is_select_list?(receiver, key)
95 | receiver.respond_to?("#{key}_options".to_sym)
96 | end
97 |
98 | def is_enabled?(receiver, key)
99 | return false if is_radiobuttongroup?(receiver, key)
100 | return true if (receiver.send "#{key}_element").tag_name == "textarea"
101 | element = receiver.send("#{key}_element")
102 | element.enabled? and element.present?
103 | end
104 | end
105 | end
106 |
--------------------------------------------------------------------------------
/lib/page-object/locator_generator.rb:
--------------------------------------------------------------------------------
1 | module PageObject
2 | module LocatorGenerator
3 |
4 | BASIC_ELEMENTS = %i(
5 | abbr
6 | address
7 | animate
8 | animate_motion
9 | animate_transform
10 | article
11 | as
12 | aside
13 | base
14 | bdi
15 | bdo
16 | blockquote
17 | body
18 | br
19 | caption
20 | circle
21 | cite
22 | code
23 | col
24 | colgroup
25 | command
26 | cursor
27 | data
28 | datalist
29 | dd
30 | defs
31 | del
32 | desc
33 | details
34 | dfn
35 | dialog
36 | discard
37 | dl
38 | dt
39 | ellipse
40 | em
41 | embed
42 | fieldset
43 | figcaption
44 | figure
45 | font
46 | footer
47 | foreign_object
48 | g
49 | head
50 | header
51 | hgroup
52 | hr
53 | html
54 | ins
55 | kbd
56 | keygen
57 | legend
58 | line
59 | linear_gradient
60 | main
61 | map
62 | mark
63 | marker
64 | menu
65 | menuitem
66 | mesh_gradient
67 | mesh_patch
68 | mesh_row
69 | meta
70 | metadata
71 | meter
72 | mpath
73 | nav
74 | noscript
75 | object
76 | optgroup
77 | output
78 | p
79 | param
80 | path
81 | pattern
82 | polygon
83 | polyline
84 | pre
85 | progress
86 | q
87 | radial_gradient
88 | rect
89 | rp
90 | rt
91 | ruby
92 | s
93 | samp
94 | script
95 | section
96 | set
97 | small
98 | source
99 | stop
100 | strong
101 | style
102 | sub
103 | summary
104 | sup
105 | switch
106 | symbol
107 | template
108 | text_path
109 | thread
110 | time
111 | title
112 | track
113 | tspan
114 | u
115 | use
116 | var
117 | view
118 | wbr
119 | )
120 |
121 |
122 | ADVANCED_ELEMENTS = %i(
123 | text_field
124 | date_field
125 | hidden_field
126 | text_area
127 | select_list
128 | link
129 | checkbox
130 | radio_button
131 | button
132 | div
133 | span
134 | table
135 | cell
136 | row
137 | image
138 | form
139 | list_item
140 | ordered_list
141 | unordered_list
142 | h1
143 | h2
144 | h3
145 | h4
146 | h5
147 | h6
148 | paragraph
149 | label
150 | file_field
151 | area
152 | canvas
153 | audio
154 | video
155 | b
156 | i
157 | svg
158 | )
159 |
160 | def self.generate_locators(target)
161 | ADVANCED_ELEMENTS.each do |tag|
162 | target.send(:define_method, "#{tag.to_s}_element") do |*identifier|
163 | @platform.send "#{tag.to_s}_for", locator(identifier)
164 | end
165 |
166 | target.send(:define_method, "#{tag.to_s}_elements") do |*identifier|
167 | @platform.send("#{tag.to_s}s_for", identifier[0] ? identifier[0] : {})
168 | end
169 | end
170 |
171 | BASIC_ELEMENTS.each do |tag|
172 | target.send(:define_method, "#{tag.to_s}_element") do |*identifier|
173 | @platform.send :element_for, tag, locator(identifier)
174 | end
175 |
176 | target.send(:define_method, "#{tag.to_s}_elements") do |*identifier|
177 | @platform.send(:elements_for, tag, identifier[0] ? identifier[0] : {})
178 | end
179 | end
180 | end
181 |
182 | end
183 | end
184 |
--------------------------------------------------------------------------------
/lib/page-object/widgets.rb:
--------------------------------------------------------------------------------
1 | require 'page-object/elements'
2 | require 'page-object/platforms/watir/page_object'
3 |
4 | module PageObject
5 | module Widgets
6 |
7 | #
8 | # Module that allows for the registration of widget classes which extend the functionality of PageObject
9 | # Allows any classes which extend PageObject::Element to be used as PageObject elements.
10 | # This allows such widgets to be created using the defined tags.
11 | #
12 | # @param [Symbol] defines the symbol which will be used as an accessor name.
13 | # @param [Class] the widget class extending PageObject::Elements::Element
14 | # @param [Symbol] the symbol of the html element used when searching for this widget.
15 | #
16 | #
17 | def self.register_widget(widget_tag, widget_class, base_element_tag)
18 | if widget_class.ancestors.include? Elements::Element
19 | define_accessors(Accessors, widget_tag, widget_class)
20 | define_nested_elements(Elements::Element, widget_tag)
21 | define_locators(PageObject, widget_tag)
22 |
23 | PageObject::Platforms::Watir::PageObject.define_widget_accessors(widget_tag, widget_class, base_element_tag)
24 | end
25 | end
26 |
27 | private
28 |
29 | def self.define_accessors(base, widget_tag, widget_class)
30 | accessors_module = Module.new do
31 | define_method widget_tag do |name, *identifier_args, &block|
32 |
33 | identifier = identifier_args.first
34 | identifier = {:index => 0} if identifier.nil?
35 |
36 | define_method("#{name}_element") do
37 | return call_block(&block) if block
38 | platform.send("#{widget_tag}_for", identifier.clone)
39 | end
40 | define_method("#{name}?") do
41 | return call_block(&block).exists? if block
42 | platform.send("#{widget_tag}_for", identifier.clone).exists?
43 | end
44 | if widget_class.respond_to? :accessor_methods
45 | widget_class.accessor_methods(self, name)
46 | end
47 | end
48 | define_method widget_class.plural_form do |name, *identifier_args, &block|
49 | define_method("#{name}_elements") do
50 | return call_block(&block) unless block.nil?
51 | platform_method = "#{widget_tag.to_s}s_for"
52 | platform.send platform_method, (identifier_args.first ? identifier_args.first.clone : {})
53 | end
54 | end
55 | end
56 |
57 | base.send(:include, accessors_module)
58 | end
59 |
60 | def self.define_nested_elements(base, widget_tag)
61 | define_singular_nested_accessor(base, widget_tag)
62 | define_multiple_nested_accessor(base, widget_tag)
63 | end
64 |
65 | def self.define_multiple_nested_accessor(base, widget_tag)
66 | base.send(:define_method, "#{widget_tag}_elements") do |*args|
67 | identifier = args[0] ? args[0] : {}
68 | @platform.send("#{widget_tag}s_for", identifier.clone)
69 | end
70 | end
71 |
72 | def self.define_singular_nested_accessor(base, widget_tag)
73 | base.send(:define_method, "#{widget_tag}_element") do |*args|
74 | identifier = args[0] ? args[0] : {:index => 0}
75 | @platform.send("#{widget_tag}_for", identifier.clone)
76 | end
77 | end
78 |
79 | def self.define_locators(base, widget_tag)
80 | define_singular_locator(base, widget_tag)
81 | define_multiple_locator(base, widget_tag)
82 | end
83 |
84 | def self.define_multiple_locator(base, widget_tag)
85 | base.send(:define_method, "#{widget_tag}_elements") do |*args|
86 | identifier = args[0] ? args[0] : {}
87 | platform.send("#{widget_tag}s_for", identifier.clone)
88 | end
89 | end
90 |
91 | def self.define_singular_locator(base, widget_tag)
92 | base.send(:define_method, "#{widget_tag}_element") do |*args|
93 | identifier = args[0] ? args[0] : {:index => 0}
94 | platform.send("#{widget_tag}_for", identifier.clone)
95 | end
96 | end
97 | end
98 | end
99 |
--------------------------------------------------------------------------------
/features/frames.feature:
--------------------------------------------------------------------------------
1 | Feature: Handling frames
2 |
3 | Scenario: Accessing elements within the frame
4 | Given I am on the frame elements page
5 | When I type "page-object" into the text field for frame 2 using "id"
6 | Then I should verify "page-object" is in the text field for frame 2 using "id"
7 | When I type "page-object" into the text field for frame 2 using "name"
8 | Then I should verify "page-object" is in the text field for frame 2 using "name"
9 | When I type "page-object" into the text field for frame 2 using "index"
10 | Then I should verify "page-object" is in the text field for frame 2 using "index"
11 |
12 | Scenario: Accessing elements within the frame using Regexp
13 | Given I am on the frame elements page
14 | When I type "page-object" into the text field for frame 2 using "regex"
15 | Then I should verify "page-object" is in the text field for frame 2 using "regex"
16 |
17 | Scenario: Accessing elements within the frame using multiple identifiers
18 | Given I am on the iframe elements page
19 | When I type "page-object" into the text field for frame 2 using "visible_true"
20 | Then I should verify "page-object" is in the text field for frame 2 using "visible_true"
21 |
22 | Scenario: Accessing elements within the frame using visible: true identifier
23 | Given I am on the iframe elements page
24 | When I type "page-object" into the text field for frame 2 using "multiple identifiers"
25 | Then I should verify "page-object" is in the text field for frame 2 using "multiple identifiers"
26 |
27 | Scenario: Switching between frames
28 | Given I am on the frame elements page
29 | When I type "page-object" into the text field for frame 2 using "id"
30 | And I type "page-object" into the text field from frame 1 using "id"
31 | Then I should verify "page-object" is in the text field for frame 2 using "id"
32 | And I should verify "page-object" is in the text field for frame 1 using "id"
33 |
34 | Scenario: Accessing elements within the frame
35 | Given I am on the iframe elements page
36 | When I type "page-object" into the text field for frame 2 using "id"
37 | Then I should verify "page-object" is in the text field for frame 2 using "id"
38 | When I type "page-object" into the text field for frame 2 using "name"
39 | Then I should verify "page-object" is in the text field for frame 2 using "name"
40 | When I type "page-object" into the text field for frame 2 using "index"
41 | Then I should verify "page-object" is in the text field for frame 2 using "index"
42 |
43 | Scenario: Switching between frames
44 | Given I am on the iframe elements page
45 | When I type "page-object" into the text field for frame 2 using "id"
46 | And I type "page-object" into the text field from frame 1 using "id"
47 | Then I should verify "page-object" is in the text field for frame 2 using "id"
48 | And I should verify "page-object" is in the text field for frame 1 using "id"
49 |
50 | Scenario: Nested frames
51 | Given I am on the nested frame elements page
52 | Then I should be able to click the link in the frame
53 |
54 | Scenario: Identifying items in frames at runtime
55 | Given I am on the frame elements page
56 | When I type "page-object" into the text field from frame 1 identified dynamically
57 | Then I should verify "page-object" in the text field for frame 1 identified dynamically
58 |
59 | Scenario: Identifying items in iframes at runtime
60 | Given I am on the iframe elements page
61 | When I type "page-object" into the text field from iframe 1 identified dynamically
62 | Then I should verify "page-object" in the text field for iframe 1 identified dynamically
63 |
64 | Scenario: Handling alerts inside frames
65 | Given I am on the frame elements page
66 | When I trigger an alert within a frame
67 | Then I should be able to get the alert's message
68 |
69 | Scenario: Handling confirms inside frames
70 | Given I am on the frame elements page
71 | When I trigger a confirm within a frame
72 | Then I should be able to get the confirm message
73 |
74 | Scenario: Handling prompts inside frames
75 | Given I am on the frame elements page
76 | When I trigger a prompt within a frame
77 | Then I should be able to get the message and default value
78 |
79 | Scenario: Frames in sections
80 | Given I am on the frame section page
81 | Then I should be able to access an element in the frame in the section repeatedly
82 |
83 | Scenario: Indexed Properties in frames
84 | Given I am on the frame elements page
85 | Then I can access elements in indexed properties
--------------------------------------------------------------------------------
/lib/page-object/page_factory.rb:
--------------------------------------------------------------------------------
1 | require 'page_navigation'
2 |
3 | module PageObject
4 | #
5 | # Module to facilitate to creating of page objects in step definitions. You
6 | # can make the methods below available to all of your step definitions by adding
7 | # this module to World. This idea was first discussed in Alister Scott's blog
8 | # entry http://watirmelon.com/2011/06/07/removing-local-page-references-from-cucumber-steps/.
9 | #
10 | # @example Making the PageFactory available to your step definitions
11 | # World PageObject::PageFactory
12 | #
13 | # @example Visiting a page for the first time in a Scenario
14 | # visit_page MyPageObject do |page|
15 | # page.name = 'Cheezy'
16 | # end
17 | #
18 | # @example using a page that has already been visited in a Scenario
19 | # on_page MyPageObject do |page|
20 | # page.name.should == 'Cheezy'
21 | # end
22 | #
23 | # If you plan to use the navigate_to method you will need to ensure
24 | # you setup the possible routes ahead of time. You must always have
25 | # a default route in order for this to work. Here is an example of
26 | # how you define routes:
27 | #
28 | # @example Example routes defined in env.rb
29 | # PageObject::PageFactory.routes = {
30 | # :default => [[PageOne,:method1], [PageTwoA,:method2], [PageThree,:method3]],
31 | # :another_route => [[PageOne,:method1, "arg1"], [PageTwoB,:method2b], [PageThree,:method3]]
32 | # }
33 | #
34 | # Notice the first entry of :another_route is passing an argument
35 | # to the method.
36 | #
37 | module PageFactory
38 | include PageNavigation
39 |
40 |
41 | #
42 | # Create and navigate to a page object. The navigation will only work if the
43 | # 'page_url' method was call on the page object.
44 | #
45 | # @param [PageObject, String] a class that has included the
46 | # PageObject module or a string containing the name of the class
47 | # @param Hash values that is pass through to page class a
48 | # available in the @params instance variable.
49 | # @param an optional block to be called
50 | # @return [PageObject] the newly created page object
51 | #
52 | def visit_page(page_class, params={:using_params => {}}, &block)
53 | on_page page_class, params, true, &block
54 | end
55 |
56 | # Support 'visit' for readability of usage
57 | alias_method :visit, :visit_page
58 |
59 | #
60 | # Create a page object.
61 | #
62 | # @param [PageObject, String] a class that has included the PageObject module or a string containing the name of the class
63 | # @param Hash values that is pass through to page class a
64 | # available in the @params instance variable.
65 | # @param [Boolean] a boolean indicating if the page should be visited? default is false.
66 | # @param [block] an optional block to be called
67 | # @return [PageObject] the newly created page object
68 | #
69 | def on_page(page_class, params={:using_params => {}}, visit=false, &block)
70 | page_class = class_from_string(page_class) if page_class.is_a? String
71 | return super(page_class, params, visit, &block) unless page_class.ancestors.include? PageObject
72 | merged = page_class.params.merge(params[:using_params])
73 | page_class.instance_variable_set("@merged_params", merged) unless merged.empty?
74 | @current_page = page_class.new(@browser, visit)
75 | block.call @current_page if block
76 | @current_page
77 | end
78 |
79 | # Support 'on' for readability of usage
80 | alias_method :on, :on_page
81 |
82 | #
83 | # Create a page object if and only if the current page is the same page to be created
84 | #
85 | # @param [PageObject, String] a class that has included the PageObject module or a string containing the name of the class
86 | # @param Hash values that is pass through to page class a
87 | # available in the @params instance variable.
88 | # @param [block] an optional block to be called
89 | # @return [PageObject] the newly created page object
90 | #
91 | def if_page(page_class, params={:using_params => {}},&block)
92 | page_class = class_from_string(page_class) if page_class.is_a? String
93 | return @current_page unless @current_page.class == page_class
94 | on_page(page_class, params, false, &block)
95 | end
96 |
97 | # Support 'if' for readability of usage
98 | alias_method :if, :if_page
99 |
100 | private
101 |
102 | def class_from_string(str)
103 | str.split('::').inject(Object) do |mod, class_name|
104 | mod.const_get(class_name)
105 | end
106 | end
107 | end
108 | end
109 |
--------------------------------------------------------------------------------