Search code examples
perlseleniumselenium-webdriverwww-mechanize

Saving groups of commands for later use in perl script


I'm working on my first Perl script here and trying to be as efficient as possible by re-using code instead of having the same code over and over. I've tried a couple different things already to no avail.

I'm also trying to avoid having to just import the set of commands from an external file, but it's looking like the only viable option right now. So I'm seeking advice here.

Here is the gist of the script (taking advantage of Selenium):

#!/usr/bin/perl
use strict;
use warnings;

use Getopt::Long;
use WWW::Selenium;

my @changepass;
my $addsub     = '';
my $add2sub    = '';

GetOptions (
    "changepass|cp=s{3}" => \@changepass,
    "addsub|as=s" => \$addsub,
    "add2sub|a2s=s" => \$add2sub,
    "help|h" => \&do_help
) or die(&do_help);


sub login {
  my $sel = WWW::Selenium->new(
      host => "localhost",
      port => 4444,
      browser => "*googlechrome",
      browser_url => "example.com",
  );
  $sel->start;
  $sel->open("/login.php");
  $sel->wait_for_page_to_load("5000");
  $sel->type("id=loginSection-username", "username");
  $sel->type("id=loginSection-password", "password");
  $sel->click("name=send");
  $sel->wait_for_page_to_load("30000");
  sleep(2);

  return $sel;
}


sub do_changepass {
  my $email = $changepass[0];
  my $oldpass = $changepass[1];
  my $newpass = $changepass[2];
  my ($sel) = @_;
  $sel->click("css=#my-webspaces-container .more > a");
  $sel->wait_for_page_to_load("30000");
  ...MORE COMMANDS...
}


if (@changepass) {
  print "Changing password...\n";
  my $sel = do_changepass();
  print "Finished!\n";
}

So I'd like to be able to reuse certain blocks of code such as the my $sel variable. But I do realize it's an object. If I could somehow just store it as plain text and then import it into the function. (not via an external file, if possible.)


Solution

  • To get working what you're trying to accomplish you have to take care about the scope of the $sel Object:

    ...
    
    if (@commands){
        my $sel = login();
        do_changepass($sel);
    }
    
    sub login {
        my $sel = WWW::Selenium->new( host => "localhost",
                                      port => 4444,
                                      browser => "*googlechrome",
                                      browser_url => "example.com",
                                    );
        $sel->start;
        $sel->open("/login.php");
        $sel->wait_for_page_to_load("5000");
        $sel->type("id=loginSection-username", "username");
        $sel->type("id=loginSection-password", "password");
        $sel->click("name=send");
        $sel->wait_for_page_to_load("30000");
        sleep(2);
    
        return $sel;
    }
    
    sub do_changepass {
        my $email = $changepass[0]; my $oldpass = $changepass[1]; my $newpass = $changepass[2];
        my ($sel) = @_;
        $sel->click("css=#my-webspaces-container .more > a");
        $sel->wait_for_page_to_load("30000");
        ...MORE COMMANDS...
    }
    ...
    

    my creates the variable with a lexical scope, so it will be gone after you leave the current block (and there are no references to it neither).

    or you can use the login-subroutine directly in the do_changepass

    ...
        sub do_changepass {
            my $email = $changepass[0]; my $oldpass = $changepass[1]; my $newpass = $changepass[2];
            my ($sel) = login(); # <--- login used here!!!
            $sel->click("css=#my-webspaces-container .more > a");
            $sel->wait_for_page_to_load("30000");
            ...MORE COMMANDS...
        }
    ...