├── .gitignore ├── .mailmap ├── .travis.yml ├── Changes ├── INSTALL.md ├── MANIFEST.SKIP ├── README.md ├── TAGS ├── at ├── Waiter.t ├── chrome.test ├── edge.test ├── firefox.test ├── legacy.test ├── other.html ├── sanity-chrome.test ├── sanity-edge.test ├── sanity-ie.test ├── sanity-safari.test ├── sanity.test ├── test-firefox.test └── test.html ├── cpanfile ├── dist.ini ├── driver-example.pl ├── lib ├── Selenium │ ├── ActionChains.pm │ ├── CanStartBinary.pm │ ├── CanStartBinary │ │ ├── FindBinary.pm │ │ └── ProbePort.pm │ ├── Chrome.pm │ ├── Edge.pm │ ├── Firefox.pm │ ├── Firefox │ │ ├── Binary.pm │ │ ├── Profile.pm │ │ └── webdriver.xpi │ ├── InternetExplorer.pm │ ├── PhantomJS.pm │ ├── Remote │ │ ├── Commands.pm │ │ ├── Driver.pm │ │ ├── Driver │ │ │ ├── CanSetWebdriverContext.pm │ │ │ └── Firefox │ │ │ │ └── Profile.pm │ │ ├── ErrorHandler.pm │ │ ├── Finders.pm │ │ ├── Mock │ │ │ ├── Commands.pm │ │ │ └── RemoteConnection.pm │ │ ├── RemoteConnection.pm │ │ ├── Spec.pm │ │ ├── WDKeys.pm │ │ └── WebElement.pm │ └── Waiter.pm └── Test │ └── Selenium │ ├── Chrome.pm │ ├── Edge.pm │ ├── Firefox.pm │ ├── InternetExplorer.pm │ ├── PhantomJS.pm │ └── Remote │ ├── Driver.pm │ ├── Role │ └── DoesTesting.pm │ └── WebElement.pm ├── perlcriticrc ├── t ├── 00-load.t ├── 01-driver-pac.t ├── 01-driver.t ├── 01-webdriver3.t ├── 02-webelement.t ├── 03-spec-coverage.t ├── 04-commands-implemented.t ├── 10-switch-to-window.t ├── 12-reuse-session.t ├── 13-waiter.t ├── CanSetWebdriverContext.t ├── Finders.t ├── Firefox-Profile.t ├── Remote-Connection.t ├── Test-Selenium-Remote-Driver-google.t ├── Test-Selenium-Remote-Driver.t ├── Test-Selenium-Remote-WebElement.t ├── bin │ ├── docker-record-linux │ └── record.pl ├── convenience.t ├── error.t ├── http-server.pl ├── lib │ └── TestHarness.pm ├── mock-recordings │ ├── 01-driver-mock.json │ ├── 02-webelement-mock.json │ ├── 10-switch-to-window-mock.json │ ├── 12-reuse-session-mock.json │ ├── convenience-mock-darwin.json │ ├── convenience-mock.json │ ├── finders-mock.json │ ├── firefox-profile-mock.json │ └── test-selenium-remote-driver-google-mock.json ├── uploadTest └── www │ ├── 404.html │ ├── alerts.html │ ├── cookies.html │ ├── dragAndDropTest.html │ ├── encoded_profile.b64 │ ├── formPage.html │ ├── frameset.html │ ├── icon.gif │ ├── iframes.html │ ├── index.html │ ├── invalid-extension.xpi │ ├── javascriptPage.html │ ├── metakeys.html │ ├── nestedElements.html │ ├── popup.html │ ├── redisplay.xpi │ └── xhtmlTest.html ├── tidyall.ini └── weaver.ini /.gitignore: -------------------------------------------------------------------------------- 1 | META.yml 2 | MYMETA.yml 3 | Makefile* 4 | blib 5 | pm_to_blib 6 | cover_db 7 | *.komodo* 8 | *.sublime* 9 | .build 10 | Selenium-Remote-Driver-* 11 | selenium*.jar 12 | .prove 13 | _prove 14 | #vim swapfiles 15 | *.swo 16 | *.swp 17 | *.bak 18 | -------------------------------------------------------------------------------- /.mailmap: -------------------------------------------------------------------------------- 1 | Aditya Ivaturi 2 | Charles Howes 3 | Charles Howes 4 | Daniel Gempesaw 5 | Daniel Gempesaw 6 | Daniel Gempesaw 7 | Emmanuel Peroumalnaïk 8 | Emmanuel Peroumalnaïk 9 | Emmanuel Peroumalnaïk 10 | Gordon Child 11 | Gordon Child 12 | Mark Stosberg 13 | Bas Bloemsaat 14 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: perl 3 | perl: 4 | - '5.28' 5 | - '5.26' 6 | - '5.24' 7 | - '5.22' 8 | - '5.20' 9 | matrix: 10 | fast_finish: true 11 | include: 12 | - perl: '5.30' 13 | env: COVERAGE=1 14 | before_install: 15 | - git config --global user.name "TravisCI" 16 | - git config --global user.email $HOSTNAME":not-for-mail@travis-ci.org" 17 | - git clone git://github.com/travis-perl/helpers ~/travis-perl-helpers 18 | - source ~/travis-perl-helpers/init 19 | - build-perl 20 | - perl -V 21 | install: 22 | - cpan-install --coverage # installs converage prereqs, if enabled 23 | - cpanm --quiet --notest Devel::Cover::Report::Coveralls #send to coveralls 24 | - cpanm --quiet --notest Dist::Zilla::App::Command::cover #make sure we can dzil cover 25 | - cpanm --quiet --notest --skip-satisfied Dist::Zilla #unfortunately, we need a very new (6.0 or better) dzil, so no perl < 5.14 26 | - cpanm --quiet --notest --skip-satisfied Test::Spec WWW::Mechanize Test::WWW::Selenium #Test::Pod::Coverage can be stupid 27 | - "dzil authordeps --missing | grep -vP '[^\\w:]' | xargs -n 5 -P 10 cpanm --quiet --notest" 28 | - "dzil listdeps --author --missing | grep -vP '[^\\w:]' | xargs -n 5 -P 10 cpanm --quiet --notest" 29 | before_script: 30 | - coverage-setup 31 | script: 32 | - AUTHOR_TESTING=1 RELEASE_TESTING=1 dzil cover 33 | - export BUILDDIR=`find .build -name cover_db`; cd `dirname $BUILDDIR` 34 | after_success: 35 | - coverage-report 36 | -------------------------------------------------------------------------------- /INSTALL.md: -------------------------------------------------------------------------------- 1 | ## Installation 2 | 3 | It's probably easiest to use the `cpanm` or `CPAN` commands: 4 | 5 | ```bash 6 | $ cpanm Selenium::Remote::Driver 7 | ``` 8 | 9 | If you want to install from this repository, you have a few options; 10 | see the [installation docs][] for more details. 11 | 12 | [installation docs]: /install.md 13 | 14 | ### With Dist::Zilla 15 | 16 | If you have Dist::Zilla, it's straightforward: 17 | 18 | ```bash 19 | $ dzil listdeps --missing | cpanm 20 | $ dzil install 21 | ``` 22 | 23 | ### Without Dist::Zilla 24 | 25 | We maintain two branches that have `Makefile.PL`: 26 | [`cpan`][cpan-branch] and [`build/master`][bm-branch]. The `cpan` 27 | branch is only updated every time we release to the CPAN, and it is 28 | not kept up to date with master. The `build/master` branch is an 29 | up-to-date copy of the latest changes in master, and will usually 30 | contain changes that have not made it to a CPAN release yet. 31 | 32 | To get either of these, you can use the following, (replacing 33 | "build/master" with "cpan" if desired): 34 | 35 | ```bash 36 | $ cpanm -v git://github.com/gempesaw/Selenium-Remote-Driver.git@build/master 37 | ``` 38 | 39 | Or, without `cpanm` and/or without the `git://` protocol: 40 | 41 | ```bash 42 | $ git clone https://github.com/gempesaw/Selenium-Remote-Driver --branch build/master --single-branch --depth 1 43 | $ cd Selenium-Remote-Driver 44 | $ perl Makefile.PL 45 | ``` 46 | 47 | Note that due to POD::Weaver, the line numbers between these generated 48 | branches and the master branch are unfortunately completely 49 | incompatible. 50 | 51 | [cpan-branch]: https://github.com/gempesaw/Selenium-Remote-Driver/tree/cpan 52 | [bm-branch]: https://github.com/gempesaw/Selenium-Remote-Driver/tree/build/master 53 | 54 | ### Viewing dependencies 55 | 56 | You can also use `cpanm` to help you with dependencies after you've 57 | cloned the repository: 58 | 59 | ```bash 60 | $ cpanm --showdeps . 61 | ``` 62 | -------------------------------------------------------------------------------- /MANIFEST.SKIP: -------------------------------------------------------------------------------- 1 | MANIFEST.SKIP 2 | cover_db/* 3 | .travis.yml 4 | weaver.ini 5 | .git/* 6 | -------------------------------------------------------------------------------- /at/Waiter.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use Test::More; 4 | use Test::Warn; 5 | use Test::Fatal; 6 | use Test::Time; 7 | use Selenium::Waiter; 8 | 9 | SIMPLE_WAIT: { 10 | my $ret; 11 | waits_ok( sub { $ret = wait_until { 1 } }, '<', 2, 'immediately true returns quickly' ); 12 | ok($ret == 1, 'return value for a true wait_until is passed up'); 13 | 14 | waits_ok( sub { $ret = wait_until { 0 } }, '==', 30, 'never true expires the timeout' ); 15 | ok($ret eq '', 'return value for a false wait is an empty string'); 16 | } 17 | 18 | EVENTUALLY: { 19 | my $ret = 0; 20 | waits_ok( sub { wait_until { $ret++ > 2 } }, '>', 2, 'eventually true takes time'); 21 | 22 | $ret = 0; 23 | my %opts = ( interval => 2, timeout => 5 ); 24 | waits_ok( 25 | sub { wait_until { $ret++; 0 } %opts }, '>', 4, 26 | 'timeout is respected' 27 | ); 28 | ok(1 <= $ret && $ret <= 3, 'interval option changes iteration speed'); 29 | } 30 | 31 | EXCEPTIONS: { 32 | my %opts = ( timeout => 2 ); 33 | warning_is { wait_until { die 'caught!' } %opts } 'caught!', 34 | 'exceptions usually only warn once'; 35 | } 36 | 37 | NO_FINALLY_WAIT: { 38 | waits_ok( sub { wait_until { 1 }, interval => 10 }, '<', 1, 39 | 'does not do interval wait on success') 40 | 41 | } 42 | 43 | sub waits_ok { 44 | my ($sub, $cmp, $expected_duration, $test_desc) = @_; 45 | 46 | my $start = time; 47 | $sub->(); 48 | my $elapsed = time - $start; 49 | 50 | cmp_ok($elapsed, $cmp, $expected_duration, $test_desc); 51 | } 52 | 53 | done_testing; 54 | -------------------------------------------------------------------------------- /at/chrome.test: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Selenium::Chrome; 5 | use Selenium::Remote::WDKeys; 6 | 7 | use Cwd qw{abs_path}; 8 | use FindBin; 9 | 10 | use Test::More; 11 | use Test::Fatal; 12 | use Test::Deep; 13 | 14 | my $driver; 15 | is( exception { $driver = Selenium::Chrome->new(); }, undef, "can spawn new Selenium::Chrome"); 16 | 17 | $driver->debug_on(); 18 | 19 | ok($driver->maximize_window(),"can maximize window (WD3)"); 20 | 21 | is($driver->get_capabilities()->{browserName},'chrome',"Can get Capabilities correctly (WD3)"); 22 | my $sessions = $driver->get_sessions(); 23 | is(scalar(@$sessions),1,"Can fall back to selenium2 to list sessions"); 24 | 25 | ok($driver->status()->{ready},"status reports OK (WD3)"); 26 | 27 | #TODO do something about available_engines 28 | 29 | $driver->set_timeout('page load',10000); 30 | $driver->set_timeout('script',10000); 31 | $driver->set_timeout('implicit',10000); 32 | my $timeouts = $driver->get_timeouts(); 33 | is($timeouts->{pageLoad},10000,"WD3 set/get timeouts works"); 34 | is($timeouts->{script},10000,"WD3 set/get timeouts works"); 35 | is($timeouts->{implicit},10000,"WD3 set/get timeouts works"); 36 | 37 | $driver->set_async_script_timeout(20000); 38 | $driver->set_implicit_wait_timeout(5000); 39 | $timeouts = $driver->get_timeouts(); 40 | is($timeouts->{script},20000,"WD3 shim for set_async timeouts works"); 41 | is($timeouts->{implicit},5000,"WD3 shim for implicit timeouts works"); 42 | 43 | my $loc = abs_path("$FindBin::Bin/test.html"); 44 | ok($driver->get("file://$loc"),"Can load a web page (WD3)"); 45 | 46 | is($driver->get_alert_text(),"BEEE DOOO","get_alert_text works (WD3)"); 47 | is(exception { $driver->dismiss_alert() }, undef, "alert can be dismissed (WD3)"); 48 | 49 | #This sucker wants "value" instead of "text" like in legacy 50 | ok($driver->send_keys_to_prompt("HORGLE"),"send_keys_to_prompt works (WD3)"); 51 | is(exception { $driver->accept_alert() }, undef, "alert can be accepted (WD3)"); 52 | 53 | my $handle = $driver->get_current_window_handle(); 54 | ok($handle,"Got a window handle (WD3)"); 55 | cmp_bag($driver->get_window_handles(),[$handle],"Can list window handles (WD3)"); 56 | 57 | my $sz = $driver->get_window_size(); 58 | ok(defined $sz->{height},"get_window_size works (WD3)"); 59 | ok(defined $sz->{width},"get window size works (WD3)"); 60 | my $pos = $driver->get_window_position(); 61 | ok(defined $pos->{x},"get_window_size works (WD3)"); 62 | ok(defined $pos->{y},"get window size works (WD3)"); 63 | 64 | like($driver->get_current_url(),qr/test.html$/,"get_current_url works (WD3)"); 65 | like($driver->get_title(),qr/test/i,"get_title works (WD3)"); 66 | 67 | my $otherloc = abs_path("$FindBin::Bin/other.html"); 68 | $driver->get("file://$otherloc"); 69 | $driver->go_back(); 70 | $driver->dismiss_alert(); 71 | $driver->dismiss_alert(); 72 | like($driver->get_title(),qr/test/i,"go_back works (WD3)"); 73 | 74 | $driver->go_forward(); 75 | like($driver->get_page_source(),qr/ZIPPY/,"go_forward & get_page_source works (WD3)"); 76 | is(exception { $driver->refresh() }, undef, "refresh works (WD3)"); 77 | $driver->go_back(); 78 | $driver->dismiss_alert(); 79 | $driver->dismiss_alert(); 80 | 81 | #TODO execute_*_script testing 82 | 83 | ok($driver->screenshot(),"can get base64'd whole page screenshot (WD3)"); 84 | SKIP: { 85 | skip "chromedriver doesn't know how to take element screenshots", 1; 86 | ok($driver->find_element('body','tag_name')->screenshot(0),"can get element screenshot (WD3 ONLY) and find_element (WD3) works."); 87 | } 88 | 89 | isa_ok($driver->find_element('red','class'),"Selenium::Remote::WebElement"); 90 | isa_ok($driver->find_element('text','name'),"Selenium::Remote::WebElement"); 91 | isa_ok($driver->find_element('Test Link', 'link_text'),"Selenium::Remote::WebElement"); 92 | isa_ok($driver->find_element('Test', 'partial_link_text'),"Selenium::Remote::WebElement"); 93 | 94 | is(scalar(@{$driver->find_elements('red','class')}),2,"can find multiple elements correctly"); 95 | 96 | my $lem = $driver->find_element('body', 'tag_name'); 97 | isa_ok($driver->find_child_element($lem, 'red','class'),"Selenium::Remote::WebElement"); 98 | isa_ok($driver->find_child_element($lem, 'text','name'),"Selenium::Remote::WebElement"); 99 | isa_ok($driver->find_child_element($lem, 'Test Link', 'link_text'),"Selenium::Remote::WebElement"); 100 | isa_ok($driver->find_child_element($lem, 'Test', 'partial_link_text'),"Selenium::Remote::WebElement"); 101 | 102 | $lem = $driver->find_element('form','tag_name'); 103 | is(scalar(@{$driver->find_child_elements($lem,'./*')}),6,"can find child elements (WD3)"); 104 | 105 | isa_ok($driver->get_active_element(),"Selenium::Remote::WebElement"); 106 | 107 | is(exception { $driver->cache_status() },undef, "cache_status implemented in krom"); 108 | my $coords = { 109 | latitude => 40.714353, 110 | longitude => -74.005973, 111 | }; 112 | ok($driver->set_geolocation(location => $coords),"can set_geolocation in krom"); 113 | is( $driver->get_geolocation()->{latitude},$coords->{latitude},"cang get_geolocation in krom"); 114 | 115 | like($driver->upload_file($otherloc),qr/other.html$/,"upload_file fallback works"); 116 | 117 | ok($driver->switch_to_frame($driver->find_element('frame', 'id')),"can switch to frame (WD3)"); 118 | ok($driver->switch_to_frame(),"can switch to parent frame (WD3 only)"); 119 | 120 | ok($driver->set_window_position(1,1),"can set window position (WD3)"); 121 | ok($driver->set_window_size(640,480),"can set window size (WD3)"); 122 | 123 | SKIP: { 124 | skip "chromedriver does not minimize", 1; 125 | ok($driver->minimize_window(),"can minimize window (WD3 only)"); 126 | } 127 | ok($driver->fullscreen_window(),"can fullscreen window (WD3 only)"); 128 | 129 | #XXX chrome has issued a fatwah against cookies issued by file:// urls 130 | is(scalar(@{$driver->get_all_cookies()}),0,"can get cookie list (WD3)"); 131 | $driver->delete_all_cookies(); 132 | is(scalar(@{$driver->get_all_cookies()}),0,"can delete all cookies (WD3)"); 133 | 134 | ok($driver->mouse_move_to_location( element => $driver->find_element('a','tag_name')),"Can use new WD3 Actions API to emulate mouse_move_to_location"); 135 | $driver->click(); 136 | my $handles = $driver->get_window_handles(); 137 | is(scalar(@$handles),2,"Can move to element and then click it correctly (WD3)"); 138 | 139 | $driver->switch_to_window($handles->[1]); 140 | is(exception { $driver->close() }, undef, "Can close new window (WD3)"); 141 | cmp_bag($driver->get_window_handles,[$handles->[0]],"Correct window closed (WD3)"); 142 | $driver->switch_to_window($handles->[0]); 143 | 144 | my $input = $driver->find_element('input','tag_name'); 145 | $driver->mouse_move_to_location( element => $input ); 146 | $driver->click(); 147 | is(exception {$driver->send_modifier('Shift','down')}, undef, "chromedriver can send_modifier"); 148 | $driver->send_keys_to_active_element('howdy',KEYS->{tab}); 149 | $input->send_keys('eee'); 150 | $driver->mouse_move_to_location( element => $driver->find_element('body','tag_name')); 151 | $driver->click(); 152 | 153 | #XXX this has to be a BUG in the driver, the keys are getting thru 154 | is($input->get_attribute('value'),'defaultHOWDYEEE',"element->get_attribute() emulates old behavior thru get_property (WD3)"); 155 | TODO: { 156 | local $TODO = "chrome can't get_property()"; 157 | is($input->get_attribute('value',1),'default',"element->get_attribute() can do it's actual job (WD3)"); 158 | } 159 | is($driver->execute_script(qq/ return document.querySelector('input').value /),'defaultHOWDYEEE',"execute_script works, and so does send_keys_to_active_element & element->send_keys (WD3)"); 160 | $input->clear(); 161 | is($input->get_property('value'),'',"clear() works (WD3)"); 162 | 163 | is(exception { $driver->button_down() },undef,"Can button down (WD3)"); 164 | is(exception { $driver->button_up() },undef,"Can button up (WD3)"); 165 | SKIP: { 166 | skip "chrome don't actionChain", 1; 167 | is(exception { $driver->release_general_action() }, undef, "Can release_general_action (WD3)"); 168 | } 169 | ok($driver->find_element('radio2','id')->is_selected(),"WD3 is_selected() works"); 170 | my $l1 = $driver->find_element('radio1','id'); 171 | $l1->set_selected(); 172 | $l1->set_selected(); 173 | ok($l1->is_selected(),"WD3 set_selected works"); 174 | $l1->toggle(); 175 | TODO: { 176 | local $TODO = "chrome toggle won't allow bogus values (radios with both disabled)"; 177 | ok(!$l1->is_selected(),"WD3 toggle works: off"); 178 | } 179 | $l1->toggle(); 180 | ok($l1->is_selected(),"WD3 toggle works: on"); 181 | 182 | my $l2 = $driver->find_element('hammertime','id'); 183 | is( $l2->is_enabled(),0,"is_enabled works (WD3)"); 184 | #ok( $l2->get_element_location()->{x},"Can get element rect (WD3)"); 185 | #ok( $l2->get_size()->{'height'}, "Size shim on rect works (WD3)"); 186 | is( $l2->get_tag_name(),'input',"get_tag_name works (WD3)"); 187 | is( exception { $l2->get_element_location_in_view() }, undef, "get_element_location_in_view available in gegl krom"); 188 | 189 | is($driver->find_element('hidon','id')->is_displayed(),0,"is_displayed returns false for type=hidden elements"); 190 | my $gone = $driver->find_element('no-see-em','id'); 191 | is($gone->is_displayed(),0,"is_displayed returns false for display=none"); 192 | is($gone->is_enabled(),1,"is_enabled returns true for non-input elements"); 193 | 194 | is($driver->find_element('h1','tag_name')->get_text(),'Howdy Howdy Howdy', "get_text works (WD3)"); 195 | 196 | $driver->find_element('clickme','id')->click(); 197 | is(exception { $driver->dismiss_alert() }, undef, "Can click element (WD3)"); 198 | 199 | $driver->find_element('form','tag_name')->submit(); 200 | like($driver->get_page_source(),qr/ZIPPY/,"elem submit() works (WD3)"); 201 | 202 | #Pretty sure this one has enough 'inertia' to not disappear all the sudden 203 | $driver->get('http://w3.org/History.html'); 204 | $driver->add_cookie('foo','bar','/',undef,0,0,time()+5000); 205 | is(scalar(@{$driver->get_all_cookies()}),1,"can get cookie (WD3)"); 206 | 207 | is($driver->get_cookie_named('foo')->{value},'bar',"can get cookie by name (WD3 only)"); 208 | 209 | $driver->delete_cookie_named('foo'); 210 | is(scalar(@{$driver->get_all_cookies()}),0,"can delete named cookies (WD3)"); 211 | 212 | is(exception { $driver->quit() }, undef, "Can quit (WD3)"); 213 | 214 | my $port = $driver->port(); 215 | 216 | is( exception { $driver->shutdown_binary; }, undef, "can shutdown binary correctly"); 217 | sleep 2; 218 | 219 | my $cmd = "lsof -t -i :$port"; 220 | my $pid = `$cmd`; 221 | chomp $pid; 222 | is($pid,'',"Destructor appears to have run shutdown_binary and whacked the driver process"); 223 | 224 | done_testing(); 225 | 226 | -------------------------------------------------------------------------------- /at/edge.test: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::More; 5 | use Selenium::Edge; 6 | 7 | my $driver = Selenium::Edge->new(); 8 | $driver->get('http://www.perlmonks.org'); 9 | like( $driver->get_title(),qr/monastery gates/i,"Can load perlmonks"); 10 | $driver->quit(); 11 | 12 | done_testing(); 13 | -------------------------------------------------------------------------------- /at/firefox.test: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Selenium::Firefox; 5 | use Test::More tests => 4; 6 | use Test::Fatal; 7 | 8 | my $driver; 9 | is( exception { $driver = Selenium::Firefox->new( 10 | extra_capabilities => { 11 | 'moz:firefoxOptions' => { 12 | args => [ '-headless' ], 13 | }, 14 | }, 15 | ); }, undef, "can spawn new Selenium::Firefox"); 16 | 17 | my $port = $driver->port(); 18 | 19 | ok($driver->get('http://google.com'),"can load a page"); 20 | $driver->quit(); 21 | 22 | is( exception { $driver->shutdown_binary; }, undef, "can shutdown binary correctly"); 23 | sleep 2; 24 | 25 | my $cmd = "lsof -t -i :$port"; 26 | my $pid = `$cmd`; 27 | chomp $pid; 28 | is($pid,'',"Destructor appears to have run shutdown_binary and whacked the driver process"); 29 | -------------------------------------------------------------------------------- /at/legacy.test: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Cwd qw{abs_path}; 5 | use FindBin; 6 | 7 | use Test::More; 8 | use Test::Fatal; 9 | use Test::Deep; 10 | 11 | use Selenium::Remote::Driver; 12 | use Selenium::Remote::WDKeys; 13 | 14 | my $driver = Selenium::Remote::Driver->new( 15 | remote_server_addr => '10.17.64.252', 16 | port => 4444, 17 | browser_name => 'firefox', 18 | accept_ssl_certs => 1, 19 | ); 20 | isa_ok($driver,'Selenium::Remote::Driver',"Can get new S::R::D with WebDriver3"); 21 | 22 | $driver->debug_on(); 23 | 24 | is($driver->get_capabilities()->{browserName},'firefox',"Can get Capabilities correctly (WD2)"); 25 | my $sessions = $driver->get_sessions(); 26 | is(scalar(@$sessions),1,"Can fall back to selenium2 to list sessions"); 27 | 28 | ok($driver->status()->{build}->{version},"status reports OK (WD2)"); 29 | 30 | #TODO do something about available_engines 31 | 32 | is( exception { $driver->set_timeout('page load',10000) }, undef, "WD2 set_timeout pageload OK"); 33 | is( exception { $driver->set_timeout('script',10000) }, undef, "WD2 set_timeout script OK"); 34 | is( exception { $driver->set_timeout('implicit',10000) }, undef, "WD2 set_timeout implicit OK"); 35 | is( exception { $driver->set_async_script_timeout(20000) }, undef, "WD2 set_async_script_timeout OK"); 36 | is( exception { $driver->set_implicit_wait_timeout(5000) }, undef, "WD2 set_implicit_wait_timeout OK"); 37 | 38 | my $loc = abs_path("$FindBin::Bin/test.html"); 39 | my $local_loc = $driver->upload_file($loc); 40 | note $local_loc; 41 | 42 | ok($driver->get("file://$local_loc"),"Can load a web page (WD2)"); 43 | 44 | is($driver->get_alert_text(),"BEEE DOOO","get_alert_text works (WD2)"); 45 | is(exception { $driver->dismiss_alert() }, undef, "alert can be dismissed (WD2)"); 46 | 47 | #This sucker wants "value" instead of "text" like in legacy 48 | ok($driver->send_keys_to_prompt("HORGLE"),"send_keys_to_prompt works (WD2)"); 49 | is(exception { $driver->accept_alert() }, undef, "alert can be accepted (WD2)"); 50 | 51 | my $handle = $driver->get_current_window_handle(); 52 | ok($handle,"Got a window handle (WD2)"); 53 | cmp_bag($driver->get_window_handles(),[$handle],"Can list window handles (WD2)"); 54 | 55 | my $sz = $driver->get_window_size(); 56 | ok(defined $sz->{height},"get_window_size works (WD2)"); 57 | ok(defined $sz->{width},"get window size works (WD2)"); 58 | my $pos = $driver->get_window_position(); 59 | ok(defined $pos->{x},"get_window_size works (WD2)"); 60 | ok(defined $pos->{y},"get window size works (WD2)"); 61 | 62 | like($driver->get_current_url(),qr/test.html$/,"get_current_url works (WD2)"); 63 | like($driver->get_title(),qr/test/i,"get_title works (WD2)"); 64 | 65 | my $otherloc = abs_path("$FindBin::Bin/other.html"); 66 | my $other_local_loc = $driver->upload_file($otherloc); 67 | note $other_local_loc; 68 | 69 | $driver->get("file://$other_local_loc"); 70 | $driver->go_back(); 71 | $driver->dismiss_alert(); 72 | $driver->dismiss_alert(); 73 | like($driver->get_title(),qr/test/i,"go_back works (WD2)"); 74 | 75 | $driver->go_forward(); 76 | like($driver->get_page_source(),qr/ZIPPY/,"go_forward & get_page_source works (WD2)"); 77 | is(exception { $driver->refresh() }, undef, "refresh works (WD2)"); 78 | $driver->go_back(); 79 | $driver->dismiss_alert(); 80 | $driver->dismiss_alert(); 81 | 82 | #TODO execute_*_script testing 83 | 84 | ok($driver->screenshot(),"can get base64'd whole page screenshot (WD2)"); 85 | 86 | isa_ok($driver->find_element('red','class'),"Selenium::Remote::WebElement"); 87 | isa_ok($driver->find_element('text','name'),"Selenium::Remote::WebElement"); 88 | isa_ok($driver->find_element('Test Link', 'link_text'),"Selenium::Remote::WebElement"); 89 | isa_ok($driver->find_element('Test', 'partial_link_text'),"Selenium::Remote::WebElement"); 90 | 91 | is(scalar(@{$driver->find_elements('red','class')}),2,"can find multiple elements correctly"); 92 | 93 | my $lem = $driver->find_element('body', 'tag_name'); 94 | isa_ok($driver->find_child_element($lem, 'red','class'),"Selenium::Remote::WebElement"); 95 | isa_ok($driver->find_child_element($lem, 'text','name'),"Selenium::Remote::WebElement"); 96 | isa_ok($driver->find_child_element($lem, 'Test Link', 'link_text'),"Selenium::Remote::WebElement"); 97 | isa_ok($driver->find_child_element($lem, 'Test', 'partial_link_text'),"Selenium::Remote::WebElement"); 98 | 99 | $lem = $driver->find_element('form','tag_name'); 100 | is(scalar(@{$driver->find_child_elements($lem,'./*')}),6,"can find child elements (WD2)"); 101 | 102 | isa_ok($driver->get_active_element(),"Selenium::Remote::WebElement"); 103 | 104 | TODO: { 105 | local $TODO = "These methods aren't supported on firefox"; 106 | is(exception { $driver->cache_status() },undef, "cache_status works in WD2"); 107 | is(exception { 108 | $driver->set_geolocation(location => { 109 | latitude => 40.714353, 110 | longitude => -74.005973, 111 | altitude => 0.056747 112 | }); 113 | }, undef, "set_geolocation works in WD2"); 114 | is(exception { $driver->get_geolocation() }, undef, "get_geolocation works in WD2"); 115 | is(exception { $driver->set_orientation("LANDSCAPE") }, undef, "set_orientation works in WD2"); 116 | is(exception { $driver->get_orientation() }, undef, "get_orientation works in WD2"); 117 | } 118 | 119 | ok($driver->get_log('server'), "get_log fallback works"); 120 | ok( scalar(@{$driver->get_log_types()}),"can fallback for get_log_types"); 121 | 122 | like($driver->upload_file($otherloc),qr/other.html$/,"upload_file fallback works"); 123 | 124 | #Jinkies, this stuff is cool, it prints the selenium server help page @_@ 125 | #diag explain $driver->get_local_storage_item('whee'); 126 | #diag explain $driver->delete_local_storage_item('whee'); 127 | 128 | ok($driver->switch_to_frame($driver->find_element('frame', 'id')),"can switch to frame (WD2)"); 129 | ok($driver->switch_to_frame(),"can switch to parent frame (WD2 only)"); 130 | 131 | ok($driver->set_window_position(1,1),"can set window position (WD2)"); 132 | ok($driver->set_window_size(200,200),"can set window size (WD2)"); 133 | 134 | ok($driver->maximize_window(),"can maximize window (WD2)"); 135 | 136 | is(scalar(@{$driver->get_all_cookies()}),1,"can get cookie list (WD2)"); 137 | $driver->delete_all_cookies(); 138 | is(scalar(@{$driver->get_all_cookies()}),0,"can delete all cookies (WD2)"); 139 | 140 | ok($driver->mouse_move_to_location( element => $driver->find_element('a','tag_name')),"Can use mouse_move_to_location"); 141 | $driver->click(); 142 | my $handles = $driver->get_window_handles(); 143 | is(scalar(@$handles),2,"Can move to element and then click it correctly (WD2)"); 144 | 145 | $driver->switch_to_window($handles->[1]); 146 | is(exception { $driver->close() }, undef, "Can close new window (WD2)"); 147 | cmp_bag($driver->get_window_handles,[$handles->[0]],"Correct window closed (WD2)"); 148 | $driver->switch_to_window($handles->[0]); 149 | 150 | my $input = $driver->find_element('input','tag_name'); 151 | $driver->mouse_move_to_location( element => $input ); 152 | $driver->click(); 153 | 154 | #TODO pretty sure this isn't working right 155 | SKIP: { 156 | skip("P.sure send_modifier is kind of screwed up",1); 157 | $driver->send_modifier('Shift','down'); 158 | } 159 | 160 | $driver->send_keys_to_active_element('howdy',KEYS->{tab}); 161 | $input->send_keys('eee'); 162 | $driver->mouse_move_to_location( element => $driver->find_element('body','tag_name')); 163 | $driver->click(); 164 | 165 | #XXX this has to be a BUG in the driver, the keys are getting thru 166 | is($input->get_attribute('value'),'defaulthowdyeee',"element->get_attribute() works (WD2)"); 167 | is($input->get_attribute('value',1),'defaulthowdyeee',"element->get_attribute() second arg ignored (WD2)"); 168 | is($driver->execute_script(qq/ return document.querySelector('input').value /),'defaulthowdyeee',"execute_script works, and so does send_keys_to_active_element & element->send_keys (WD2)"); 169 | $input->clear(); 170 | is($input->get_attribute('value'),'',"clear() works (WD2)"); 171 | 172 | is(exception { $driver->button_down() },undef,"Can button down (WD2)"); 173 | is(exception { $driver->button_up() },undef,"Can button up (WD2)"); 174 | 175 | ok($driver->find_element('radio2','id')->is_selected(),"WD2 is_selected() works"); 176 | my $l1 = $driver->find_element('radio1','id'); 177 | SKIP: { 178 | skip "set_selected, toggle_element, is_selected looks broke", 1; 179 | $l1->set_selected(); 180 | $l1->set_selected(); 181 | ok($l1->is_selected(),"WD2 set_selected works"); 182 | $l1->toggle(); 183 | ok(!$l1->is_selected(),"WD2 toggle works: off"); 184 | $l1->toggle(); 185 | ok($l1->is_selected(),"WD2 toggle works: on"); 186 | } 187 | 188 | my $l2 = $driver->find_element('hammertime','id'); 189 | is( $l2->is_enabled(),0,"is_enabled works (WD2)"); 190 | ok( $l2->get_element_location()->{x},"Can get element rect (WD2)"); 191 | ok( $l2->get_size()->{'height'}, "Size shim on rect works (WD2)"); 192 | is( $l2->get_tag_name(),'input',"get_tag_name works (WD2)"); 193 | is( exception { $l2->get_element_location_in_view() }, undef, "get_element_location_in_view not available in WD2"); 194 | 195 | is($driver->find_element('hidon','id')->is_displayed(),0,"is_displayed returns false for type=hidden elements"); 196 | is($driver->find_element('no-see-em','id')->is_displayed(),0,"is_displayed returns false for display=none"); 197 | is($driver->find_element('h1','tag_name')->get_text(),'Howdy Howdy Howdy', "get_text works (WD2)"); 198 | 199 | $driver->find_element('clickme','id')->click(); 200 | is(exception { $driver->dismiss_alert() }, undef, "Can click element (WD2)"); 201 | 202 | $driver->find_element('form','tag_name')->submit(); 203 | like($driver->get_page_source(),qr/File not found/,"elem submit() works (WD2)"); 204 | 205 | #Pretty sure this one has enough 'inertia' to not disappear all the sudden 206 | $driver->get('http://w3.org/History.html'); 207 | $driver->add_cookie('foo','bar',undef,undef,0,0,time()+5000); 208 | is(scalar(@{$driver->get_all_cookies()}),1,"can set cookie (WD2)"); 209 | 210 | $driver->delete_cookie_named('foo'); 211 | is(scalar(@{$driver->get_all_cookies()}),0,"can delete named cookies (WD2)"); 212 | 213 | is(exception { $driver->quit() }, undef, "Can quit (WD2)"); 214 | 215 | done_testing(); 216 | -------------------------------------------------------------------------------- /at/other.html: -------------------------------------------------------------------------------- 1 | ZIPPY 2 | -------------------------------------------------------------------------------- /at/sanity-chrome.test: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Cwd qw{abs_path}; 5 | use FindBin; 6 | 7 | use Test::More; 8 | use Test::Fatal; 9 | use Test::Deep; 10 | 11 | use Selenium::Remote::Driver; 12 | use Selenium::Remote::WDKeys; 13 | 14 | #TODO: cover new_from_caps 15 | #TODO: Selenium::Firefox::Profile usage 16 | 17 | my $driver = Selenium::Remote::Driver->new( 18 | remote_server_addr => 'localhost', 19 | port => 4444, 20 | browser_name => 'chrome', 21 | accept_ssl_certs => 1, 22 | extra_capabilities => { 23 | args => ['start-maximized'], 24 | }, 25 | ); 26 | isa_ok($driver,'Selenium::Remote::Driver',"Can get new S::R::D with WebDriver3"); 27 | 28 | $driver->debug_on(); 29 | 30 | ok($driver->maximize_window(),"can maximize window (WD3)"); 31 | 32 | is($driver->get_capabilities()->{browserName},'chrome',"Can get Capabilities correctly (WD3)"); 33 | my $sessions = $driver->get_sessions(); 34 | is(scalar(@$sessions),1,"Can fall back to selenium2 to list sessions"); 35 | 36 | ok($driver->status()->{ready},"status reports OK (WD3)"); 37 | 38 | #TODO do something about available_engines 39 | 40 | $driver->set_timeout('page load',10000); 41 | $driver->set_timeout('script',10000); 42 | $driver->set_timeout('implicit',10000); 43 | my $timeouts = $driver->get_timeouts(); 44 | is($timeouts->{pageLoad},10000,"WD3 set/get timeouts works"); 45 | is($timeouts->{script},10000,"WD3 set/get timeouts works"); 46 | is($timeouts->{implicit},10000,"WD3 set/get timeouts works"); 47 | 48 | $driver->set_async_script_timeout(20000); 49 | $driver->set_implicit_wait_timeout(5000); 50 | $timeouts = $driver->get_timeouts(); 51 | is($timeouts->{script},20000,"WD3 shim for set_async timeouts works"); 52 | is($timeouts->{implicit},5000,"WD3 shim for implicit timeouts works"); 53 | 54 | my $loc = abs_path("$FindBin::Bin/test.html"); 55 | ok($driver->get("file://$loc"),"Can load a web page (WD3)"); 56 | 57 | is($driver->get_alert_text(),"BEEE DOOO","get_alert_text works (WD3)"); 58 | is(exception { $driver->dismiss_alert() }, undef, "alert can be dismissed (WD3)"); 59 | 60 | #This sucker wants "value" instead of "text" like in legacy 61 | ok($driver->send_keys_to_prompt("HORGLE"),"send_keys_to_prompt works (WD3)"); 62 | is(exception { $driver->accept_alert() }, undef, "alert can be accepted (WD3)"); 63 | 64 | my $handle = $driver->get_current_window_handle(); 65 | ok($handle,"Got a window handle (WD3)"); 66 | cmp_bag($driver->get_window_handles(),[$handle],"Can list window handles (WD3)"); 67 | 68 | my $sz = $driver->get_window_size(); 69 | ok(defined $sz->{height},"get_window_size works (WD3)"); 70 | ok(defined $sz->{width},"get window size works (WD3)"); 71 | my $pos = $driver->get_window_position(); 72 | ok(defined $pos->{x},"get_window_size works (WD3)"); 73 | ok(defined $pos->{y},"get window size works (WD3)"); 74 | 75 | like($driver->get_current_url(),qr/test.html$/,"get_current_url works (WD3)"); 76 | like($driver->get_title(),qr/test/i,"get_title works (WD3)"); 77 | 78 | my $otherloc = abs_path("$FindBin::Bin/other.html"); 79 | $driver->get("file://$otherloc"); 80 | $driver->go_back(); 81 | $driver->dismiss_alert(); 82 | $driver->dismiss_alert(); 83 | like($driver->get_title(),qr/test/i,"go_back works (WD3)"); 84 | 85 | $driver->go_forward(); 86 | like($driver->get_page_source(),qr/ZIPPY/,"go_forward & get_page_source works (WD3)"); 87 | is(exception { $driver->refresh() }, undef, "refresh works (WD3)"); 88 | $driver->go_back(); 89 | $driver->dismiss_alert(); 90 | $driver->dismiss_alert(); 91 | 92 | #TODO execute_*_script testing 93 | 94 | ok($driver->screenshot(),"can get base64'd whole page screenshot (WD3)"); 95 | SKIP: { 96 | skip "chromedriver doesn't know how to take element screenshots", 1; 97 | ok($driver->find_element('body','tag_name')->screenshot(0),"can get element screenshot (WD3 ONLY) and find_element (WD3) works."); 98 | } 99 | 100 | isa_ok($driver->find_element('red','class'),"Selenium::Remote::WebElement"); 101 | isa_ok($driver->find_element('text','name'),"Selenium::Remote::WebElement"); 102 | isa_ok($driver->find_element('Test Link', 'link_text'),"Selenium::Remote::WebElement"); 103 | isa_ok($driver->find_element('Test', 'partial_link_text'),"Selenium::Remote::WebElement"); 104 | 105 | is(scalar(@{$driver->find_elements('red','class')}),2,"can find multiple elements correctly"); 106 | 107 | my $lem = $driver->find_element('body', 'tag_name'); 108 | isa_ok($driver->find_child_element($lem, 'red','class'),"Selenium::Remote::WebElement"); 109 | isa_ok($driver->find_child_element($lem, 'text','name'),"Selenium::Remote::WebElement"); 110 | isa_ok($driver->find_child_element($lem, 'Test Link', 'link_text'),"Selenium::Remote::WebElement"); 111 | isa_ok($driver->find_child_element($lem, 'Test', 'partial_link_text'),"Selenium::Remote::WebElement"); 112 | 113 | $lem = $driver->find_element('form','tag_name'); 114 | is(scalar(@{$driver->find_child_elements($lem,'./*')}),6,"can find child elements (WD3)"); 115 | 116 | isa_ok($driver->get_active_element(),"Selenium::Remote::WebElement"); 117 | 118 | is(exception { $driver->cache_status() },undef, "cache_status implemented in krom"); 119 | my $coords = { 120 | latitude => 40.714353, 121 | longitude => -74.005973, 122 | }; 123 | ok($driver->set_geolocation(location => $coords),"can set_geolocation in krom"); 124 | is( $driver->get_geolocation()->{latitude},$coords->{latitude},"cang get_geolocation in krom"); 125 | 126 | ok($driver->get_log('server'), "get_log fallback works"); 127 | ok( scalar(@{$driver->get_log_types()}),"can fallback for get_log_types"); 128 | 129 | isnt(exception { $driver->set_orientation("LANDSCAPE") },undef,"set_orientation unavailable on desktop"); 130 | like(exception { $driver->get_orientation() },qr/error/,"get_orientation unavailable on desktop"); 131 | 132 | like($driver->upload_file($otherloc),qr/other.html$/,"upload_file fallback works"); 133 | 134 | #Jinkies, this stuff is cool, it prints the selenium server help page @_@ 135 | like( exception { $driver->get_local_storage_item('whee') },qr/help/i,"get_local_storage_item prints help page"); 136 | like( exception { $driver->delete_local_storage_item('whee') },qr/help/i,"get_local_storage_item prints help page"); 137 | 138 | ok($driver->switch_to_frame($driver->find_element('frame', 'id')),"can switch to frame (WD3)"); 139 | ok($driver->switch_to_frame(),"can switch to parent frame (WD3 only)"); 140 | 141 | ok($driver->set_window_position(1,1),"can set window position (WD3)"); 142 | ok($driver->set_window_size(640,480),"can set window size (WD3)"); 143 | 144 | SKIP: { 145 | skip "chromedriver does not minimize", 1; 146 | ok($driver->minimize_window(),"can minimize window (WD3 only)"); 147 | } 148 | ok($driver->fullscreen_window(),"can fullscreen window (WD3 only)"); 149 | 150 | #XXX chrome has issued a fatwah against cookies issued by file:// urls 151 | is(scalar(@{$driver->get_all_cookies()}),0,"can get cookie list (WD3)"); 152 | $driver->delete_all_cookies(); 153 | is(scalar(@{$driver->get_all_cookies()}),0,"can delete all cookies (WD3)"); 154 | 155 | ok($driver->mouse_move_to_location( element => $driver->find_element('a','tag_name')),"Can use new WD3 Actions API to emulate mouse_move_to_location"); 156 | $driver->click(); 157 | my $handles = $driver->get_window_handles(); 158 | is(scalar(@$handles),2,"Can move to element and then click it correctly (WD3)"); 159 | 160 | $driver->switch_to_window($handles->[1]); 161 | is(exception { $driver->close() }, undef, "Can close new window (WD3)"); 162 | cmp_bag($driver->get_window_handles,[$handles->[0]],"Correct window closed (WD3)"); 163 | $driver->switch_to_window($handles->[0]); 164 | 165 | my $input = $driver->find_element('input','tag_name'); 166 | $driver->mouse_move_to_location( element => $input ); 167 | $driver->click(); 168 | isnt(exception {$driver->send_modifier('Shift','down')}, undef, "chromedriver can't send_modifier"); 169 | $driver->send_keys_to_active_element('howdy',KEYS->{tab}); 170 | $input->send_keys('eee'); 171 | $driver->mouse_move_to_location( element => $driver->find_element('body','tag_name')); 172 | $driver->click(); 173 | 174 | #XXX this has to be a BUG in the driver, the keys are getting thru 175 | is($input->get_attribute('value'),'defaulthowdyeee',"element->get_attribute() emulates old behavior thru get_property (WD3)"); 176 | TODO: { 177 | local $TODO = "chrome can't get_property()"; 178 | is($input->get_attribute('value',1),'default',"element->get_attribute() can do it's actual job (WD3)"); 179 | } 180 | is($driver->execute_script(qq/ return document.querySelector('input').value /),'defaulthowdyeee',"execute_script works, and so does send_keys_to_active_element & element->send_keys (WD3)"); 181 | $input->clear(); 182 | is($input->get_property('value'),'',"clear() works (WD3)"); 183 | 184 | is(exception { $driver->button_down() },undef,"Can button down (WD3)"); 185 | is(exception { $driver->button_up() },undef,"Can button up (WD3)"); 186 | SKIP: { 187 | skip "chrome don't actionChain", 1; 188 | is(exception { $driver->release_general_action() }, undef, "Can release_general_action (WD3)"); 189 | } 190 | ok($driver->find_element('radio2','id')->is_selected(),"WD3 is_selected() works"); 191 | my $l1 = $driver->find_element('radio1','id'); 192 | $l1->set_selected(); 193 | $l1->set_selected(); 194 | ok($l1->is_selected(),"WD3 set_selected works"); 195 | $l1->toggle(); 196 | TODO: { 197 | local $TODO = "chrome toggle won't allow bogus values (radios with both disabled)"; 198 | ok(!$l1->is_selected(),"WD3 toggle works: off"); 199 | } 200 | $l1->toggle(); 201 | ok($l1->is_selected(),"WD3 toggle works: on"); 202 | 203 | my $l2 = $driver->find_element('hammertime','id'); 204 | is( $l2->is_enabled(),0,"is_enabled works (WD3)"); 205 | ok( $l2->get_element_location()->{x},"Can get element rect (WD3)"); 206 | ok( $l2->get_size()->{'height'}, "Size shim on rect works (WD3)"); 207 | is( $l2->get_tag_name(),'input',"get_tag_name works (WD3)"); 208 | is( exception { $l2->get_element_location_in_view() }, undef, "get_element_location_in_view available in gegl krom"); 209 | 210 | is($driver->find_element('hidon','id')->is_displayed(),0,"is_displayed returns false for type=hidden elements"); 211 | my $gone = $driver->find_element('no-see-em','id'); 212 | is($gone->is_displayed(),0,"is_displayed returns false for display=none"); 213 | is($gone->is_enabled(),1,"is_enabled returns true for non-input elements"); 214 | 215 | is($driver->find_element('h1','tag_name')->get_text(),'Howdy Howdy Howdy', "get_text works (WD3)"); 216 | 217 | $driver->find_element('clickme','id')->click(); 218 | is(exception { $driver->dismiss_alert() }, undef, "Can click element (WD3)"); 219 | 220 | $driver->find_element('form','tag_name')->submit(); 221 | like($driver->get_page_source(),qr/ZIPPY/,"elem submit() works (WD3)"); 222 | 223 | #Pretty sure this one has enough 'inertia' to not disappear all the sudden 224 | $driver->get('http://w3.org/History.html'); 225 | $driver->add_cookie('foo','bar',undef,undef,0,0,time()+5000); 226 | is(scalar(@{$driver->get_all_cookies()}),1,"can set cookie (WD3)"); 227 | 228 | is($driver->get_cookie_named('foo')->{value},'bar',"can get cookie by name (WD3 only)"); 229 | 230 | $driver->delete_cookie_named('foo'); 231 | is(scalar(@{$driver->get_all_cookies()}),0,"can delete named cookies (WD3)"); 232 | 233 | is(exception { $driver->quit() }, undef, "Can quit (WD3)"); 234 | 235 | done_testing(); 236 | -------------------------------------------------------------------------------- /at/sanity.test: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Cwd qw{abs_path}; 5 | use FindBin; 6 | 7 | use Test::More; 8 | use Test::Fatal; 9 | use Test::Deep; 10 | 11 | use Selenium::Remote::Driver; 12 | use Selenium::Remote::WDKeys; 13 | 14 | #TODO: cover new_from_caps 15 | #TODO: Selenium::Firefox::Profile usage 16 | 17 | $Selenium::Remote::Driver::FORCE_WD3 = 1; 18 | my $driver = Selenium::Remote::Driver->new( 19 | remote_server_addr => 'localhost', 20 | port => 4444, 21 | browser_name => 'firefox', 22 | accept_ssl_certs => 1, 23 | extra_capabilities => { 24 | log => { level => 'trace' }, 25 | }, 26 | ); 27 | isa_ok($driver,'Selenium::Remote::Driver',"Can get new S::R::D with WebDriver3"); 28 | 29 | $driver->debug_on(); 30 | 31 | is($driver->get_capabilities()->{browserName},'firefox',"Can get Capabilities correctly (WD3)"); 32 | my $sessions = $driver->get_sessions(); 33 | is(scalar(@$sessions),1,"Can fall back to selenium2 to list sessions"); 34 | 35 | ok($driver->status()->{ready},"status reports OK (WD3)"); 36 | 37 | #TODO do something about available_engines 38 | 39 | $driver->set_timeout('page load',10000); 40 | $driver->set_timeout('script',10000); 41 | $driver->set_timeout('implicit',10000); 42 | my $timeouts = $driver->get_timeouts(); 43 | is($timeouts->{pageLoad},10000,"WD3 set/get timeouts works"); 44 | is($timeouts->{script},10000,"WD3 set/get timeouts works"); 45 | is($timeouts->{implicit},10000,"WD3 set/get timeouts works"); 46 | 47 | $driver->set_async_script_timeout(20000); 48 | $driver->set_implicit_wait_timeout(5000); 49 | $timeouts = $driver->get_timeouts(); 50 | is($timeouts->{script},20000,"WD3 shim for set_async timeouts works"); 51 | is($timeouts->{implicit},5000,"WD3 shim for implicit timeouts works"); 52 | 53 | my $loc = abs_path("$FindBin::Bin/test.html"); 54 | ok($driver->get("file://$loc"),"Can load a web page (WD3)"); 55 | 56 | is($driver->get_alert_text(),"BEEE DOOO","get_alert_text works (WD3)"); 57 | is(exception { $driver->dismiss_alert() }, undef, "alert can be dismissed (WD3)"); 58 | 59 | #This sucker wants "value" instead of "text" like in legacy 60 | ok($driver->send_keys_to_prompt("HORGLE"),"send_keys_to_prompt works (WD3)"); 61 | is(exception { $driver->accept_alert() }, undef, "alert can be accepted (WD3)"); 62 | 63 | my $handle = $driver->get_current_window_handle(); 64 | ok($handle,"Got a window handle (WD3)"); 65 | cmp_bag($driver->get_window_handles(),[$handle],"Can list window handles (WD3)"); 66 | 67 | my $sz = $driver->get_window_size(); 68 | ok(defined $sz->{height},"get_window_size works (WD3)"); 69 | ok(defined $sz->{width},"get window size works (WD3)"); 70 | my $pos = $driver->get_window_position(); 71 | ok(defined $pos->{x},"get_window_size works (WD3)"); 72 | ok(defined $pos->{y},"get window size works (WD3)"); 73 | 74 | like($driver->get_current_url(),qr/test.html$/,"get_current_url works (WD3)"); 75 | like($driver->get_title(),qr/test/i,"get_title works (WD3)"); 76 | 77 | my $otherloc = abs_path("$FindBin::Bin/other.html"); 78 | $driver->get("file://$otherloc"); 79 | $driver->go_back(); 80 | like($driver->get_title(),qr/test/i,"go_back works (WD3)"); 81 | 82 | $driver->go_forward(); 83 | like($driver->get_page_source(),qr/ZIPPY/,"go_forward & get_page_source works (WD3)"); 84 | is(exception { $driver->refresh() }, undef, "refresh works (WD3)"); 85 | $driver->go_back(); 86 | 87 | #TODO execute_*_script testing 88 | 89 | ok($driver->screenshot(),"can get base64'd whole page screenshot (WD3)"); 90 | ok($driver->find_element('body','tag_name')->screenshot(0),"can get element screenshot (WD3 ONLY) and find_element (WD3) works."); 91 | 92 | isa_ok($driver->find_element('red','class'),"Selenium::Remote::WebElement"); 93 | isa_ok($driver->find_element('text','name'),"Selenium::Remote::WebElement"); 94 | isa_ok($driver->find_element('Test Link', 'link_text'),"Selenium::Remote::WebElement"); 95 | isa_ok($driver->find_element('Test', 'partial_link_text'),"Selenium::Remote::WebElement"); 96 | 97 | is(scalar(@{$driver->find_elements('red','class')}),2,"can find multiple elements correctly"); 98 | 99 | my $lem = $driver->find_element('body', 'tag_name'); 100 | isa_ok($driver->find_child_element($lem, 'red','class'),"Selenium::Remote::WebElement"); 101 | isa_ok($lem->child('red','class'),"Selenium::Remote::WebElement"); 102 | isa_ok($driver->find_child_element($lem, 'text','name'),"Selenium::Remote::WebElement"); 103 | isa_ok($driver->find_child_element($lem, 'Test Link', 'link_text'),"Selenium::Remote::WebElement"); 104 | isa_ok($driver->find_child_element($lem, 'Test', 'partial_link_text'),"Selenium::Remote::WebElement"); 105 | 106 | $lem = $driver->find_element('form','tag_name'); 107 | is(scalar(@{$driver->find_child_elements($lem,'./*')}),6,"can find child elements (WD3)"); 108 | is(scalar(@{$lem->children('./*')}),6,"can find child elements via children() alias (WD3)"); 109 | 110 | isa_ok($driver->get_active_element(),"Selenium::Remote::WebElement"); 111 | 112 | like(exception { $driver->cache_status() },qr/unknown command/, "cache_status unimplemented in WD3"); 113 | like(exception { 114 | diag explain $driver->set_geolocation(location => { 115 | latitude => 40.714353, 116 | longitude => -74.005973, 117 | altitude => 0.056747 118 | }); 119 | }, qr/unknown command/, "set_geolocation unimplemented in WD3"); 120 | like(exception { $driver->get_geolocation() }, qr/unknown command/, "get_geolocation unimplemented in WD3"); 121 | 122 | ok($driver->get_log('server'), "get_log fallback works"); 123 | ok( scalar(@{$driver->get_log_types()}),"can fallback for get_log_types"); 124 | 125 | like(exception { $driver->set_orientation("LANDSCAPE") }, qr/unknown command/, "set_orientation unimplemented in WD3"); 126 | like(exception { $driver->get_orientation() }, qr/unknown command/, "get_orientation unimplemented in WD3"); 127 | 128 | like($driver->upload_file($otherloc),qr/other.html$/,"upload_file fallback works"); 129 | 130 | #Jinkies, this stuff is cool, it prints the selenium server help page @_@ 131 | like( exception { $driver->get_local_storage_item('whee') },qr/help/i,"get_local_storage_item prints help page"); 132 | like( exception { $driver->delete_local_storage_item('whee') },qr/help/i,"get_local_storage_item prints help page"); 133 | 134 | ok($driver->switch_to_frame($driver->find_element('frame', 'id')),"can switch to frame (WD3)"); 135 | ok($driver->switch_to_frame(),"can switch to parent frame (WD3 only)"); 136 | 137 | ok($driver->set_window_position(1,1),"can set window position (WD3)"); 138 | ok($driver->set_window_size(640,480),"can set window size (WD3)"); 139 | 140 | SKIP: { 141 | skip(2, "maxi/mini not working right now?"); 142 | ok($driver->maximize_window(),"can maximize window (WD3)"); 143 | ok($driver->minimize_window(),"can minimize window (WD3 only)"); 144 | } 145 | ok($driver->fullscreen_window(),"can fullscreen window (WD3 only)"); 146 | 147 | is(scalar(@{$driver->get_all_cookies()}),1,"can get cookie list (WD3)"); 148 | $driver->delete_all_cookies(); 149 | is(scalar(@{$driver->get_all_cookies()}),0,"can delete all cookies (WD3)"); 150 | 151 | ok($driver->mouse_move_to_location( element => $driver->find_element('a','tag_name')),"Can use new WD3 Actions API to emulate mouse_move_to_location"); 152 | $driver->click(); 153 | sleep 5; 154 | my $handles = $driver->get_window_handles(); 155 | is(scalar(@$handles),2,"Can move to element and then click it correctly (WD3)"); 156 | 157 | $driver->switch_to_window($handles->[1]); 158 | is(exception { $driver->close() }, undef, "Can close new window (WD3)"); 159 | cmp_bag($driver->get_window_handles,[$handles->[0]],"Correct window closed (WD3)"); 160 | $driver->switch_to_window($handles->[0]); 161 | 162 | my $input = $driver->find_element('input','tag_name'); 163 | $driver->mouse_move_to_location( element => $input ); 164 | $driver->click(); 165 | #TODO pretty sure this isn't working right 166 | $driver->send_modifier('Shift','down'); 167 | $driver->send_keys_to_active_element('howdy',KEYS->{tab}); 168 | $input->send_keys('eee'); 169 | $driver->mouse_move_to_location( element => $driver->find_element('body','tag_name')); 170 | $driver->click(); 171 | 172 | #XXX this has to be a BUG in the driver, the keys are getting thru 173 | is($input->get_attribute('value'),'defaulthowdyeee',"element->get_attribute() emulates old behavior thru get_property (WD3)"); 174 | is($input->get_attribute('value',1),'default',"element->get_attribute() can do it's actual job (WD3)"); 175 | is($driver->execute_script(qq/ return document.querySelector('input').value /),'defaulthowdyeee',"execute_script works, and so does send_keys_to_active_element & element->send_keys (WD3)"); 176 | $input->clear(); 177 | is($input->get_property('value'),'',"clear() works (WD3)"); 178 | 179 | is(exception { $driver->button_down() },undef,"Can button down (WD3)"); 180 | is(exception { $driver->button_up() },undef,"Can button up (WD3)"); 181 | is(exception { $driver->release_general_action() }, undef, "Can release_general_action (WD3)"); 182 | 183 | ok($driver->find_element('radio2','id')->is_selected(),"WD3 is_selected() works"); 184 | my $l1 = $driver->find_element('radio1','id'); 185 | $l1->set_selected(); 186 | $l1->set_selected(); 187 | ok($l1->is_selected(),"WD3 set_selected works"); 188 | $l1->toggle(); 189 | ok(!$l1->is_selected(),"WD3 toggle works: off"); 190 | $l1->toggle(); 191 | ok($l1->is_selected(),"WD3 toggle works: on"); 192 | 193 | my $l2 = $driver->find_element('hammertime','id'); 194 | is( $l2->is_enabled(),0,"is_enabled works (WD3)"); 195 | ok( $l2->get_element_location()->{x},"Can get element rect (WD3)"); 196 | ok( $l2->get_size()->{'height'}, "Size shim on rect works (WD3)"); 197 | is( $l2->get_tag_name(),'input',"get_tag_name works (WD3)"); 198 | ok( defined $l2->get_element_location_in_view()->{x}, "get_element_location_in_view polyfill works (WD3)"); 199 | 200 | is($driver->find_element('hidon','id')->is_displayed(),0,"is_displayed returns false for type=hidden elements"); 201 | my $gone = $driver->find_element('no-see-em','id'); 202 | is($gone->is_displayed(),0,"is_displayed returns false for display=none"); 203 | is($gone->is_enabled(),1,"is_enabled returns true for non-input elements"); 204 | 205 | is($driver->find_element('h1','tag_name')->get_text(),'Howdy Howdy Howdy', "get_text works (WD3)"); 206 | 207 | $driver->find_element('clickme','id')->click(); 208 | is(exception { $driver->dismiss_alert() }, undef, "Can click element (WD3)"); 209 | 210 | $driver->find_element('form','tag_name')->submit(); 211 | like($driver->get_page_source(),qr/ZIPPY/,"elem submit() works (WD3)"); 212 | 213 | #Pretty sure this one has enough 'inertia' to not disappear all the sudden 214 | $driver->get('http://w3.org/History.html'); 215 | $driver->add_cookie('foo','bar',undef,undef,0,0,time()+5000); 216 | is(scalar(@{$driver->get_all_cookies()}),1,"can set cookie (WD3)"); 217 | 218 | is($driver->get_cookie_named('foo')->{value},'bar',"can get cookie by name (WD3 only)"); 219 | 220 | $driver->delete_cookie_named('foo'); 221 | is(scalar(@{$driver->get_all_cookies()}),0,"can delete named cookies (WD3)"); 222 | 223 | is(exception { $driver->quit() }, undef, "Can quit (WD3)"); 224 | 225 | done_testing(); 226 | -------------------------------------------------------------------------------- /at/test-firefox.test: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | 4 | use Test::Selenium::Firefox; 5 | use Test::More tests => 3; 6 | use Test::Fatal; 7 | 8 | my $driver; 9 | is( exception { $driver = Test::Selenium::Firefox->new( 10 | extra_capabilities => { 11 | 'moz:firefoxOptions' => { 12 | args => [ '-headless' ], 13 | }, 14 | }, 15 | ); }, undef, "can spawn new Selenium::Firefox"); 16 | 17 | $driver->get('http://google.com'); 18 | 19 | TODO: { 20 | local $TODO = "This test must fail"; 21 | $driver->click_ok('not_here','css',"click on non-existant element doesn't croak"); 22 | }; 23 | 24 | 25 | is( exception { $driver->shutdown_binary; }, undef, "can shutdown binary correctly"); 26 | 27 | -------------------------------------------------------------------------------- /at/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Test Page 6 | 11 | 17 | 18 | 19 | 20 |

21 | Howdy Howdy Howdy 22 |

23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
32 | 33 | 34 |
35 | Test Link 36 |
37 |