1
0

MockSeleniumWebDriver.pm 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. package t::lib::MockSeleniumWebDriver;
  2. use strict;
  3. use warnings;
  4. use LWP::Protocol::PSGI 0.04;
  5. use JSON;
  6. our $MockSeleniumWebDriverObj;
  7. sub save_recording {
  8. my ($self) = @_;
  9. open(my $fh, '>', $self->{file});
  10. print $fh encode_json($self->{req_resp});
  11. close $fh;
  12. }
  13. sub load_recording {
  14. my ($self) = @_;
  15. open(my $fh, '<', $self->{file});
  16. my @lines = <$fh>;
  17. $self->{req_resp} = decode_json(join('', @lines));
  18. close $fh;
  19. }
  20. sub register {
  21. my $record = shift;
  22. $record = 0 if !defined $record;
  23. my $file = shift;
  24. my $self = {record => $record,
  25. req_index => 0,
  26. file => $file};
  27. bless $self,__PACKAGE__;
  28. if ($record) {
  29. require LWP::UserAgent;
  30. require HTTP::Headers;
  31. require HTTP::Request;
  32. $self->{req_resp} = [];
  33. } else {
  34. $self->load_recording;
  35. }
  36. LWP::Protocol::PSGI->register(\&t::lib::MockSeleniumWebDriver::psgi_app);
  37. $MockSeleniumWebDriverObj = $self;
  38. }
  39. sub psgi_app {
  40. my $env = shift;
  41. my $self = $MockSeleniumWebDriverObj;
  42. my $uri =
  43. $env->{'psgi.url_scheme'} . '://'
  44. . $env->{SERVER_NAME} . ':'
  45. . $env->{SERVER_PORT}
  46. . $env->{REQUEST_URI};
  47. my $content = '';
  48. my $s;
  49. while (read($env->{'psgi.input'}, $s, 100)) {
  50. $content .= $s;
  51. }
  52. my $req_index = \$self->{req_index};
  53. if (!$self->{record}) {
  54. my $expected = $self->{req_resp}->[$$req_index]->{request}->{content};
  55. $expected = $expected eq "" ? $expected : decode_json($expected);
  56. my $actual = $content eq "" ? $content : decode_json($content);
  57. # ugly hack because the profile is encoded differently every time.
  58. if ($actual ne "" && defined $actual->{desiredCapabilities}->{firefox_profile}) {
  59. $expected->{desiredCapabilities}->{firefox_profile} = $actual->{desiredCapabilities}->{firefox_profile};
  60. }
  61. if ( $self->{req_resp}->[$$req_index]->{request}->{verb} eq $env->{REQUEST_METHOD}
  62. and $self->{req_resp}->[$$req_index]->{request}->{uri} eq $uri
  63. and ( $self->{req_resp}->[$$req_index]->{request}->{content} eq $content
  64. or deeply_equal($expected, $actual))) {
  65. return $self->{req_resp}->[$$req_index++]->{response};
  66. } else {
  67. die
  68. "Request information has changed since recording... do you need to record webdriver responses again?";
  69. }
  70. } else {
  71. my $ua = LWP::UserAgent->new;
  72. my $h = HTTP::Headers->new;
  73. $h->header('Content-Type' => $env->{CONTENT_TYPE});
  74. $h->header('Accept' => $env->{HTTP_ACCEPT});
  75. my $req = HTTP::Request->new($env->{REQUEST_METHOD}, $uri, $h, $content);
  76. LWP::Protocol::PSGI->unregister;
  77. my $res = $ua->request($req);
  78. LWP::Protocol::PSGI->register(\&psgi_app);
  79. my $head = $res->{_headers}->clone;
  80. my $newhead = [];
  81. for my $key (keys %{$head}) {
  82. push @{$newhead}, $key;
  83. push @{$newhead}, $head->{$key};
  84. }
  85. my $response = [$res->code, $newhead, [$res->content]];
  86. my $request = {
  87. verb => $env->{REQUEST_METHOD},
  88. uri => $uri,
  89. content => $content
  90. };
  91. push @{$self->{req_resp}}, {request => $request, response => $response};
  92. return $response;
  93. }
  94. }
  95. sub deeply_equal {
  96. my ( $a_ref, $b_ref ) = @_;
  97. local $Storable::canonical = 1;
  98. return Storable::freeze( $a_ref ) eq Storable::freeze( $b_ref );
  99. }
  100. sub DESTROY {
  101. my ($self) = @_;
  102. if($self->{record}) {
  103. $self->save_recording;
  104. }
  105. }
  106. 1;