ソースを参照

Merge branch 'main' of github.com:teodesian/playwright-perl into main

George S. Baugh 4 年 前
コミット
e9a4d56f03
6 ファイル変更53 行追加6 行削除
  1. 7 0
      README.md
  2. 34 3
      bin/playwright_server
  3. 2 0
      example.pl
  4. 3 3
      lib/Playwright.pm
  5. 1 0
      lib/Playwright/Base.pm
  6. 6 0
      lib/Playwright/Util.pm

+ 7 - 0
README.md

@@ -26,6 +26,13 @@ Everything newer than 5.28 is supported.
 Things should work on 5.20 or newer, but...
 Things should work on 5.20 or newer, but...
 Tests might fail due to Temp file weirdness with Test::MockFile.
 Tests might fail due to Temp file weirdness with Test::MockFile.
 
 
+## Supported OS
+
+Everything seems to work fine on OSX and Linux.
+
+On Windows, you will have to approve a UAC prompt to exempt playwright_server from being firewalled off.
+
+
 ## How2develop
 ## How2develop
 
 
 Everything should more or less set itself up automatically, or explode and tell you what to do.
 Everything should more or less set itself up automatically, or explode and tell you what to do.

+ 34 - 3
bin/playwright_server

@@ -14,18 +14,50 @@ const path = require('path');
 let sharedir = require.resolve('playwright'); // api.json should be shipped with playwright itself
 let sharedir = require.resolve('playwright'); // api.json should be shipped with playwright itself
 var theFile = path.dirname(sharedir) + '/api.json';
 var theFile = path.dirname(sharedir) + '/api.json';
 let rawdata = fs.readFileSync(theFile);
 let rawdata = fs.readFileSync(theFile);
+
+// On newer versions of playwright, instead of using hash tables they just lazily output arrays, so we have to convert this
 let spec = JSON.parse(rawdata);
 let spec = JSON.parse(rawdata);
 
 
-// Establish argument order for callers
+function arr2hash (arr,primary_key) {
+    var inside_out = {};
+    for (var item of arr) {
+        inside_out[item.name] = item;
+    }
+    return inside_out;
+}
+
+var fix_it=false;
+if (spec instanceof Array) {
+    fix_it = true;
+    spec = arr2hash(spec,'name');
+}
+
+// Establish argument order for callers, and correct spec array-ification
 for (var classname of Object.keys(spec)) {
 for (var classname of Object.keys(spec)) {
+    if (spec[classname].members instanceof Array) {
+        spec[classname].members = arr2hash(spec[classname].members,'name');
+    }
     for (var method of Object.keys(spec[classname].members)) {
     for (var method of Object.keys(spec[classname].members)) {
         var order = 0;
         var order = 0;
+        if (spec[classname].members[method].args instanceof Array) {
+            spec[classname].members[method].args = arr2hash(spec[classname].members[method].args,'name');
+        }
         for (var arg of Object.keys(spec[classname].members[method].args) ) {
         for (var arg of Object.keys(spec[classname].members[method].args) ) {
             spec[classname].members[method].args[arg].order = order++;
             spec[classname].members[method].args[arg].order = order++;
         }
         }
     }
     }
 }
 }
 
 
+//XXX spec is wrong here unfortunately
+if (fix_it) {
+    for (var className of ['Page','Frame']) {
+        spec[className].members.$$     = spec[className].members.querySelectorAll;
+        spec[className].members.$      = spec[className].members.querySelector;
+        spec[className].members.$$eval = spec[className].members.evalOnSelectorAll;
+        spec[className].members.$eval  = spec[className].members.evalOnSelector;
+    }
+}
+
 const argv = yargs
 const argv = yargs
     .option('debug', {
     .option('debug', {
         alias: 'd',
         alias: 'd',
@@ -112,7 +144,6 @@ app.post('/command', async (req, res) => {
                     ...args
                     ...args
                 ];
                 ];
             }
             }
-
             const res = await subject[command](...args);
             const res = await subject[command](...args);
             result = { error : false, message : res };
             result = { error : false, message : res };
 
 
@@ -150,7 +181,7 @@ app.post('/command', async (req, res) => {
             result = { error : true, message : e.message };
             result = { error : true, message : e.message };
         }
         }
     } else {
     } else {
-        result = { error : true, message : "No such object, or " + command + " is not a globally recognized command for puppeteer" };
+        result = { error : true, message : "No such object, or " + command + " is not a globally recognized command for Playwright" };
     }
     }
 
 
     res.json(result);
     res.json(result);

+ 2 - 0
example.pl

@@ -51,6 +51,8 @@ print Dumper($result);
 $page->on('console',"return [...arguments]");
 $page->on('console',"return [...arguments]");
 
 
 my $promise = $page->waitForEvent('console');
 my $promise = $page->waitForEvent('console');
+#XXX this *can* race
+sleep 1;
 $page->evaluate("console.log('hug')");
 $page->evaluate("console.log('hug')");
 my $console_log = $handle->await( $promise );
 my $console_log = $handle->await( $promise );
 
 

+ 3 - 3
lib/Playwright.pm

@@ -18,7 +18,7 @@ use Net::EmptyPort();
 use JSON::MaybeXS();
 use JSON::MaybeXS();
 use File::Slurper();
 use File::Slurper();
 use File::Which();
 use File::Which();
-use Capture::Tiny qw{capture_stderr};
+use Capture::Tiny qw{capture capture_stderr};
 use Carp qw{confess};
 use Carp qw{confess};
 
 
 use Playwright::Base();
 use Playwright::Base();
@@ -136,7 +136,6 @@ sub _check_node {
     confess("Can't locate Playwright server in '$server_bin'!")
     confess("Can't locate Playwright server in '$server_bin'!")
       unless -f $server_bin;
       unless -f $server_bin;
 
 
-    #TODO make this portable with File::Which etc
     # Check that node and npm are installed
     # Check that node and npm are installed
     $node_bin = File::Which::which('node');
     $node_bin = File::Which::which('node');
     confess("node must exist and be executable") unless -x $node_bin;
     confess("node must exist and be executable") unless -x $node_bin;
@@ -149,7 +148,7 @@ sub _check_node {
     {
     {
         #XXX the node Depsolver is deranged, global modules DO NOT WORK
         #XXX the node Depsolver is deranged, global modules DO NOT WORK
         my $curdir = pushd(File::Basename::dirname($server_bin));
         my $curdir = pushd(File::Basename::dirname($server_bin));
-        capture_stderr { $dep_raw = qx{$npm_bin list --json} };
+        ($dep_raw) = capture { system($npm_bin, qw{list --json}) };
         confess("Could not list available node modules!") unless $dep_raw;
         confess("Could not list available node modules!") unless $dep_raw;
 
 
         chomp $dep_raw;
         chomp $dep_raw;
@@ -307,6 +306,7 @@ sub _check_and_build_spec ($self) {
     $spec = Playwright::Util::request(
     $spec = Playwright::Util::request(
         'GET', 'spec', $self->{port}, $self->{ua},
         'GET', 'spec', $self->{port}, $self->{ua},
     );
     );
+
     confess("Could not retrieve Playwright specification.  Check that your playwright installation is correct and complete.") unless ref $spec eq 'HASH';
     confess("Could not retrieve Playwright specification.  Check that your playwright installation is correct and complete.") unless ref $spec eq 'HASH';
     return $spec;
     return $spec;
 }
 }

+ 1 - 0
lib/Playwright/Base.pm

@@ -72,6 +72,7 @@ sub _coerce ( $spec, %args ) {
             $args{args}[$i] = $truthy ? JSON::true : JSON::false;
             $args{args}[$i] = $truthy ? JSON::true : JSON::false;
         }
         }
         elsif ( $type->{name} eq 'Object' ) {
         elsif ( $type->{name} eq 'Object' ) {
+            $type->{properties} = Playwright::Util::arr2hash($type->{properties},'name') if ref $type->{properties} eq 'ARRAY';
             foreach my $prop ( keys( %{ $type->{properties} } ) ) {
             foreach my $prop ( keys( %{ $type->{properties} } ) ) {
                 next unless exists $arg->{$prop};
                 next unless exists $arg->{$prop};
                 my $truthy = int( !!$arg->{$prop} );
                 my $truthy = int( !!$arg->{$prop} );

+ 6 - 0
lib/Playwright/Util.pm

@@ -35,4 +35,10 @@ sub request ( $method, $url, $port, $ua, %args ) {
     return $msg;
     return $msg;
 }
 }
 
 
+sub arr2hash ($array,$primary_key) {
+    my $inside_out = {};
+    @$inside_out{map { $_->{$primary_key} } @$array} = @$array;
+    return $inside_out;
+}
+
 1;
 1;