File Coverage

lib/Test/WWW/Selenium.pm
Criterion Covered Total %
statement 89 101 88.1
branch 35 44 79.5
condition 16 21 76.1
subroutine 15 16 93.7
pod 3 4 75.0
total 158 186 84.9


line stmt bran cond sub pod time code
1             package Test::WWW::Selenium;
2             {
3             $Test::WWW::Selenium::VERSION = '1.36';
4             }
5             # ABSTRACT: Test applications using Selenium Remote Control
6 6     6   155874 use strict;
  6         16  
  6         252  
7 6     6   33 use base qw(WWW::Selenium);
  6         11  
  6         5751  
8 6     6   59 use Carp qw(croak);
  6         11  
  6         329  
9              
10              
11 6     6   3948 use Test::More;
  6         94312  
  6         67  
12 6     6   4360 use Test::Builder;
  6         12  
  6         4729  
13              
14             our $AUTOLOAD;
15              
16             my $Test = Test::Builder->new;
17             $Test->exported_to(__PACKAGE__);
18              
19             my %comparator = (
20             is => 'is_eq',
21             isnt => 'isnt_eq',
22             like => 'like',
23             unlike => 'unlike',
24             );
25              
26             # These commands don't require a locator
27             # grep item lib/WWW/Selenium.pm | grep sel | grep \(\) | grep get
28             my %no_locator = map { $_ => 1 }
29             qw( speed alert confirmation prompt location title
30             body_text all_buttons all_links all_fields
31             mouse_speed all_window_ids all_window_names
32             all_window_titles html_source cookie absolute_location );
33              
34             sub no_locator {
35 8     8 0 18 my $self = shift;
36 8         20 my $method = shift;
37 8         37 return $no_locator{$method};
38             }
39              
40             sub AUTOLOAD {
41 11     11   17184 my $name = $AUTOLOAD;
42 11         119 $name =~ s/.*:://;
43 11 50       113 return if $name eq 'DESTROY';
44 11         21 my $self = $_[0];
45              
46 11         20 my $sub;
47 11 100       129 if ($name =~ /(\w+)_(is|isnt|like|unlike)$/i) {
    100          
48 8         35 my $getter = "get_$1";
49 8         88 my $comparator = $comparator{lc $2};
50              
51             # make a subroutine that will call Test::Builder's test methods
52             # with selenium data from the getter
53 8 100       514 if ($self->no_locator($1)) {
54             $sub = sub {
55 11     11   25573 my( $self, $str, $name ) = @_;
56 11 50       75 diag "Test::WWW::Selenium running $getter (@_[1..$#_])"
57             if $self->{verbose};
58 11 100 66     1202 $name = "$getter, '$str'"
59             if $self->{default_names} and !defined $name;
60 6     6   46 no strict 'refs';
  6         13  
  6         1986  
61 11         69 my $rc = $Test->$comparator( $self->$getter, $str, $name );
62 11 50 66     14280 if (!$rc && $self->error_callback) {
63 0         0 &{$self->error_callback}( $name, $self );
  0         0  
64             }
65 11         25 return $rc;
66 4         29 };
67             }
68             else {
69             $sub = sub {
70 24     24   51270 my( $self, $locator, $str, $name ) = @_;
71 24 50       261 diag "Test::WWW::Selenium running $getter (@_[1..$#_])"
72             if $self->{verbose};
73 24 50 33     1555 $name = "$getter, $locator, '$str'"
74             if $self->{default_names} and !defined $name;
75 6     6   219 no strict 'refs';
  6         10  
  6         5360  
76 24         148 my $rc = $Test->$comparator( $self->$getter($locator), $str, $name );
77 24 100 100     51072 if (!$rc && $self->error_callback) {
78 4         10 &{$self->error_callback}( $name, $self );
  4         46  
79             }
80 24         317 return $rc;
81 4         39 };
82             }
83             }
84             elsif ($name =~ /(\w+?)_?ok$/i) {
85 2         7 my $cmd = $1;
86              
87             # make a subroutine for ok() around the selenium command
88             $sub = sub {
89 6     6   1628 my( $self, $arg1, $arg2, $name ) = @_;
90 6 100 100     55 if ($self->{default_names} and !defined $name) {
91 4         8 $name = $cmd;
92 4 100       10 $name .= ", $arg1" if defined $arg1;
93 4 100       16 $name .= ", $arg2" if defined $arg2;
94             }
95 6 50       19 diag "Test::WWW::Selenium running $cmd (@_[1..$#_])"
96             if $self->{verbose};
97              
98 6         9 local $Test::Builder::Level = $Test::Builder::Level + 1;
99 6         11 my $rc = '';
100 6         8 eval { $rc = $self->$cmd( $arg1, $arg2 ) };
  6         42  
101 6 100 100     42 die $@ if $@ and $@ =~ /Can't locate object method/;
102 5 100       572 diag($@) if $@;
103 5         150 $rc = ok( $rc, $name );
104 5 50 66     2034 if (!$rc && $self->error_callback) {
105 0         0 &{$self->error_callback}( $name, $self );
  0         0  
106             }
107 5         18 return $rc;
108 2         18 };
109             }
110              
111             # jump directly to the new subroutine, avoiding an extra frame stack
112 11 100       310 if ($sub) {
113 6     6   43 no strict 'refs';
  6         14  
  6         4284  
114 10         22 *{$AUTOLOAD} = $sub;
  10         419  
115 10         53 goto &$AUTOLOAD;
116             }
117             else {
118             # try to pass through to WWW::Selenium
119 1         3 my $sel = 'WWW::Selenium';
120 1         18 my $sub = "${sel}::${name}";
121 1 50       5 goto &$sub if exists &$sub;
122 1         5 my ($package, $filename, $line) = caller;
123 1         62 die qq(Can't locate object method "$name" via package ")
124             . __PACKAGE__
125             . qq(" (also tried "$sel") at $filename line $line\n);
126             }
127             }
128              
129             sub new {
130 15     15 1 6567 my ($class, %opts) = @_;
131 15 100       71 my $default_names = defined $opts{default_names} ?
132             delete $opts{default_names} : 1;
133 15 100       59 my $error_callback = defined $opts{error_callback} ?
134             delete $opts{error_callback} : undef;
135 15         117 my $self = $class->SUPER::new(%opts);
136 15         44 $self->{default_names} = $default_names;
137 15         38 $self->{error_callback} = $error_callback;
138 15         62 $self->start;
139 15         53 return $self;
140             }
141              
142             sub error_callback {
143 22     22 1 57 my ($self, $cb) = @_;
144 22 50       168 if (defined($cb)) {
145 0         0 $self->{error_callback} = $cb;
146             }
147 22         133 return $self->{error_callback};
148             }
149              
150              
151             sub debug {
152 0     0 1   my $self = shift;
153 0           require Devel::REPL;
154 0           my $repl = Devel::REPL->new(prompt => 'Selenium$ ');
155 0           $repl->load_plugin($_) for qw/History LexEnv Colors Selenium Interrupt/;
156 0           $repl->selenium($self);
157 0           $repl->lexical_environment->do($repl->selenium_lex_env);
158 0           $repl->run;
159             }
160              
161             1;
162              
163             __END__