1 package Test::WWW::Selenium::Catalyst;
7 use Test::WWW::Selenium;
11 BEGIN { $ENV{CATALYST_ENGINE} ||= 'HTTP'; }
13 local $SIG{CHLD} = 'IGNORE';
15 our $DEBUG = $ENV{CATALYST_DEBUG};
16 our $app; # app name (MyApp)
17 our $sel_pid; # pid of selenium server
18 our $app_pid; # pid of myapp server
23 Test::WWW::Selenium::Catalyst - Test your Catalyst application with Selenium
27 our $VERSION = '0.03';
29 =head1 DEVELOPERISH RELEASE
31 This is still a test release. It's working for me in production, but
32 it depends on a Java application (SeleniumRC), which can be
33 unreliable. On my Debian system, I had to put C<firefox-bin> in my
34 path, and add C</usr/lib/firefox> to C<LD_LIBRARY_PATH>. Every distro
35 and OS is different, so I'd like some feedback on how this works on
36 your system. I would like to find a clean solution that lets this
37 module "Just Work" for everyone, but I have a feeling that it's going
38 to look more like C<if(gentoo){ ... } elsif (debian) { ... }> and so
39 on. I can live with that, but I need your help to get to that stage!
41 Please report any problems to RT, the Catalyst mailing list, or the
42 #catalyst IRC channel on L<irc.perl.org>. Thanks!
46 use Test::WWW::Selenium::Catalyst 'MyApp', 'command line to selenium';
47 use Test::More tests => 2;
49 my $sel = Test::WWW::Selenium::Catalyst->start;
51 $sel->is_text_present_ok('Welcome to MyApp');
53 This module starts the SeleniumRC server and your Catalyst app so that
54 you can test it with SeleniumRC. Once you've called
55 C<< Test::WWW::Selenium::Catalyst->start >>, everything is just like
56 L<Test::WWW::Selenium|Test::WWW:Selenium>.
62 Starts the Selenium and Catalyst servers, and returns a pre-initialized,
63 ready-to-use Test::WWW::Selenium object.
71 URI at which the application can be reached. If this is specified then no
72 application server will be started.
76 Port on which to run the catalyst application server. The C<MYAPP_PORT>
77 environment variable is also respected.
82 B<Default>: Test::WWW::Selenium
84 Classname of Selenium object to create. Use this if you want to subclass
85 selenium to add custom logic.
91 Location of externally running selenium server if you do not wish this module
92 to control one. See also below for details.
96 All other options passed verbatim to the selenium constructor.
98 B<NOTE>: By default a selenium server is started when you C<use> this module, and
99 it's killed when your test exits. If wish to manage a selenium server yourself,
100 (for instance you wish to start up a server once and run a number of tests
101 against it) pass C<-no_selenium_server> to import:
103 use Test::WWW::Selenium 'MyApp'
104 -no_selenium_server = 1
106 Along a similar vein you can also pass command line arguments to the selenium
107 server via C<-selenium_args>:
109 use Test::WWW::Selenium 'MyApp'
110 -selenium_args = "-singleWindow -port 4445"
114 Returns the process ID of the Selenium Server.
118 Returns the process ID of the Catalyst server.
124 my ($class, $args) = @_;
125 # fork off a selenium server
127 if(0 == ($pid = fork())){
128 local $SIG{TERM} = sub {
129 diag("Selenium server $$ going down (TERM)") if $DEBUG;
141 diag("Selenium running in $$") if $DEBUG;
142 $class->_start_selenium($args);
143 diag("Selenium server $$ going down") if $DEBUG;
149 # Moved out to be subclassable seperately to the fork logic
150 sub _start_selenium {
151 my ($class, $arg) = @_;
152 $arg = '' unless defined $arg;
153 Alien::SeleniumRC::start($arg)
154 or croak "Can't start Selenium server";
166 my ($class, $appname, %args) = @_;
168 croak q{Specify your app's name} if !$appname;
171 my $d = $ENV{Catalyst::Utils::class2env($appname). "_DEBUG"}; # MYAPP_DEBUG
176 unless ($args{-no_seleniun_server}) {
177 $class->_start_server($args{-selenium_args}) or croak "Couldn't start selenium server";
184 my $args = shift || {};
186 my $port = delete $args->{port};
187 $port ||= $ENV{Catalyst::Utils::class2env($app). "_PORT"} # MYAPP_PORT
192 # Check for CATALYST_SERVER env var like TWMC does.
193 if ( $ENV{CATALYST_SERVER} ) {
194 $uri = $ENV{CATALYST_SERVER};
195 } elsif ( $args->{app_uri} ) {
196 $uri = delete $args->{app_uri}
198 # start a Catalyst MyApp server
200 croak "Couldn't load $app: $@" if $@;
203 if(0 == ($pid = fork())){
204 local $SIG{TERM} = sub {
205 diag("Catalyst server $$ going down (TERM)") if $DEBUG;
208 diag("Catalyst server running in $$") if $DEBUG;
209 $app->run($port, 'localhost');
212 $uri = 'http://localhost:' . $port;
218 my $sel_class = delete $args->{selenium_class} || 'Test::WWW::Selenium';
221 while(!$sel && $tries--){
223 diag("Waiting for selenium server to start")
227 $sel = $sel_class->new(
228 host => delete $args->{selenium_host} || 'localhost',
229 port => delete $args->{selenium_port} || 4444,
230 browser => '*firefox',
238 croak "Can't start selenium: $error" if $error;
240 return $www_selenium = $sel;
246 diag("Shutting down Selenium Server $sel_pid") if $DEBUG;
247 $www_selenium->do_command('shutDown');
250 diag("Killing Selenium Server $sel_pid") if $DEBUG;
251 kill 15, $sel_pid or diag "Killing Selenium: $!";
255 diag("Killing catalyst server $app_pid") if $DEBUG;
256 kill 15, $app_pid or diag "Killing MyApp: $!";
259 diag("Waiting for children to die") if $DEBUG;
260 waitpid $sel_pid, 0 if $sel_pid;
261 waitpid $app_pid, 0 if $app_pid;
267 Debugging messages are shown if C<CATALYST_DEBUG> or C<MYAPP_DEBUG>
268 are set. C<MYAPP> is the name of your application, uppercased. (This
269 is the same syntax as Catalyst itself.)
271 C<CATALYST_SERVER> can be set to test against an externally running server,
272 in a similar manner to how L<Test::WWW::Mechanize::Catalyst> behaves.
274 The port that the application sever runs on can be affected by C<MYAPP_PORT>
275 in addition to being specifiable in the arguments passed to start.
279 =head2 Specify your app's name
281 You need to pass your Catalyst app's name as the argument to the use
284 use Test::WWW::Selenium::Catalyst 'MyApp'
286 C<MyApp> is the name of your Catalyst app.
294 Selenium website: L<http://www.openqa.org/>
298 Description of what you can do with the C<$sel> object: L<Test::WWW::Selenium>
302 If you don't need a real web browser: L<Test::WWW::Mechanize::Catalyst>
308 Jonathan Rockway, C<< <jrockway at cpan.org> >>
312 Please report any bugs or feature requests to
313 C<bug-test-www-selenium-catalyst at rt.cpan.org>, or through the web interface at
314 L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Test-WWW-Selenium-Catalyst>.
315 I will be notified, and then you'll automatically be notified of progress on
316 your bug as I make changes.
320 Send me unified diffs against the git HEAD at:
322 git://git.jrock.us/Test-WWW-Selenium-Catalyst
324 You can view the repository online at
326 http://git.jrock.us/?p=Test-WWW-Selenium-Catalyst.git;a=summary
328 Thanks in advance for your contributions!
330 =head1 ACKNOWLEDGEMENTS
332 Thanks for mst for getting on my case to actually write this thing :)
334 =head1 COPYRIGHT & LICENSE
336 Copyright 2006 Jonathan Rockway, all rights reserved.
338 This program is free software; you can redistribute it and/or modify it
339 under the same terms as Perl itself.
343 1; # End of Test::WWW::Selenium::Catalyst