WebElement.pm 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. package Test::Selenium::Remote::WebElement;
  2. use parent 'Selenium::Remote::WebElement';
  3. use Test::More;
  4. use Test::Builder;
  5. our $AUTOLOAD;
  6. our $Test = Test::Builder->new;
  7. $Test->exported_to(__PACKAGE__);
  8. our %comparator = (
  9. is => 'is_eq',
  10. isnt => 'isnt_eq',
  11. like => 'like',
  12. unlike => 'unlike',
  13. );
  14. our %one_arg = map { $_ => 1 } qw(
  15. get_attribute
  16. send_keys
  17. );
  18. sub one_arg {
  19. my $self = shift;
  20. my $method = shift;
  21. return $one_arg{$method};
  22. }
  23. our %no_arg = map { $_ => 1 } qw(
  24. clear
  25. click
  26. get_text
  27. get_value
  28. get_tag_name
  29. is_enabled
  30. is_selected
  31. submit
  32. );
  33. sub no_arg {
  34. my $self = shift;
  35. my $method = shift;
  36. return $no_arg{$method};
  37. }
  38. our %no_return = map { $_ => 1 } qw(send_keys click clear submit);
  39. sub no_return {
  40. my $self = shift;
  41. my $method = shift;
  42. return $no_return{$method};
  43. }
  44. sub AUTOLOAD {
  45. my $name = $AUTOLOAD;
  46. $name =~ s/.*:://;
  47. return if $name eq 'DESTROY';
  48. my $self = $_[0];
  49. my $sub;
  50. if ($name =~ /(\w+)_(is|isnt|like|unlike)$/i) {
  51. my $getter = "get_$1";
  52. my $comparator = $comparator{lc $2};
  53. $sub = sub {
  54. my( $self, $str, $name ) = @_;
  55. # There is no verbose option currently
  56. #diag "Test::Selenium::Remote::WebElement running $getter (@_[1..$#_])" if $self->{verbose};
  57. $name = "$getter, '$str'" if !defined $name;
  58. no strict 'refs';
  59. return $Test->$comparator( $self->$getter, $str, $name );
  60. };
  61. }
  62. elsif ($name =~ /(\w+?)_?ok$/i) {
  63. my $cmd = $1;
  64. # make a subroutine for ok() around the selenium command
  65. $sub = sub {
  66. my( $self, $arg1, $arg2, $name );
  67. $self = $_[0];
  68. if ($self->no_arg($cmd)) {
  69. $name = $_[1];
  70. }
  71. elsif ($self->one_arg($cmd)) {
  72. $arg1 = $_[1];
  73. $name = $_[2];
  74. }
  75. else {
  76. $arg1 = $_[1];
  77. $arg2 = $_[2];
  78. $name = $_[3];
  79. }
  80. if (!defined $name) {
  81. $name = $cmd;
  82. $name .= ", $arg1" if defined $arg1;
  83. $name .= ", $arg2" if defined $arg2;
  84. }
  85. # There is no verbose option currently
  86. # diag "Test::Selenium::Remote::WebElement running $cmd (@_[1..$#_])" if $self->{verbose};
  87. local $Test::Builder::Level = $Test::Builder::Level + 1;
  88. my $rc = '';
  89. eval {
  90. if ($self->no_arg($cmd)) {
  91. $rc = $self->$cmd();
  92. }
  93. elsif ($self->one_arg($cmd)) {
  94. $rc = $self->$cmd( $arg1 );
  95. }
  96. else {
  97. $rc = $self->$cmd( $arg1, $arg2 );
  98. }
  99. };
  100. die $@ if $@ and $@ =~ /Can't locate object method/;
  101. diag($@) if $@;
  102. if ($self->no_return($cmd)) {
  103. $rc = ok( 1, "$name... no return value" );
  104. }
  105. else {
  106. $rc = ok( $rc, $name );
  107. }
  108. return $rc;
  109. };
  110. }
  111. # jump directly to the new subroutine, avoiding an extra frame stack
  112. if ($sub) {
  113. no strict 'refs';
  114. *{$AUTOLOAD} = $sub;
  115. goto &$AUTOLOAD;
  116. }
  117. else {
  118. # try to pass through to Selenium::Remote::WebElement
  119. my $sel = 'Selenium::Remote::WebElement';
  120. my $sub = "${sel}::${name}";
  121. goto &$sub if exists &$sub;
  122. my ($package, $filename, $line) = caller;
  123. 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. 1;
  129. __END__
  130. =head1 NAME
  131. Test::Selenium::Remote::WebElement
  132. =head1 DESCRIPTION
  133. A sub-class of L<Selenium::Remote::WebElement>, with several test-specific method additions.
  134. This is an I<experimental> addition to the Selenium::Remote::Driver
  135. distribution, and some interfaces may change.
  136. =head1 METHODS
  137. All methods from L<Selenium::Remote::WebElement> are available through this
  138. module, as well as the following test-specific methods. All test names are optional.
  139. text_is($match_str,$test_name);
  140. text_isnt($match_str,$test_name);
  141. text_like($match_re,$test_name);
  142. text_unlike($match_re,$test_name);
  143. tag_name_is($match_str,$test_name);
  144. tag_name_isnt($match_str,$test_name);
  145. tag_name_like($match_re,$test_name);
  146. tag_name_unlike($match_re,$test_name);
  147. value_is($match_str,$test_name);
  148. value_isnt($match_str,$test_name);
  149. value_like($match_re,$test_name);
  150. value_unlike($match_re,$test_name);
  151. clear_ok($test_name);
  152. click_ok($test_name);
  153. submit_ok($test_name);
  154. is_selected_ok($test_name);
  155. is_enabled_ok($test_name);
  156. is_displayed_ok($test_name);
  157. send_keys_ok($str)
  158. send_keys_ok($str,$test_name)
  159. attribute_is($attr_name,$match_str,$test_name); # TODO
  160. attribute_isnt($attr_name,$match_str,$test_name); # TODO
  161. attribute_like($attr_name,$match_re,$test_name); # TODO
  162. attribute_unlike($attr_name,$match_re,$test_name); # TODO
  163. css_attribute_is($attr_name,$match_str,$test_name); # TODO
  164. css_attribute_isnt($attr_name,$match_str,$test_name); # TODO
  165. css_attribute_like($attr_name,$match_re,$test_name); # TODO
  166. css_attribute_unlike($attr_name,$match_re,$test_name); # TODO
  167. element_location_is([x,y]) # TODO
  168. element_location_in_view_is([x,y]) # TODO
  169. =head1 AUTHORS
  170. =over 4
  171. =item *
  172. Created by: Mark Stosberg <mark@stosberg.org>, but inspired by
  173. L<Test::WWW::Selenium> and its authors.
  174. =back
  175. =head1 COPYRIGHT AND LICENSE
  176. Copyright (c) 2013 Mark Stosberg
  177. This program is free software; you can redistribute it and/or
  178. modify it under the same terms as Perl itself.