File Coverage

blib/lib/Selenium/PageObject.pm
Criterion Covered Total %
statement 28 52 53.8
branch 3 20 15.0
condition n/a
subroutine 9 16 56.2
pod 5 5 100.0
total 45 93 48.3


line stmt bran cond sub pod time code
1             package Selenium::PageObject;
2             {
3             $Selenium::PageObject::VERSION = '0.011';
4             }
5              
6 2     2   247906 use 5.010;
  2         8  
  2         63  
7 2     2   8 use strict;
  2         2  
  2         43  
8 2     2   9 use warnings;
  2         5  
  2         35  
9              
10 2     2   8 use Carp;
  2         4  
  2         131  
11 2     2   9 use Scalar::Util qw(reftype blessed);
  2         2  
  2         122  
12 2     2   462 use Try::Tiny;
  2         1142  
  2         88  
13              
14 2     2   992 use Selenium::Remote::WDKeys; #Needed to send things like tabs for navigation
  2         1194  
  2         96  
15 2     2   758 use Selenium::Element;
  2         4  
  2         821  
16              
17             =head1 NAME
18              
19             Selenium::PageObject - Selenium's PageObject pattern in Perl. Now your module @ISA pageObject!
20              
21             =head1 SYNOPSIS
22              
23             This module is intended to be a base for PageObjects.
24             It abstracts a good deal of the things required to get/set various page inputs, and provides callback hooks so you can do special things like wait for JS.
25             It also is driver agnostic -- use WWW::Selenium or Selenium::Remote::Driver if you want.
26             I recommend Selenium::Remote::Driver due to it having a more complete feature set.
27              
28             Refer to the other module in this distribution L for the rest.
29              
30             =head1 CONSTRUCTOR
31              
32             =head2 new(driver,uri)
33              
34             Create a new PageObject using the provided driver, and navigate to the provided URI.
35             If you have subclassed your driver, you will need to override this method to not do it's strict driver class checks.
36              
37             B:
38              
39             I - The driver object
40              
41             I - the page this object should fiddle with (saved as $self->{'page'})
42              
43             B:
44              
45             new Selenium::PageObject object
46              
47             =cut
48              
49             sub new {
50 2     2 1 662 my ($class,$driver,$uri) = @_;
51 2 50       5 confess("Constructor must be called statically, not by an instance") if ref($class);
52 2 50       3 confess("Driver must be an instance of Selenium::Remote::Driver or WWW::Selenium") if !( grep {defined(blessed($driver)) && $_ eq blessed($driver)} qw(Selenium::Remote::Driver WWW::Selenium) );
  4 50       528  
53              
54 0           my $self = {
55             'drivertype' => blessed($driver) eq 'WWW::Selenium',
56             'driver' => $driver,
57             'page' => $uri
58             };
59              
60 0 0         $self->{'drivertype'} ? $driver->open($uri) : $driver->get($uri); #Get initial page based on what type of driver used
61              
62 0           bless $self, $class;
63 0           return $self;
64             }
65              
66             =head1 UTILITY
67              
68             =head2 driver
69              
70             The base selenium driver is available to you here.
71              
72             =cut
73              
74             sub driver {
75 0     0 1   my $self = shift;
76 0           return $self->{'driver'};
77             }
78              
79             =head1 GETTERS
80              
81             =head2 getElement(SELECTOR,SELECTORTYPE)
82              
83             Get the first element matching the provided selector and selector type. Refer to your driver's documentation as to valid types.
84              
85             B:
86              
87             I - Instructions for finding some element on the page
88              
89             I - Specifiation by which above instructions are parsed
90              
91             B:
92              
93             new Selenium::Element object
94              
95             =cut
96              
97             sub getElement {
98 0     0 1   my ($self,$selector,$selectortype) = @_;
99 0           my $element;
100 0 0         if ($self->{'drivertype'}) {
101 0 0         $element = $self->{'driver'}->is_element_present("$selectortype=$selector") ? "$selectortype=$selector" : undef;
102             } else {
103             try {
104 0     0     $element = $self->{'driver'}->find_element($selector,$selectortype);
105             } catch {
106 0     0     carp "# $_ \n";
107 0           $element = undef;
108             }
109 0           }
110 0 0         return Selenium::Element->new($element,$self->{'drivertype'} ? $self->{'driver'} : $self->{'drivertype'},[$selector,$selectortype]);
111             }
112              
113             =head2 getElements(SELECTOR,SELECTORTYPE)
114              
115             Get the elements matching the provided selector and selector type. Refer to your driver's documentation as to valid types.
116             WWW::Selenium is designed to work with single elements, so this method will fail when using it. Consider refining your selectors and looping instead.
117              
118             B:
119              
120             I - Instructions for finding some element on the page
121              
122             I - Specifiation by which above instructions are parsed
123              
124             B:
125              
126             array of new Selenium::Element objects
127              
128             =cut
129              
130             sub getElements {
131 0     0 1   my ($self,$selector,$selectortype) = @_;
132 0           my $elements = [];
133 0 0         confess ("WWW::Selenium is designed to work with single elements. Consider refining your selectors and looping instead.") if $self->{'drivertype'};
134             try {
135 0     0     @$elements = $self->{'driver'}->find_elements($selector,$selectortype);
136 0           };
137 0 0         return map {Selenium::Element->new($_,$self->{'drivertype'} ? $self->{'driver'} : $self->{'drivertype'},[$selector,$selectortype])} @$elements;
  0            
138             }
139              
140             =head1 GLOBAL EVENTS
141              
142             =head2 tab
143              
144             Send a tab to the page, to test tab navigation, or to de-focus the current element (useful for lose focus listeners, etc).
145              
146             =cut
147              
148             sub tab {
149 0     0 1   my $self = shift;
150             #9 is VK_TAB
151 0 0         $self->{'drivertype'} ? $self->driver->key_press_native(9) : $self->driver->send_keys_to_active_element(KEYS->{'tab'});
152             }
153              
154             1;
155              
156             __END__