File Coverage

blib/lib/Test/Selenium/Remote/Role/DoesTesting.pm
Criterion Covered Total %
statement 85 92 92.3
branch 25 28 89.2
condition 2 3 66.6
subroutine 16 18 88.8
pod n/a
total 128 141 90.7


line stmt bran cond sub pod time code
1             package Test::Selenium::Remote::Role::DoesTesting;
2             $Test::Selenium::Remote::Role::DoesTesting::VERSION = '1.47';
3             # ABSTRACT: Role to cope with everything that is related to testing (could
4             # be reused in both testing classes)
5              
6 7     7   34532 use Moo::Role;
  7         18  
  7         37  
7 7     7   2744 use Test::Builder;
  7         47592  
  7         253  
8 7     7   1300 use Try::Tiny;
  7         3454  
  7         393  
9 7     7   47 use Scalar::Util 'blessed';
  7         14  
  7         289  
10 7     7   36 use List::Util qw/any/;
  7         15  
  7         563  
11 7     7   2008 use namespace::clean;
  7         41262  
  7         40  
12              
13             requires qw(func_list has_args);
14              
15             has _builder => (
16             is => 'lazy',
17 18     18   441 builder => sub { return Test::Builder->new() },
18             handles => [qw/is_eq isnt_eq like unlike ok croak/],
19             );
20              
21             # get back the key value from an already coerced finder (default finder)
22              
23             sub _get_finder_key {
24 9     9   61 my $self = shift;
25 9         14 my $finder_value = shift;
26              
27 9         13 foreach my $k ( keys %{ $self->FINDERS } ) {
  9         35  
28 13 100       53 return $k if ( $self->FINDERS->{$k} eq $finder_value );
29             }
30              
31 0         0 return;
32             }
33              
34             # main method for non ok tests
35              
36             sub _check_method {
37 28     28   47 my $self = shift;
38 28         44 my $method = shift;
39 28         44 my $method_to_test = shift;
40 28         52 $method = "get_$method";
41 28         71 my @args = @_;
42 28         33 my $rv;
43             try {
44 28     28   1109 my $num_of_args = $self->has_args($method);
45 28         65 my @r_args = splice( @args, 0, $num_of_args );
46 28         154 $rv = $self->$method(@r_args);
47             }
48             catch {
49 0     0   0 $self->croak($_);
50 28         175 };
51              
52 28         742 return $self->$method_to_test( $rv, @args );
53             }
54              
55             # main method for _ok tests
56             # a bit hacked so that find_no_element_ok can also be processed
57              
58             sub _check_ok {
59 31     31   51 my $self = shift;
60 31         47 my $method = shift;
61              
62 31         71 my @args = @_;
63 31         52 my ( $rv, $num_of_args, @r_args );
64             try {
65 31     31   1251 $num_of_args = $self->has_args($method);
66 31         76 @r_args = splice( @args, 0, $num_of_args );
67 31 100       152 if ( $method =~ m/^find(_no|_child)?_element/ ) {
68              
69             # case find_element_ok was called with no arguments
70 10 50       25 if ( scalar(@r_args) - $num_of_args == 1 ) {
71 0         0 push @r_args, $self->_get_finder_key( $self->default_finder );
72             }
73             else {
74 10 100       19 if ( scalar(@r_args) == $num_of_args ) {
75              
76             # case find_element was called with no finder but
77             # a test description
78 8         10 my $finder = $r_args[ $num_of_args - 1 ];
79 8         14 my @FINDERS = keys( %{ $self->FINDERS } );
  8         32  
80 8 100       41 unless ( any { $finder eq $_ } @FINDERS ) {
  47         74  
81 4         78 $r_args[ $num_of_args - 1 ] =
82             $self->_get_finder_key( $self->default_finder );
83 4         9 push @args, $finder;
84             }
85             }
86             }
87             }
88              
89             # quick hack to fit 'find_no_element' into check_ok logic
90 31 100       82 if ( $method eq 'find_no_element' ) {
91             # If we use `find_element` and find nothing, the error
92             # handler is incorrectly invoked. Doing a `find_elements`
93             # and checking that it returns an empty array does not
94             # invoke the error_handler. See
95             # https://github.com/gempesaw/Selenium-Remote-Driver/issues/253
96 3         9 my $elements = $self->find_elements(@r_args);
97 1 50       2 if ( @{$elements} ) {
  1         3  
98 1         3 $rv = $elements->[0];
99             }
100             else {
101 0         0 $rv = 1; # empty list means success
102             }
103             }
104             else {
105 28         202 $rv = $self->$method(@r_args); # a true $rv means success
106             }
107             }
108             catch {
109 4 100   4   50 if ($method eq 'find_no_element') {
110 2         6 $rv = 1; # an exception from find_elements() means success
111             }
112             else {
113 2         41 $self->croak($_);
114             }
115 31         213 };
116              
117             # test description might have been explicitly passed
118 29         501 my $test_name = pop @args;
119              
120             # generic test description when no explicit test description was passed
121 29 100       73 if ( ! defined $test_name ) {
122             $test_name = $num_of_args > 0 ?
123 15 100       49 join( ' ', $method, map { q{'$_'} } @r_args )
  10         37  
124             :
125             $method;
126             }
127              
128             # case when find_no_element found an element, we should croak
129 29 100       69 if ( $method eq 'find_no_element' ) {
130 3 100 66     18 if ( blessed($rv) && $rv->isa('Selenium::Remote::WebElement') ) {
131 1         17 $self->croak($test_name);
132             }
133             }
134              
135 28         505 return $self->ok( $rv, $test_name );
136             }
137              
138             # build the subs with the correct arg set
139              
140             sub _build_sub {
141 381     381   527 my $self = shift;
142 381         476 my $meth_name = shift;
143              
144             # e.g. for $meth_name = 'find_no_element_ok':
145             # $meth_comp = 'ok'
146             # $meth_without_comp = 'find_no_element'
147 381         884 my @meth_elements = split '_', $meth_name;
148 381         599 my $meth_comp = pop @meth_elements;
149 381         809 my $meth_without_comp = join '_', @meth_elements;
150              
151             # handle the ok testing methods
152 381 100       663 if ( $meth_comp eq 'ok' ) {
153             return sub {
154 31     31   8333 my $self = shift;
155              
156 31         64 local $Test::Builder::Level = $Test::Builder::Level + 2;
157              
158 31         97 return $self->_check_ok($meth_without_comp, @_);
159 135         516 };
160             }
161              
162             # find the Test::More comparator method
163 246         615 my %comparators = (
164             is => 'is_eq',
165             isnt => 'isnt_eq',
166             like => 'like',
167             unlike => 'unlike',
168             );
169              
170             # croak on unknown comparator methods
171 246 50       458 if ( ! exists $comparators{$meth_comp} ) {
172             return sub {
173 0     0   0 my $self = shift;
174              
175 0         0 return $self->croak("Sub $meth_name could not be defined");
176 0         0 };
177             }
178              
179             # handle check in _check_method()
180             return sub {
181 28     28   11333 my $self = shift;
182              
183 28         56 local $Test::Builder::Level = $Test::Builder::Level + 2;
184              
185 28         81 return $self->_check_method( $meth_without_comp, $comparators{$meth_comp}, @_ );
186 246         913 };
187             }
188              
189             1;
190              
191             =head1 NAME
192              
193             Selenium::Remote::Role::DoesTesting - Role implementing the common logic used for testing
194              
195             =cut