Subclass.pm 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. package Selenium::Subclass;
  2. #ABSTRACT: Generic template for Selenium sugar subclasses like Selenium::Session
  3. use strict;
  4. use warnings;
  5. use v5.28;
  6. no warnings 'experimental';
  7. use feature qw/signatures/;
  8. =head1 CONSTRUCTOR
  9. =head2 $class->new($parent Selenium::Client, $data HASHREF)
  10. You should probably not use this directly; objects should be created as part of normal operation.
  11. =cut
  12. sub new ($class,$parent,$data) {
  13. my %lowkey;
  14. @lowkey{map { lc $_ } keys(%$data)} = values(%$data);
  15. $lowkey{parent} = $parent;
  16. my $self = bless(\%lowkey,$class);
  17. $self->_build_subs($class);
  18. return $self;
  19. }
  20. sub _request ($self, $method, %params) {
  21. #XXX BAD SPEC AUTHOR, BAD!
  22. if ( $self->{sortfield} eq 'element-6066-11e4-a52e-4f735466cecf') {
  23. $self->{sortfield} = 'elementid';
  24. $self->{elementid} = delete $self->{'element-6066-11e4-a52e-4f735466cecf'};
  25. # Ensure element childs don't think they are their parent
  26. $self->{to_inject}{elementid} = $self->{elementid};
  27. }
  28. # Inject our sortField param, and anything else we need to
  29. $params{$self->{sortfield}} = $self->{$self->{sortfield}};
  30. my $inject = $self->{to_inject};
  31. @params{keys(%$inject)} = values(%$inject) if ref $inject eq 'HASH';
  32. # and ensure it is injected into child object requests
  33. # This is primarily to ensure that the session ID trickles down correctly.
  34. # Some also need the element ID to trickle down.
  35. # However, in the case of getting child elements, we wish to specifically prevent that, and do so above.
  36. $params{inject} = $self->{sortfield};
  37. $self->{callback}->($self,$method,%params) if $self->{callback};
  38. return $self->{parent}->_request($method, %params);
  39. }
  40. sub DESTROY($self) {
  41. return if ${^GLOBAL_PHASE} eq 'DESTRUCT';
  42. $self->{destroy_callback}->($self) if $self->{destroy_callback};
  43. }
  44. #TODO filter spec so we don't need parent anymore, and can have a catalog() method
  45. sub _build_subs($self,$class) {
  46. #Filter everything out which doesn't have {sortField} in URI
  47. my $k = lc($self->{sortfield});
  48. #XXX deranged field name
  49. $k = 'elementid' if $self->{sortfield} eq 'element-6066-11e4-a52e-4f735466cecf';
  50. foreach my $sub (keys(%{$self->{parent}{spec}})) {
  51. next unless $self->{parent}{spec}{$sub}{uri} =~ m/{\Q$k\E}/;
  52. Sub::Install::install_sub(
  53. {
  54. code => sub {
  55. my $self = shift;
  56. return $self->_request($sub,@_);
  57. },
  58. as => $sub,
  59. into => $class,
  60. }
  61. ) unless $class->can($sub);
  62. }
  63. }
  64. 1;