01-webdriver3.t 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. use strict;
  2. use warnings;
  3. use Test::More;
  4. use Test::Deep;
  5. use Test::Fatal;
  6. use Scalar::Util qw{looks_like_number};
  7. use Selenium::Remote::Driver;
  8. use Selenium::Firefox::Profile;
  9. use Selenium::Remote::Spec;
  10. #So we only modify _request_new_session to get webd3 working.
  11. #As such, we should only test that.
  12. NEWSESS: {
  13. #TODO cover case where ISA Selenium::Firefox
  14. my $self = bless({ is_wd3 => 1 },"Selenium::Remote::Driver");
  15. my $profile = Selenium::Firefox::Profile->new();
  16. $profile->set_preference(
  17. 'browser.startup.homepage' => 'http://www.google.com',
  18. );
  19. my $args = {
  20. desiredCapabilities => {
  21. browserName => 'firefox',
  22. version => 666,
  23. platform => 'ANY',
  24. javascript => 1,
  25. acceptSslCerts => 1,
  26. firefox_profile => $profile,
  27. pageLoadStrategy => 'none',
  28. proxy => {
  29. proxyType => 'direct',
  30. proxyAutoconfigUrl => 'http://localhost',
  31. ftpProxy => 'localhost:1234',
  32. httpProxy => 'localhost:1234',
  33. sslProxy => 'localhost:1234',
  34. socksProxy => 'localhost:1234',
  35. socksVersion => 2,
  36. noProxy => ['http://localhost'],
  37. },
  38. extra_capabilities => { #TODO these need to be translated as moz:firefoxOptions => {} automatically, and then to be put in the main hash
  39. binary => '/usr/bin/firefox',
  40. args => ['-profile', '~/.mozilla/firefox/vbdgri9o.default'], #gotta check this gets overridden
  41. profile => 'some Base64 string of a zip file. I should really make this a feature',
  42. log => 'trace', #trace|debug|config|info|warn|error|fatal
  43. prefs => {}, #TODO check that this is auto-set above by the Selenium::Firefox::Profile stuff
  44. webdriverClick => 0, #This option is OP, *must* be set to false 24/7
  45. },
  46. },
  47. };
  48. no warnings qw{redefine once};
  49. local *Selenium::Remote::RemoteConnection::request = sub {return { sessionId => 'zippy', cmd_status => 'OK', cmd_return => {capabilities => 'eee'} }};
  50. local *File::Temp::Dir::dirname = sub { return '/tmp/zippy' };
  51. use warnings;
  52. my ($args_modified,undef) = $self->_request_new_session($args);
  53. my $expected = {
  54. 'alwaysMatch' => {
  55. 'browserVersion' => 666,
  56. 'moz:firefoxOptions' => {
  57. 'args' => [
  58. '-profile',
  59. '/tmp/zippy'
  60. ],
  61. 'binary' => '/usr/bin/firefox',
  62. 'log' => 'trace',
  63. 'prefs' => {},
  64. 'profile' => 'some Base64 string of a zip file. I should really make this a feature',
  65. 'webdriverClick' => 0
  66. },
  67. 'platformName' => 'ANY',
  68. 'proxy' => {
  69. 'ftpProxy' => 'localhost:1234',
  70. 'httpProxy' => 'localhost:1234',
  71. 'noProxy' => [
  72. 'http://localhost'
  73. ],
  74. 'proxyAutoconfigUrl' => 'http://localhost',
  75. 'proxyType' => 'direct',
  76. 'socksProxy' => 'localhost:1234',
  77. 'socksVersion' => 2,
  78. 'sslProxy' => 'localhost:1234'
  79. },
  80. 'browserName' => 'firefox',
  81. 'pageLoadStrategy' => 'none',
  82. acceptInsecureCerts => 1,
  83. }
  84. };
  85. is($self->{capabilities},'eee',"Caps set correctly in wd3 mode");
  86. is_deeply($args_modified->{capabilities},$expected,"Desired capabilities correctly translated to Firefox (WD3)");
  87. #$expected->{alwaysMatch}->{'goog:chromeOptions'} = $expected->{alwaysMatch}->{'moz:firefoxOptions'};
  88. $expected->{alwaysMatch}->{'moz:firefoxOptions'} = {};
  89. #$expected->{alwaysMatch}->{'goog:chromeOptions'}->{args} = ['-profile', '~/.mozilla/firefox/vbdgri9o.default'];
  90. $expected->{alwaysMatch}->{browserName} = 'chrome';
  91. $args->{desiredCapabilities}->{browserName} = 'chrome';
  92. ($args_modified,undef) = $self->_request_new_session($args);
  93. is_deeply($args_modified->{capabilities},$expected,"Desired capabilities correctly translated to Krom (WD3)");
  94. }
  95. EXECOMMAND: {
  96. #_execute_command with payload 'hitting all the right buttons'
  97. #also check that fallback works w/ the right special missing word
  98. #also check capability shortcut
  99. my $self = bless({ is_wd3 => 1, capabilities => 'wakka wakka', browser_name => 'firefox' },"Selenium::Remote::Driver");
  100. no warnings qw{redefine once};
  101. local *Selenium::Remote::RemoteConnection::request = sub {return { sessionId => 'zippy', cmd_status => 'OK' }};
  102. local *Selenium::Remote::Spec::get_params = sub { my ($self,$ret) = @_; $ret->{v3} = 1; return $ret; };
  103. local *Selenium::Remote::Commands::get_params = sub { die 'whee' };
  104. local *Selenium::Remote::Spec::parse_response = sub { my ($self,undef,$ret) = @_; $ret->{rv3} = 1; return $ret; };
  105. local *Selenium::Remote::Commands::parse_response = sub { die 'zippy' };
  106. use warnings;
  107. my ($input,$params) = ({ command => 'zippy'},{ ms => 1, type=> 1, text => 1, value => 1, using => 1});
  108. my $ret = $self->_execute_command($input,$params);
  109. is($ret->{rv3},1,"v3 code walked in _execute_command on happy path");
  110. $input->{command} = 'getCapabilities';
  111. $ret = $self->_execute_command($input,$params);
  112. is($ret,'wakka wakka',"v3 code walked in _execute_command on getCapabilities path");
  113. $input->{command} = 'HORGLE';
  114. no warnings qw{redefine once};
  115. local *Selenium::Remote::Spec::get_params = sub { return undef; };
  116. local *Selenium::Remote::Commands::get_params = sub { die 'whee' };
  117. local *Selenium::Remote::Spec::parse_response = sub { my ($self,undef,$ret) = @_; $ret->{rv3} = 1; return $ret; };
  118. local *Selenium::Remote::Commands::parse_response = sub { die 'zippy' };
  119. use warnings;
  120. $ret = exception { $self->_execute_command($input,$params) };
  121. like($ret,qr/whee/,"v2 fallback walked in _execute_command on getCapabilities path");
  122. }
  123. REMOTECONN: {
  124. my $self = bless({},'Selenium::Remote::RemoteConnection');
  125. $self->remote_server_addr('eee');
  126. $self->port(666);
  127. no warnings qw{redefine once};
  128. local *LWP::UserAgent::request = sub { my ($self,$req) = @_; return $req };
  129. use warnings;
  130. my $res = $self->request({ payload => { zippy => 1}, url => 'grid', method => 'eee' },{},1);
  131. is($res->content,'{"zippy":1}',"RemoteConnection payload shim works");
  132. }
  133. #get_cmds, get_params, parse_response
  134. #get_caps and get_caps map have already been checked above in the _request_new_session code
  135. SPEC: {
  136. my $obj = Selenium::Remote::Spec->new();
  137. my $cmds = $obj->get_cmds();
  138. subtest "parsing of spec blob done correctly" => sub {
  139. foreach my $key (keys(%$cmds)) {
  140. like($cmds->{$key}->{url},qr/^session|status/,"url parsed for $key correctly");
  141. is($cmds->{$key}->{url},$obj->get_url($key),"get_url accessor works for $key");
  142. like($cmds->{$key}->{method},qr/^GET|POST|DELETE|PUT$/,"method parsed for $key correctly");
  143. is($cmds->{$key}->{method},$obj->get_method($key),"get_method accessor works for $key");
  144. ok($cmds->{$key}->{description},"description parsed for $key correctly");
  145. ok(looks_like_number($cmds->{$key}->{no_content_success}),"no_content_success parsed for $key correctly");
  146. is($cmds->{$key}->{no_content_success},$obj->get_no_content_success($key),"get_no_content_success accessor works for $key");
  147. }
  148. };
  149. }
  150. SPEC_PARAMS: {
  151. no warnings qw{redefine once};
  152. local *Selenium::Remote::Spec::get_url = sub { return ':sessionId/:id/:name/:propertyName/:other/:windowHandle/timeouts' };
  153. use warnings;
  154. my $obj = Selenium::Remote::Spec->new();
  155. my $args = {
  156. session_id => 'a',
  157. id => 'man',
  158. name => 'a',
  159. property_name => 'plan',
  160. other => 'a canal',
  161. window_handle => 'panama',
  162. command => 'fullscreenWindow',
  163. ms => 666,
  164. type => 'page load',
  165. using => 'id',
  166. value => 'whee',
  167. text => 'zippy',
  168. };
  169. my $expected = {
  170. 'method' => 'POST',
  171. 'no_content_success' => 1,
  172. 'url' => 'a/man/a/plan/a canal/panama/timeouts',
  173. 'payload' => {
  174. 'handle' => 'panama',
  175. 'pageLoad' => 666,
  176. 'using' => 'css selector',
  177. 'value' => 'zippy',
  178. },
  179. };
  180. is_deeply($obj->get_params($args),$expected,"get_params: var substitution works, payload construction works (mostly)");
  181. $args->{type} = 'implicit';
  182. $expected->{payload}{implicit} = 666;
  183. delete $expected->{payload}{pageLoad};
  184. is_deeply($obj->get_params($args),$expected,"get_params: timeout payload mongling (implicit) works");
  185. $args->{type} = 'script';
  186. $expected->{payload}{script} = 666;
  187. delete $expected->{payload}{implicit};
  188. is_deeply($obj->get_params($args),$expected,"get_params: timeout payload mongling (script) works");
  189. no warnings qw{redefine once};
  190. local *Selenium::Remote::Spec::get_url = sub { return ':sessionId/:id/:name/:propertyName/:other/:windowHandle/timeouts/async_script' };
  191. use warnings;
  192. $args->{type} = 'page load';
  193. delete $expected->{payload}{pageLoad};
  194. $expected->{payload}{script} = 666;
  195. $expected->{payload}{type} = 'script';
  196. is_deeply($obj->get_params($args),$expected,"get_params: async_script substitution works");
  197. no warnings qw{redefine once};
  198. local *Selenium::Remote::Spec::get_url = sub { return ':sessionId/:id/:name/:propertyName/:other/:windowHandle/timeouts/implicit_wait' };
  199. use warnings;
  200. delete $expected->{payload}{script};
  201. $expected->{payload}{implicit} = 666;
  202. $expected->{payload}{type} = 'implicit';
  203. is_deeply($obj->get_params($args),$expected,"get_params: implicit_wait substitution works");
  204. delete $args->{text};
  205. $expected->{payload}{value} = "[id='whee']";
  206. is_deeply($obj->get_params($args),$expected,"get_params: id css substitution works");
  207. $args->{using} = 'class name';
  208. $expected->{payload}{value} = ".whee";
  209. is_deeply($obj->get_params($args),$expected,"get_params: class name css substitution works");
  210. $args->{using} = 'name';
  211. $expected->{payload}{value} = "[name='whee']";
  212. is_deeply($obj->get_params($args),$expected,"get_params: name css substitution works");
  213. }
  214. PARSE_RESP: {
  215. my $obj = Selenium::Remote::Spec->new();
  216. my $expected = { error => 'ID10T', 'message' => 'Please insert another quarter'};
  217. my $args = {
  218. cmd_status => 'OK',
  219. cmd_return => $expected,
  220. };
  221. is_deeply($obj->parse_response(undef,$args),$expected,"parse_response works");
  222. $args->{cmd_status} = 'NOT OK';
  223. like(exception { $obj->parse_response(undef,$args) },qr/insert another quarter/i,"parse_response throws on failure");
  224. }
  225. done_testing();