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.05';
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.
78 Port on which to run the catalyst application server. The C<MYAPP_PORT>
79 environment variable is also respected.
84 B<Default>: Test::WWW::Selenium
86 Classname of Selenium object to create. Use this if you want to subclass
87 selenium to add custom logic.
93 Location of externally running selenium server if you do not wish this module
94 to control one. See also for details.
98 All other options passed verbatim to the selenium constructor.
100 B<NOTE>: By default a selenium server is started when you C<use> this module,
101 and it's killed when your test exits. If wish to manage a selenium server
102 yourself, (for instance you wish to start up a server once and run a number of
103 tests against it) pass C<-no_selenium_server> to import:
105 use Test::WWW::Selenium 'MyApp'
106 -no_selenium_server => 1
108 Along a similar vein you can also pass command line arguments to the selenium
109 server via C<-selenium_args>:
111 use Test::WWW::Selenium 'MyApp'
112 -selenium_args => "-singleWindow -port 4445"
116 Returns the process ID of the Selenium Server.
120 Returns the process ID of the Catalyst server.
126 my ($class, $args) = @_;
127 # fork off a selenium server
129 if(0 == ($pid = fork())){
130 local $SIG{TERM} = sub {
131 diag("Selenium server $$ going down (TERM)") if $DEBUG;
143 diag("Selenium running in $$") if $DEBUG;
144 $class->_start_selenium($args);
145 diag("Selenium server $$ going down") if $DEBUG;
151 # Moved out to be subclassable seperately to the fork logic
152 sub _start_selenium {
153 my ($class, $arg) = @_;
154 $arg = '' unless defined $arg;
155 Alien::SeleniumRC::start($arg)
156 or croak "Can't start Selenium server";
168 my ($class, $appname, %args) = @_;
170 croak q{Specify your app's name} if !$appname;
173 my $d = $ENV{Catalyst::Utils::class2env($appname). "_DEBUG"}; # MYAPP_DEBUG
178 unless ($args{-no_selenium_server}) {
179 $class->_start_server($args{-selenium_args}) or croak "Couldn't start selenium server";
186 my $args = shift || {};
188 my $port = delete $args->{port};
189 $port ||= $ENV{Catalyst::Utils::class2env($app). "_PORT"} # MYAPP_PORT
194 # Check for CATALYST_SERVER env var like TWMC does.
195 if ( $ENV{CATALYST_SERVER} ) {
196 $uri = $ENV{CATALYST_SERVER};
197 } elsif ( $args->{app_uri} ) {
198 $uri = delete $args->{app_uri}
200 # start a Catalyst MyApp server
202 croak "Couldn't load $app: $@" if $@;
205 if(0 == ($pid = fork())){
206 local $SIG{TERM} = sub {
207 diag("Catalyst server $$ going down (TERM)") if $DEBUG;
210 diag("Catalyst server running in $$") if $DEBUG;
211 $app->run($port, 'localhost');
214 $uri = 'http://localhost:' . $port;
220 my $sel_class = delete $args->{selenium_class} || 'Test::WWW::Selenium';
223 while(!$sel && $tries--){
225 diag("Waiting for selenium server to start")
229 $sel = $sel_class->new(
230 host => delete $args->{selenium_host} || 'localhost',
231 port => delete $args->{selenium_port} || 4444,
232 browser => '*firefox',
240 croak "Can't start selenium: $error" if $error;
242 return $www_selenium = $sel;
248 diag("Shutting down Selenium Server $sel_pid") if $DEBUG;
249 $www_selenium->stop();
250 $www_selenium->do_command('shutDown');
253 diag("Killing Selenium Server $sel_pid") if $DEBUG;
254 kill 15, $sel_pid or diag "Killing Selenium: $!";
257 } elsif ($www_selenium) {
258 diag("Stopping Selenium Session $sel_pid") if $DEBUG;
259 $www_selenium->stop();
264 diag("Killing catalyst server $app_pid") if $DEBUG;
265 kill 15, $app_pid or diag "Killing MyApp: $!";
268 diag("Waiting for children to die") if $DEBUG;
269 waitpid $sel_pid, 0 if $sel_pid;
270 waitpid $app_pid, 0 if $app_pid;
276 Debugging messages are shown if C<CATALYST_DEBUG> or C<MYAPP_DEBUG>
277 are set. C<MYAPP> is the name of your application, uppercased. (This
278 is the same syntax as Catalyst itself.)
280 C<CATALYST_SERVER> can be set to test against an externally running server,
281 in a similar manner to how L<Test::WWW::Mechanize::Catalyst> behaves.
283 The port that the application sever runs on can be affected by C<MYAPP_PORT>
284 in addition to being specifiable in the arguments passed to start.
288 =head2 Specify your app's name
290 You need to pass your Catalyst app's name as the argument to the use
293 use Test::WWW::Selenium::Catalyst 'MyApp'
295 C<MyApp> is the name of your Catalyst app.
303 Selenium website: L<http://seleniumhq.org/>
307 Description of what you can do with the C<$sel> object: L<Test::WWW::Selenium>
312 If you don't need a real web browser: L<Test::WWW::Mechanize::Catalyst>
318 Ash Berlin C<< <ash@cpan.org> >>
320 Jonathan Rockway, C<< <jrockway at cpan.org> >>
324 Please report any bugs or feature requests to
325 C<bug-test-www-selenium-catalyst at rt.cpan.org>, or through the web interface at
326 L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Test-WWW-Selenium-Catalyst>.
327 I will be notified, and then you'll automatically be notified of progress on
328 your bug as I make changes.
332 Send me unified diffs against the git HEAD at:
334 git://github.com/jrockway/test-www-selenium-catalyst.git
336 You can view the repository online at
338 http://github.com/jrockway/test-www-selenium-catalyst/tree/master
340 Thanks in advance for your contributions!
342 =head1 ACKNOWLEDGEMENTS
344 Thanks for mst for getting on my case to actually write this thing :)
346 =head1 COPYRIGHT & LICENSE
348 Copyright 2009 Ash Berlin, all rights reserved.
350 Copyright 2006 Jonathan Rockway, all rights reserved.
352 This program is free software; you can redistribute it and/or modify it
353 under the same terms as Perl itself.
357 1; # End of Test::WWW::Selenium::Catalyst