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.
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_seleniun_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->do_command('shutDown');
252 diag("Killing Selenium Server $sel_pid") if $DEBUG;
253 kill 15, $sel_pid or diag "Killing Selenium: $!";
256 } elsif ($www_selenium) {
257 diag("Stopping Selenium Session $sel_pid") if $DEBUG;
258 $www_selenium->stop();
263 diag("Killing catalyst server $app_pid") if $DEBUG;
264 kill 15, $app_pid or diag "Killing MyApp: $!";
267 diag("Waiting for children to die") if $DEBUG;
268 waitpid $sel_pid, 0 if $sel_pid;
269 waitpid $app_pid, 0 if $app_pid;
275 Debugging messages are shown if C<CATALYST_DEBUG> or C<MYAPP_DEBUG>
276 are set. C<MYAPP> is the name of your application, uppercased. (This
277 is the same syntax as Catalyst itself.)
279 C<CATALYST_SERVER> can be set to test against an externally running server,
280 in a similar manner to how L<Test::WWW::Mechanize::Catalyst> behaves.
282 The port that the application sever runs on can be affected by C<MYAPP_PORT>
283 in addition to being specifiable in the arguments passed to start.
287 =head2 Specify your app's name
289 You need to pass your Catalyst app's name as the argument to the use
292 use Test::WWW::Selenium::Catalyst 'MyApp'
294 C<MyApp> is the name of your Catalyst app.
302 Selenium website: L<http://seleniumhq.org/>
306 Description of what you can do with the C<$sel> object: L<Test::WWW::Selenium>
311 If you don't need a real web browser: L<Test::WWW::Mechanize::Catalyst>
317 Ash Berlin C<< <ash@cpan.org> >>
319 Jonathan Rockway, C<< <jrockway at cpan.org> >>
323 Please report any bugs or feature requests to
324 C<bug-test-www-selenium-catalyst at rt.cpan.org>, or through the web interface at
325 L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Test-WWW-Selenium-Catalyst>.
326 I will be notified, and then you'll automatically be notified of progress on
327 your bug as I make changes.
331 Send me unified diffs against the git HEAD at:
333 git://github.com/jrockway/test-www-selenium-catalyst.git
335 You can view the repository online at
337 http://github.com/jrockway/test-www-selenium-catalyst/tree/master
339 Thanks in advance for your contributions!
341 =head1 ACKNOWLEDGEMENTS
343 Thanks for mst for getting on my case to actually write this thing :)
345 =head1 COPYRIGHT & LICENSE
347 Copyright 2009 Ash Berlin, all rights reserved.
349 Copyright 2006 Jonathan Rockway, all rights reserved.
351 This program is free software; you can redistribute it and/or modify it
352 under the same terms as Perl itself.
356 1; # End of Test::WWW::Selenium::Catalyst