add test_recursive method for easier multi-directory testing, factor out 'start every...
[scpubgit/Test-Harness-Selenium.git] / lib / Test / Harness / Selenium.pm
index 0df97e4..added88 100644 (file)
@@ -35,43 +35,59 @@ BEGIN {
 sub new {
   my $class = shift;
   my %args = @_;
-  if( $ENV{SELENIUM_RC_HOST} && 
-      $ENV{SELENIUM_RC_PORT} &&
-      $ENV{SELENIUM_RC_START} ) {
-    $args{selenium_rc}{host} = $ENV{SELENIUM_RC_HOST};
-    $args{selenium_rc}{port} = $ENV{SELENIUM_RC_PORT};
-    $args{selenium_rc}{start} = $ENV{SELENIUM_RC_START};
-  }
-  $args{selenium_rc}{xvnc_display} //= '0';
+  my $selrc = ($args{selenium_rc} ||={});
+  $selrc->{$_} = $ENV{"SELENIUM_RC_${\uc $_}"}
+    for grep exists $ENV{"SELENIUM_RC_${\uc $_}"},
+      qw(host port start start_xvnc xvnc_display);
+  $selrc->{xvnc_display} ||= '0';
+  $selrc->{host} ||= 'localhost';
+  $selrc->{port} ||= 4444;
+  $args{browser} ||= '*firefox';
   my $self = \%args;
   bless $self, $class;
 }
 
 sub start_selenium_server {
   my($self) = @_;
-  if($self->{selenium_rc}{start}) {
-    my $child = Child->new(sub {
-        system('ssh', $self->{selenium_rc}{host}, 'vncserver',
-          ":$self->{selenium_rc}{xvnc_display}");
-      }
-    );
-    $self->{selenium_rc}{xvnc_server_proc} = $child->start;
-    $child = Child->new(sub {
-        system('ssh', $self->{selenium_rc}{host}, 'env',
-          "DISPLAY=:$self->{selenium_rc}{xvnc_display}", 'selenium-rc', '-port',
-          $self->{selenium_rc}{port} );
+  my $selrc = $self->{selenium_rc};
+  if($selrc->{start}) {
+    my ($host, $display, $port) = @{$selrc}{qw(host xvnc_display port)};
+    my @do_ssh = $host eq 'localhost' ? () : ('ssh', $host);
+    if ($selrc->{start_xvnc}) {
+      $selrc->{xvnc_server_proc} = Child->new(
+          sub {
+            exec(
+              @do_ssh,
+              'vncserver', ":${display}",
+            );
+          }
+        )->start;
+      $selrc->{xvnc_started} = 1;
+      sleep 3;
+    }
+    $selrc->{selenium_server_proc} = Child->new(
+      sub {
+        exec(
+          @do_ssh,
+          'env', "DISPLAY=:${display}", 'selenium-rc', '-port', $port
+        )
       }
-    );
-    $self->{selenium_rc}{selenium_server_proc} = $child->start;
+    )->start;
+    sleep 1;
   }
   my $tries = 0;
   while($tries < 5) {
     eval {
+      # if we don't create the ::Selenium object ourselves, then
+      # wikifixture shuts the session down after the first test table
+      # is run, at which point KABOOM when you try and run a second one.
       $self->{src} = Socialtext::WikiFixture::Selenese->new(
-        host => $self->{selenium_rc}{host},
-        port => $self->{selenium_rc}{port},
-        browser => $self->{browser},
-        browser_url => $self->{app_base},
+        selenium => Test::WWW::Selenium->new(
+          host => $self->{selenium_rc}{host},
+          port => $self->{selenium_rc}{port},
+          browser => $self->{browser},
+          browser_url => $self->{app_base},
+        )
       );
     };
     $tries++;
@@ -86,53 +102,82 @@ sub start_selenium_server {
     diag "timed out waiting for selenium server to start at
     http://$self->{selenium_rc}{host}:$self->{selenium_rc}{port}" if $tries == 5;
     $self->done;
+    die;
   }
 }
 
 sub stop_selenium_server {
   my($self) = @_;
-  # okay, we're done, kill the server.
-  my $url = sprintf
-    "http://%s:%s/selenium-server/driver/?cmd=shutDownSeleniumServer",
-    $self->{selenium_rc}{host}, $self->{selenium_rc}{port};
-  get($url);
-  delete $self->{src};
-  $self->{selenium_rc}{selenium_server_proc}->kill("KILL");
-  my $child = Child->new(sub {
-      system('ssh', $self->{selenium_rc}{host}, 'vncserver', '-kill',
+  if (my $proc = delete $self->{selenium_rc}{selenium_server_proc}) {
+    my $url = sprintf
+      "http://%s:%s/selenium-server/driver/?cmd=shutDownSeleniumServer",
+      $self->{selenium_rc}{host}, $self->{selenium_rc}{port};
+    eval { get($url); }; # will fail if it never started
+    delete $self->{src};
+    $proc->kill("KILL");
+  }
+  if (delete $self->{selenium_rc}{xvnc_started}) {
+    my $host = $self->{selenium_rc}{host};
+    my @do_ssh = $host eq 'localhost' ? () : ('ssh', $host);
+    Child->new(sub {
+      exec(@do_ssh, 'vncserver', '-kill',
         ":$self->{selenium_rc}{xvnc_display}");
-    }
-  );
-  my $proc = $child->start;
-  $proc->wait;
+    })->start->wait;
+  }
 }
 
 sub start_app_server {
   my($self) = @_;
+  return unless $self->{app_server_cmd};
   my $child = Child->new(sub { exec($self->{app_server_cmd}) } );
   $self->{app_server_proc} = $child->start;
 }
 
 sub stop_app_server {
   my($self) = @_;
-  $self->{app_server_proc}->kill("KILL");
+  if (my $proc = $self->{app_server_proc}) {
+    $proc->kill("KILL");
+  }
 }
 
-sub test_directory {
-  my ($self, $dir) = @_;
+sub start_everything {
+  my ($self) = @_;
   if(!exists $self->{app_server_proc}) {
     $self->start_app_server;
   }
   if($self->{selenium_rc}{start} && !$self->{selenium_rc}{selenium_server_proc}) {
     $self->start_selenium_server;
   }
-  my @tests = File::Find::Rule->file()->name('*.html')->in($dir);
+}
+
+sub test_recursive {
+  my ($self, @proto) = @_;
+  my (@files, @dirs);
+  if (@proto) {
+    @files = grep /\.html$/, @proto;
+    @dirs = grep !/\.htmL$/, @proto;
+  } else {
+    $0 =~ /^(t\/.*).t$/ or die "Can't guess directory from $0";
+    @dirs = ($1);
+  }
+  $self->start_everything;
+  $self->test_file($_) for @files;
+  $self->test_directory($_) for
+    sort map File::Find::Rule->directory->in($_), @dirs;
+}
+
+sub test_directory {
+  my ($self, $dir) = @_;
+  $self->start_everything;
+  my @tests =
+    sort File::Find::Rule->file->name('*.html')->maxdepth(1)->in($dir);
+
   for my $test (@tests) {
-    $self->run_tests_for($test);
+    $self->test_file($test);
   }
 }
 
-sub run_tests_for {
+sub test_file {
   my ($self, $html_file) = @_;
   my $rows = $self->get_rows_for($html_file);
   $self->{src}->run_test_table($rows);
@@ -152,13 +197,12 @@ sub get_rows_for {
 
 sub done {
   my($self) = @_;
-  if(exists $self->{selenium_rc}{xvnc_server_proc} and 
-    exists $self->{selenium_rc}{selenium_server_proc}) {
-    $self->stop_selenium_server;
-  }
+  $self->stop_selenium_server;
   $self->stop_app_server;
 }
 
+sub DESTROY { shift->done }
+
 1;
 
 __END__