WebElement.pm 5.4 KB

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