sanity.test 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. use Test2::V0;
  5. #XXX Test2 Knows Better TM
  6. no warnings 'experimental';
  7. use feature qw/signatures/;
  8. use Test::Fatal;
  9. use FindBin;
  10. use Cwd qw{abs_path};
  11. use JSON;
  12. use Data::Dumper;
  13. use Selenium::Client;
  14. # SHUT UP WITH THE WARNINGS
  15. local $Test::Builder::Level = 0;
  16. my $extra = '';
  17. $extra = '/' if grep { $^O eq $_ } qw{msys MSWin32};
  18. my $sut = 'file://' . $extra . abs_path("$FindBin::Bin/test.html");
  19. my $sut2 = 'file://' . $extra . abs_path("$FindBin::Bin/other.html");
  20. #Do WinAppDriver testing if we are on windows and have it installed at all
  21. SKIP: {
  22. skip("Need JSONWire support before we can test winappdriver",1);
  23. my $winapp = eval { Selenium::Client->new( driver => 'WinApp', debug => $ENV{DEBUG} ) };
  24. if ($winapp) {
  25. my $caps = {
  26. app => 'C:\\Windows\\System32\\notepad.exe',
  27. platformName => "WINDOWS",
  28. platform => "WINDOWS",
  29. deviceName => "WindowsPC",
  30. appArguments => "zippy.txt",
  31. appWorkingDir => '.',
  32. "ms:experimental-webdriver" => JSON::true,
  33. };
  34. #XXX the WC3 support is only "sorta" in that they don't support modern caps
  35. my @ret = $winapp->NewSession( desiredCapabilities => $caps );
  36. use Data::Dumper;
  37. print Dumper(\@ret);
  38. my $notepad;
  39. my $input = $notepad->FindElement( using => 'css selector', value => 'Edit' );
  40. $input->ElementSendKeys( text => 'tickle');
  41. is($input->GetElementProperty( name => 'value' ), 'tickle', "Can clear and send keys to a text input");
  42. }
  43. }
  44. my @browsers = qw{firefox chrome};
  45. push(@browsers, 'MicrosoftEdge') if grep { $^O eq $_ } qw{MSWin32 msys};
  46. push(@browsers, 'safari') if $^O eq 'darwin';
  47. foreach my $browser (@browsers) {
  48. my @drivers = qw{Gecko Auto SeleniumHQ::Jar};
  49. @drivers = qw{Chrome Auto SeleniumHQ::Jar} if $browser eq 'chrome';
  50. @drivers = qw{Edge Auto SeleniumHQ::Jar} if $browser eq 'MicrosoftEdge';
  51. @drivers = qw{Safari Auto SeleniumHQ::Jar} if $browser eq 'safari';
  52. foreach my $driver (@drivers) {
  53. subtest "$browser (using $driver): Spec compliance" => sub {
  54. my %options = ( driver => $driver, browser => $browser, debug => $ENV{DEBUG}, headless => !$ENV{NO_HEADLESS} );
  55. # TODO remove when it goes public
  56. $options{driver_version} = '4.0.0-alpha-7' if $driver eq 'SeleniumHQ::Jar';
  57. my $driver = Selenium::Client->new( %options );
  58. my $status = $driver->Status();
  59. ok($status->{ready}, "Driver up and running");
  60. my ($capabilities,$session) = $driver->NewSession();
  61. isa_ok($capabilities,"Selenium::Capabilities");
  62. isa_ok($session, "Selenium::Session");
  63. is( exception { $session->SetTimeouts( script => 1000, implicit => 1000, pageLoad => 1000 ) }, undef, "Can set timeouts");
  64. #XXX GetTimeouts like every other thing *chokes* on data not being *just right* despite spec having undefined behavior here
  65. my $expected = { script => 1000, implicit => 1000, pageLoad => 1000 };
  66. SKIP: {
  67. skip("Selenium 4.0 GetTimeouts is broken, and as we know all broken things HANG 30 SECONDS!!!",1);
  68. my $t = $session->GetTimeouts( script => undef, implicit => undef, pageLoad => undef );
  69. is($t,$expected, "GetTimeouts works");
  70. }
  71. is( exception { $session->NavigateTo( url => $sut ) }, undef, "Can open page");
  72. #Alerts
  73. alertify($session);
  74. is($session->GetCurrentURL(), $sut, "Can get current URL");
  75. is($session->GetTitle(), 'Test Page', "Can get page title");
  76. is(exception { $session->NavigateTo( 'url' => $sut2 ) }, undef, "Can open other page");
  77. is($session->GetPageSource(),"<html><head></head><body>ZIPPY\n</body></html>","Can get page source");
  78. is(exception { $session->Back() }, undef, "Can navigate to the last page visited with back()");
  79. alertify($session) unless $browser eq 'safari' || $browser eq 'firefox';
  80. is(exception { $session->Forward() }, undef, "Can navigate back to previously visited page with forward()");
  81. $session->Back();
  82. #XXX webkit re-issues alerts on back()
  83. alertify($session) if grep { $browser eq $_ } qw{chrome MicrosoftEdge};
  84. is(exception { $session->Refresh() }, undef, "Can refresh the page");
  85. alertify($session);
  86. my $handle = "".$session->GetWindowHandle();
  87. ok($handle,"Can get window handle");
  88. my $link = $session->FindElement( using => 'css selector', value => '#linky' );
  89. $link->ElementClick();
  90. my @newhandles = map { "".$_ } $session->GetWindowHandles();
  91. my ($newhandle) = grep { $_ ne $handle } @newhandles;
  92. die("Could not get existing handle from getwindowhandles") unless $newhandle;
  93. is( exception { $session->SwitchToWindow( handle => $newhandle ) }, undef, "Can switch to new window");
  94. #XXX This fails on firefoxdriver directly for whatever reason
  95. my $src = eval { $session->GetPageSource() } || '';
  96. like($src, qr/ZIPPY/i, "Got right window") if $browser ne 'firefox' || $driver eq 'SeleniumHQ::Jar';
  97. todo "Get page source after back() sometimes fails on firefox direct driver" => sub {
  98. like($src, qr/ZIPPY/i, "Got right window");
  99. } if $browser eq 'firefox' && $driver ne 'SeleniumHQ::Jar';
  100. is( exception { $session->SwitchToWindow( handle => $handle ) }, undef, "Can switch to old window");
  101. like($session->GetPageSource(), qr/Howdy/i, "Switched window correctly");
  102. $session->SwitchToWindow( handle => $newhandle );
  103. is( exception { $session->CloseWindow() }, undef, "CloseWindow closes current window context");
  104. $session->SwitchToWindow( handle => $handle );
  105. #move it around
  106. my %erekt = ( height => 100, width => 500, x => 50, y => 50);
  107. is( exception { $session->SetWindowRect(%erekt) }, undef, "Can set window rect");
  108. my $rekt = $session->GetWindowRect();
  109. SKIP: {
  110. skip("Window rect set is basically never correctly obeyed",1);
  111. is($rekt, \%erekt, "Can get window rect");
  112. }
  113. #Frames
  114. #my $frame = $session->FindElement( using => 'css selector', value => '#frame' );
  115. #is( exception { $session->SwitchToFrame( id => $frame->{elementid} ) }, undef, "Can switch into frame");
  116. #XXX the above actually does not do anything, only switching by window.frames index actually works lol
  117. $session->SwitchToFrame( id => 0 );
  118. # Check that the driver yanno *actually did something*
  119. my $fbody = $session->FindElement( using => 'css selector', value => 'body' );
  120. my $ftext = $fbody->GetElementText();
  121. is($ftext, 'ZIPPY', "Can do things in iframes");
  122. is( exception { $session->SwitchToParentFrame() }, undef, "Can travel up the frame stack");
  123. #Maximize etc
  124. is( exception { $session->MaximizeWindow() }, undef, "Can maximize window");
  125. is( exception { $session->MinimizeWindow() }, undef, "Can minimize window");
  126. is( exception { $session->FullscreenWindow() }, undef, "Can Fullscreen window");
  127. #Element Method Testing
  128. my $element = $session->FindElement( using => 'css selector', value => 'input[name=text]' );
  129. isa_ok($element,'Selenium::Element');
  130. my $prop = $element->GetElementProperty( name => 'title' );
  131. is($prop,'default', "Can get element properties");
  132. my @inputs = $session->FindElements( using => 'css selector', value => 'input' );
  133. is( scalar(@inputs), 5, "Can find multiple elements correctly");
  134. my $finder = $session->FindElement( using => 'css selector', value => 'form' );
  135. my $found = $finder->FindElementFromElement( using => 'css selector', 'value' => 'label' );
  136. is($found->GetElementAttribute( name => 'for' ), 'text', "Can find child properly");
  137. my @radios = $finder->FindElementsFromElement( using => 'css selector', 'value' => 'input[type=radio]' );
  138. is(scalar(@radios), 2, "Can find child elements properly");
  139. my ($unselected, $selected) = @radios;
  140. ok(!$unselected->IsElementSelected(),"IsElementSelected works");
  141. todo "IsElementSelected appears to always return false, lol" => sub {
  142. ok($selected->IsElementSelected(), "IsElementSelected works");
  143. };
  144. my @checked = $session->FindElements( using => 'css selector', value => 'input:checked');
  145. is(scalar(@checked),1,"But we can at least work around that using css :checked pseudoselector");
  146. is(exception { $session->GetActiveElement() }, undef, "Can get active element");
  147. my $invisible = $session->FindElement( using => 'css selector', value => '#no-see-em' );
  148. is($invisible->GetElementCSSValue( propertyname => 'display' ),'none',"Can get CSS values for elements");
  149. is(lc($invisible->GetElementTagName()),'button', "Can get element tag name");
  150. my $hammertime = $session->FindElement( using => 'css selector', value => '#hammertime' );
  151. ok(!$hammertime->IsElementEnabled(),"IsElementEnabled works");
  152. my $clickme = $session->FindElement( using => 'css selector', value => '#clickme' );
  153. is($clickme->GetElementText(),'PARTY HARD', "Can get element text");
  154. my $rkt = $clickme->GetElementRect();
  155. ok(defined $rkt->{x},"GetElementRect appears to function");
  156. my $input = $session->FindElement( using => 'css selector', value => 'input[name=text]' );
  157. $input->ElementClear();
  158. $input->ElementSendKeys( text => "tickle" );
  159. is($input->GetElementProperty( name => 'value' ), 'tickle', "Can clear and send keys to a text input");
  160. is($session->ExecuteScript( script => qq/ return document.querySelector('input').value /, args => [] ),'tickle',"ExecuteScript works");
  161. is($session->ExecuteAsyncScript( script => qq/ return arguments[arguments.length - 1](document.querySelector('input').value) /, args => [] ),'tickle',"ExecuteAsyncScript works");
  162. # Screenshots
  163. ok($session->TakeScreenshot(),"Can take screenshot");
  164. ok($input->TakeElementScreenshot(), "Can take element screenshot");
  165. # Perform / Release Actions
  166. is( exception {
  167. $session->PerformActions( actions => [ { type => 'key', id => 'key', actions => [ { type => 'keyDown', value => 'a' } ] } ] )
  168. }, undef, "Can perform general actions");
  169. is( exception { $session->ReleaseActions() }, undef, "Can release general actions");
  170. is($input->GetElementProperty( name => 'value' ), 'ticklea', "Key sent worked");
  171. # Cookies -- Browsers don't allow cookies for local stuff, so let's do it against CPAN
  172. # XXX lol this site is slow
  173. $session->SetTimeouts( script => 1000, implicit => 1000, pageLoad => 10000 );
  174. $session->NavigateTo( url => 'http://cpan.org' );
  175. $session->AddCookie( cookie => { name => 'tickle', value => 'hug' } );
  176. my @jar = $session->GetAllCookies();
  177. ok(scalar(grep { $_->{name} eq 'tickle' } @jar), "Can set cookies and read them");
  178. ok($session->GetNamedCookie( name => 'tickle' ),"Can GetNamedCookie");
  179. $session->DeleteCookie( name => 'tickle' );
  180. isnt(exception { $session->GetNamedCookie( name => 'tickle') }, undef, "DeleteCookie works");
  181. $session->AddCookie( cookie => { name => 'tickle', value => 'hug' } );
  182. $session->DeleteAllCookies();
  183. isnt( exception { $session->GetNamedCookie( name => 'tickle' ) }, undef, "DeleteAllCookies works");
  184. # is( exception { $session->DeleteSession() }, undef, "Can delete session");
  185. };
  186. }
  187. }
  188. sub alertify ($session) {
  189. is(eval { $session->GetAlertText() } // $@,'BEEE DOOO', "Can get alert text");
  190. is( exception { $session->AcceptAlert() }, undef, "Can dismiss alert");
  191. is(eval { $session->GetAlertText() } // $@,'Are you a fugitive from Justice?', "Can get alert text on subsequent alert");
  192. is( exception { $session->SendAlertText( text => "HORGLE") }, undef,"send_keys_to_prompt works");
  193. is( exception { $session->DismissAlert() }, undef, "Can accept alert");
  194. }
  195. done_testing();