change method call to subroutine call; Sel's docs are WRONG here
[catagits/Test-WWW-Selenium-Catalyst.git] / lib / Test / WWW / Selenium / Catalyst.pm
CommitLineData
4f6d213e 1package Test::WWW::Selenium::Catalyst;
2
3use warnings;
4use strict;
5use Carp;
6use Alien::SeleniumRC;
7use Test::WWW::Selenium;
8use Test::More;
9use Catalyst::Utils;
10
11BEGIN { $ENV{CATALYST_ENGINE} ||= 'HTTP'; }
12
13local $SIG{CHLD} = 'IGNORE';
14
15my $DEBUG = $ENV{CATALYST_DEBUG};
16my $app; # app name (MyApp)
17my $sel_pid; # pid of selenium server
18my $app_pid; # pid of myapp server
19
20=head1 NAME
21
1cdeb21f 22Test::WWW::Selenium::Catalyst - Test your Catalyst application with Selenium
4f6d213e 23
24=cut
25
26our $VERSION = '0.00_01';
27
1cdeb21f 28=head1 DEVELOPER RELEASE
29
30This is a developer release. It's working for me in production, but
31it depends on a Java application (SeleniumRC), which can be
32unreliable. On my Debian system, I had to put C<firefox-bin> in my
33path, and add C</usr/lib/firefox> to C<LD_LIBRARY_PATH>. Every distro
34and OS is different, so I'd like some feedback on how this works on
35your system. I would like to find a clean solution that lets this
36module "Just Work" for everyone, but I have a feeling that it's going
37to look more like C<if(gentoo){ ... } elsif (debian) { ... }> and so
38on. I can live with that, but I need your help to get to that stage!
39
40Please report any problems to RT, the Catalyst mailing list, or the
41#catalyst IRC channel on L<irc.perl.org>. Thanks!
42
4f6d213e 43=head1 SYNOPSIS
44
45 use Test::WWW::Selenium::Catalyst 'MyApp';
46 use Test::More tests => 2;
47
48 my $sel = Test::WWW::Selenium::Catalyst->start;
49 $sel->open_ok('/');
50 $sel->is_text_present_ok('Welcome to MyApp');
51
1cdeb21f 52This module starts the SeleniumRC server and your Catalyst app so that
53you can test it with SeleniumRC. Once you've called
6fd21f2e 54C<< Test::WWW::Selenium::Catalyst->start >>, everything is just like
1cdeb21f 55L<Test::WWW::Selenium|Test::WWW:Selenium>.
56
4f6d213e 57=head1 FUNCTIONS
58
59=head2 start
60
61Starts the Selenium and Catalyst servers, and returns a
62pre-initialized, ready-to-use Test::WWW::Selenium object.
63
64[NOTE] The selenium server is actually started when you C<use> this
65module, and it's killed when your test exits.
66
67=head2 sel_pid
68
69Returns the process ID of the Selenium Server.
70
71=head2 app_pid
72
73Returns the process ID of the Catalyst server.
74
75=cut
76
77
78sub _start_server {
79 # fork off a selenium server
80 my $pid;
81 if(0 == ($pid = fork())){
82 local $SIG{TERM} = sub {
6fd21f2e 83 diag("Selenium server $$ going down (TERM)") if $DEBUG;
4f6d213e 84 exit 0;
85 };
86
87 chdir '/';
88
89 if(!$DEBUG){
90 close *STDERR;
91 close *STDOUT;
e39d6317 92 #close *STDIN;
4f6d213e 93 }
94
95 diag("Selenium running in $$") if $DEBUG;
d5bcfeb7 96 Alien::SeleniumRC::start()
4f6d213e 97 or croak "Can't start Selenium server";
98 diag("Selenium server $$ going down") if $DEBUG;
99 exit 1;
100 }
101 $sel_pid = $pid;
102}
103
104sub sel_pid {
105 return $sel_pid;
106}
107
108sub app_pid {
109 return $app_pid;
110}
111
112sub import {
113 my ($class, $appname) = @_;
114 croak q{Specify your app's name} if !$appname;
115 $app = $appname;
116
117 my $d = $ENV{Catalyst::Utils::class2env($appname). "_DEBUG"}; # MYAPP_DEBUG
118 if(defined $d && $d){
119 $DEBUG = 1;
120 }
121 elsif(defined $d && $d == 0){
122 $DEBUG = 0;
123 }
124 # if it's something else, leave the CATALYST_DEBUG setting in tact
125
126 _start_server() or croak "Couldn't start selenium server";
127 return 1;
128}
129
130sub start {
131 my $class = shift;
132 my $args = shift || {};
133
134 # start a Catalyst MyApp server
135 eval("use $app");
136 croak "Couldn't load $app: $@" if $@;
137
138 my $pid;
139 if(0 == ($pid = fork())){
140 local $SIG{TERM} = sub {
141 diag("Catalyst server $$ going down (TERM)") if $DEBUG;
142 exit 0;
143 };
144 diag("Catalyst server running in $$") if $DEBUG;
145 $app->run('3000', 'localhost');
146 exit 1;
147 }
148 $app_pid = $pid;
149
150 my $tries = 5;
151 my $error;
152 my $sel;
153 while(!$sel && $tries--){
154 sleep 1;
155 diag("Waiting for selenium server to start")
156 if $DEBUG;
157
158 eval {
159 $sel = Test::WWW::Selenium->
160 new(host => 'localhost',
161 port => 4444,
162 browser => $args->{browser} || '*firefox',
163 browser_url => 'http://localhost:3000/'
164 );
165 };
166 $error = $@;
167 }
168
169 eval { $sel->start }
170 or croak "Can't start selenium: $@ (previous error: $error)";
171
172 return $sel;
173}
174
175END {
176 if($sel_pid){
177 diag("Killing Selenium Server $sel_pid") if $DEBUG;
178 kill 15, $sel_pid or diag "Killing Selenium: $!";
179 undef $sel_pid;
180 }
181 if($app_pid){
182 diag("Killing catalyst server $app_pid") if $DEBUG;
183 kill 15, $app_pid or diag "Killing MyApp: $!";
184 undef $app_pid;
185 }
186 diag("Waiting for children to die") if $DEBUG;
187 waitpid $sel_pid, 0 if $sel_pid;
188 waitpid $app_pid, 0 if $app_pid;
189}
190
191
192=head1 ENVIRONMENT
193
194Debugging messages are shown if C<CATALYST_DEBUG> or C<MYAPP_DEBUG>
195are set. C<MYAPP> is the name of your application, uppercased. (This
196is the same syntax as Catalyst itself.)
197
198=head1 DIAGNOSTICS
199
200=head2 Specify your app's name
201
202You need to pass your Catalyst app's name as the argument to the use
203statement:
204
205 use Test::WWW::Selenium::Catalyst 'MyApp'
206
207C<MyApp> is the name of your Catalyst app.
208
1cdeb21f 209=head1 SEE ALSO
210
211=over 4
212
213=item *
214
215Selenium website: L<http://www.openqa.org/>
216
217=item *
218
219Description of what you can do with the C<$sel> object: L<Test::WWW::Selenium>
220
221=item *
222
223If you don't need a real web browser: L<Test::WWW::Mechanize::Catalyst>
224
225=back
226
4f6d213e 227=head1 AUTHOR
228
229Jonathan Rockway, C<< <jrockway at cpan.org> >>
230
231=head1 BUGS
232
233Please report any bugs or feature requests to
234C<bug-test-www-selenium-catalyst at rt.cpan.org>, or through the web interface at
235L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Test-WWW-Selenium-Catalyst>.
236I will be notified, and then you'll automatically be notified of progress on
237your bug as I make changes.
238
239=head1 SUPPORT
240
241You can find documentation for this module with the perldoc command.
242
243 perldoc Test::WWW::Selenium::Catalyst
244
245You can also look for information at:
246
247=over 4
248
249=item * AnnoCPAN: Annotated CPAN documentation
250
251L<http://annocpan.org/dist/Test-WWW-Selenium-Catalyst>
252
253=item * CPAN Ratings
254
255L<http://cpanratings.perl.org/d/Test-WWW-Selenium-Catalyst>
256
257=item * RT: CPAN's request tracker
258
259L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Test-WWW-Selenium-Catalyst>
260
261=item * Search CPAN
262
263L<http://search.cpan.org/dist/Test-WWW-Selenium-Catalyst>
264
265=back
266
267=head1 ACKNOWLEDGEMENTS
268
1cdeb21f 269Thanks for mst for getting on my case to actually write this thing :)
270
4f6d213e 271=head1 COPYRIGHT & LICENSE
272
273Copyright 2006 Jonathan Rockway, all rights reserved.
274
275This program is free software; you can redistribute it and/or modify it
276under the same terms as Perl itself.
277
278=cut
279
2801; # End of Test::WWW::Selenium::Catalyst