File Coverage

blib/lib/Selenium/PageObject.pm
Criterion Covered Total %
statement 25 49 51.0
branch 3 20 15.0
condition n/a
subroutine 8 15 53.3
pod 5 5 100.0
total 41 89 46.0


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