WebElement.pm 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  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. # These commands don't require a locator
  15. # grep item lib/WWW/Selenium.pm | grep sel | grep \(\) | grep get
  16. our %no_locator = map { $_ => 1 }
  17. qw( send_keys speed alert confirmation prompt location title
  18. body_text all_buttons all_links all_fields
  19. mouse_speed all_window_ids all_window_names
  20. all_window_titles html_source cookie absolute_location );
  21. sub no_locator {
  22. my $self = shift;
  23. my $method = shift;
  24. return $no_locator{$method};
  25. }
  26. our %one_arg = map { $_ => 1 } qw(send_keys);
  27. sub one_arg {
  28. my $self = shift;
  29. my $method = shift;
  30. return $one_arg{$method};
  31. }
  32. our %no_arg = map { $_ => 1 } qw(click clear);
  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);
  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 = $1;
  52. my $comparator = $comparator{lc $2};
  53. # make a subroutine that will call Test::Builder's test methods
  54. # with selenium data from the getter
  55. if ($self->no_locator($1)) {
  56. $sub = sub {
  57. my( $self, $str, $name ) = @_;
  58. diag "Test::Selenium::Remote::Driver running $getter (@_[1..$#_])"
  59. if $self->{verbose};
  60. $name = "$getter, '$str'"
  61. if $self->{default_names} and !defined $name;
  62. no strict 'refs';
  63. my $rc = $Test->$comparator( $self->$getter, $str, $name );
  64. if (!$rc && $self->error_callback) {
  65. &{$self->error_callback}( $name, $self );
  66. }
  67. return $rc;
  68. };
  69. }
  70. else {
  71. $sub = sub {
  72. my( $self, $locator, $str, $name ) = @_;
  73. diag "Test::Selenium::Remote::Driver running $getter (@_[1..$#_])"
  74. if $self->{verbose};
  75. $name = "$getter, $locator, '$str'"
  76. if $self->{default_names} and !defined $name;
  77. no strict 'refs';
  78. my $rc = $Test->$comparator( $self->$getter($locator), $str, $name );
  79. if (!$rc && $self->error_callback) {
  80. &{$self->error_callback}( $name, $self );
  81. }
  82. return $rc;
  83. };
  84. }
  85. }
  86. elsif ($name =~ /(\w+?)_?ok$/i) {
  87. my $cmd = $1;
  88. # make a subroutine for ok() around the selenium command
  89. $sub = sub {
  90. my( $self, $arg1, $arg2, $name );
  91. $self = $_[0];
  92. if ($self->no_arg($cmd)) {
  93. $name = $_[1];
  94. }
  95. elsif ($self->one_arg($cmd)) {
  96. $arg1 = $_[1];
  97. $name = $_[2];
  98. }
  99. else {
  100. $arg1 = $_[1];
  101. $arg2 = $_[2];
  102. $name = $_[3];
  103. }
  104. if ($self->{default_names} and !defined $name) {
  105. $name = $cmd;
  106. $name .= ", $arg1" if defined $arg1;
  107. $name .= ", $arg2" if defined $arg2;
  108. }
  109. diag "Test::Selenium::Remote::Driver running $cmd (@_[1..$#_])"
  110. if $self->{verbose};
  111. local $Test::Builder::Level = $Test::Builder::Level + 1;
  112. my $rc = '';
  113. eval {
  114. if ($self->no_arg($cmd)) {
  115. $rc = $self->$cmd();
  116. }
  117. elsif ($self->one_arg($cmd)) {
  118. $rc = $self->$cmd( $arg1 );
  119. }
  120. else {
  121. $rc = $self->$cmd( $arg1, $arg2 );
  122. }
  123. };
  124. die $@ if $@ and $@ =~ /Can't locate object method/;
  125. diag($@) if $@;
  126. if ($self->no_return($cmd)) {
  127. $rc = ok( 1, "$name... no return value" );
  128. }
  129. else {
  130. $rc = ok( $rc, $name );
  131. }
  132. if (!$rc && $self->error_callback) {
  133. &{$self->error_callback}( $name, $self );
  134. }
  135. return $rc;
  136. };
  137. }
  138. # jump directly to the new subroutine, avoiding an extra frame stack
  139. if ($sub) {
  140. no strict 'refs';
  141. *{$AUTOLOAD} = $sub;
  142. goto &$AUTOLOAD;
  143. }
  144. else {
  145. # try to pass through to Selenium::Remote::Driver
  146. my $sel = 'Selenium::Remote::Driver';
  147. my $sub = "${sel}::${name}";
  148. goto &$sub if exists &$sub;
  149. my ($package, $filename, $line) = caller;
  150. die qq(Can't locate object method "$name" via package ")
  151. . __PACKAGE__
  152. . qq(" (also tried "$sel") at $filename line $line\n);
  153. }
  154. }
  155. sub error_callback {
  156. my ($self, $cb) = @_;
  157. if (defined($cb)) {
  158. $self->{error_callback} = $cb;
  159. }
  160. return $self->{error_callback};
  161. }
  162. sub value_is_ok {
  163. my $self = shift;
  164. my $txt_compare = shift;
  165. my $desc = shift;
  166. return(is($self->get_value(), $txt_compare, $desc));
  167. }
  168. sub type_ok {
  169. my $e = shift;
  170. my $text = shift;
  171. my $desc = shift;
  172. $e->send_keys_ok($text, $desc);
  173. $e->value_is_ok($text, $desc);
  174. }
  175. 1;