Bläddra i källkod

skeleton of module & beginning of app server

George S. Baugh 5 år sedan
förälder
incheckning
977be40cb6
10 ändrade filer med 337 tillägg och 1 borttagningar
  1. 12 0
      .gitignore
  2. 4 0
      Changes
  3. 5 0
      MANIFEST.SKIP
  4. 18 1
      README.md
  5. 130 0
      bin/playwright.js
  6. 84 0
      dist.ini
  7. 13 0
      lib/Playwright.pm
  8. 1 0
      perlcriticrc
  9. 3 0
      tidyall.ini
  10. 67 0
      weaver.ini

+ 12 - 0
.gitignore

@@ -33,3 +33,15 @@ inc/
 /MANIFEST.bak
 /pm_to_blib
 /*.zip
+
+# VIM
+*.swp
+*.swo
+*.swn
+
+# Perltidy
+*.bak
+
+# Node stuff
+node_modules
+package-lock.json

+ 4 - 0
Changes

@@ -0,0 +1,4 @@
+Revision history for Playwright
+
+0.001   10-20-2020
+        - First version, released on an unsuspecting world.

+ 5 - 0
MANIFEST.SKIP

@@ -0,0 +1,5 @@
+MANIFEST.SKIP
+cover_db/*
+.travis.yml
+weaver.ini
+.git/*

+ 18 - 1
README.md

@@ -1,2 +1,19 @@
 # playwright-perl
-Perl bindings for playwright
+Perl bindings for [playwright][pw]
+
+## Has this ever happened to you?
+
+You're writing some acceptance test with [Selenium::Remote:Driver][srd], but you figure out selenium is a dead protocol?
+Finally, a solution!
+
+## Here's how it works
+
+A little node webserver written in [express][xp] is spun up which exposes the entire playwright API.
+You build a bunch of little actions to do much like action chains in Selenium, and then make 'em go whir.
+
+The best way to do this is probably using [Promise::XS][xs].
+
+## How2develop
+
+npm i playwright express
+perl -Ilib example.pl

+ 130 - 0
bin/playwright.js

@@ -0,0 +1,130 @@
+#!/usr/bin/node
+
+"use strict";
+
+const yargs = require('yargs');
+const uuid = require('uuid');
+const express = require('express');
+const { chromium, firefox, webkit, devices } = require('playwright');
+
+const fs = require('fs');
+
+//TODO use this to define the interface for /command
+let rawdata = fs.readFileSync('api.json');
+let spec = JSON.parse(rawdata);
+
+//console.log(spec);
+
+//TODO support device commands
+const argv = yargs
+    .command('firefox', 'Starts a playwright instance of firefox', {
+        firefox: {
+            description: 'Start a firefox instance',
+            alias: 'f',
+            type: 'boolean',
+        }
+    })
+    .command('chrome', 'Starts a playwright instance of chrome', {
+        chrome: {
+            description: 'Start a chrome instance',
+            alias: 'c',
+            type: 'boolean',
+        }
+    })
+    .command('webkit', 'Starts a playwright instance of webkit', {
+        webkit: {
+            description: 'Start a webkit instance',
+            alias: 'w',
+            type: 'boolean',
+        }
+    })
+    .option('port', {
+        alias: 'p',
+        description: 'Run on specified port',
+        type: 'number',
+    })
+    .option('visible', {
+        alias: 'v',
+        description: 'Run with headless mode off',
+        type: 'boolean',
+    })
+    .help()
+    .alias('help', 'h')
+    .argv;
+
+const app = express();
+const port = argv.port || 6969;
+
+var browser;
+var pages = {};
+
+//XXX this is probably a race but I don't care yet
+(async () => {
+    var browser;
+    if (argv._.includes('firefox')) {
+        browser = await firefox.launch( { "headless" : !argv.visible } );
+    }
+    if (argv._.includes('chrome')) {
+        browser = await chrome.launch( { "headless" : !argv.visible } );
+    }
+    if (argv._.includes('webkit')) {
+        browser = await webkit.launch( { "headless" : !argv.visible } );
+    }
+
+    if (!browser) {
+        console.log(argv);
+        console.log('no browser selected, begone');
+        process.exit(1);
+    }
+    pages.default = await browser.newPage();
+    pages.default.goto('http://google.com');
+    console.log('Browser Ready for use');
+
+})();
+
+var results = {};
+
+app.use(express.json())
+//app.use(express.urlencoded({ extended: true }))
+app.get('/command', (req, res) => {
+
+	var payload = req.body;
+    var page = payload.page;
+    var command = payload.command;
+    var result = {};
+	if (pages[page]) {
+        if (pages[page][command]) {
+            //TODO execute, return result
+            result = { error : false, value : command, type : "page" };
+        } else {
+            result = { error : true, message : "Invalid command '" + command + "' to issue to page '" + page + "'." };
+        }
+    } else if (browser[command]) {
+        //TODO execute, return result
+        result = { error : false, value : command, type : "global" };
+    } else {
+        result = { error : true, message : "No such page, or " + command + " is not a globally recognized command for puppeteer" };
+    }
+    res.json(result);
+});
+
+// XXX this hangs for some reason.
+// Maybe I shouldn't care and just send SIGTERM tho
+// ^C seems to not leave zommies
+app.get('/shutdown', (req, res) => {
+    (async () => {i
+        console.log('shutting down...');
+        await browser.close();
+        console.log('done');
+        process.exit(0);
+
+        res.send("Sent kill signal to browser");
+    });
+});
+
+//Modulino
+if (require.main === module) {
+    app.listen( port, () => {
+	    console.log(`Listening on port ${port}`);
+    });
+}

+ 84 - 0
dist.ini

@@ -0,0 +1,84 @@
+name = Playwright
+version = 0.001
+author = George S. Baugh <george@troglodyne.net>
+license = MIT
+copyright_holder = Troglodyne LLC
+copyright_year = 2020
+
+[GatherDir]
+include_dotfiles = 1
+exclude_match = .*\.swp
+exclude_match = .*\.swo
+
+[PruneCruft]
+except = \.travis.yml
+
+[ManifestSkip]
+[MetaYAML]
+[MetaJSON]
+[License]
+[Readme]
+[ExtraTests]
+[ExecDir]
+[ShareDir]
+[MakeMaker]
+[Manifest]
+
+[PkgVersion]
+[AutoPrereqs]
+[MetaProvides::Package]
+
+[PodWeaver]
+finder = :NotTestSRD
+
+; skip the Test::SRD modules, their attribution is non-standard
+[FileFinder::ByName / :NotTestSRD]
+dir = lib
+match = \.pm$
+skip = Test
+
+[Git::Contributors]
+
+; XXX can't tidy this mess yet
+;[TidyAll]
+
+; Unfortunately CPAN changes detects the first date incorrectly.  Oh well...
+; Unfortunately the Manifest test does not work for unknown reasons.
+[@TestingMania]
+critic_config = perlcriticrc
+disable = Test::CPAN::Changes
+disable = Test::DistManifest
+
+[TestRelease]
+[ConfirmRelease]
+[UploadToCPAN]
+
+[CheckMetaResources]
+[CheckPrereqsIndexed]
+[CheckChangesHasContent]
+
+[Prereqs / RuntimeRequires]
+perl = 5.010
+Moo = 1.005
+List::Util = 1.33
+
+[GithubMeta]
+issues = 1
+user = teodesian
+
+[Encoding]
+filename = t/www/icon.gif
+filename = t/www/invalid-extension.xpi
+filename = t/www/redisplay.xpi
+encoding = bytes
+
+; `dzil authordeps` doesn't know about the Pod Weaver dependenciess:
+; authordep Pod::Weaver::Section::Contributors = 0
+; authordep Pod::Weaver::Plugin::Encoding = 0
+; authordep Pod::Weaver::Section::SeeAlso = 0
+; authordep Pod::Weaver::Section::GenerateSection = 0
+; authordep Pod::Elemental::Transformer::List = 0
+; authordep XML::Simple = 0
+; authordep Test::LWP::UserAgent = 0
+; authordep Test::Pod::Coverage = 0
+; authordep Term::UI = 0

+ 13 - 0
lib/Playwright.pm

@@ -0,0 +1,13 @@
+package Playwright;
+
+use strict;
+use warnings;
+
+no warnings 'experimental';
+use feature qw{signatures state};
+
+sub new (%options) {
+
+}
+
+1;

+ 1 - 0
perlcriticrc

@@ -0,0 +1 @@
+exclude = RequireUseStrict|RequireUseWarnings|ProhibitSubroutinePrototypes

+ 3 - 0
tidyall.ini

@@ -0,0 +1,3 @@
+[PerlTidy]
+select = {lib,bin}/**/*
+argv = -noll -it=2

+ 67 - 0
weaver.ini

@@ -0,0 +1,67 @@
+[@CorePrep]
+
+[-SingleEncoding]
+
+[Name]
+[Version]
+
+[Region  / prelude]
+
+[Generic / SYNOPSIS]
+[Generic / DESCRIPTION]
+[Generic / OVERVIEW]
+
+[Collect / ATTRIBUTES]
+command = attr
+
+[Collect / METHODS]
+command = method
+
+[Collect / FUNCTIONS]
+command = func
+
+[Leftovers]
+
+[SeeAlso]
+[Bugs]
+
+[Region  / postlude]
+
+; [Authors]
+[GenerateSection / AUTHORS ]
+text = Current Maintainers:
+text =
+text = =over 4
+text =
+text = =item *
+text =
+text = George S. Baugh <teodesian@gmail.com>
+text =
+text = =back
+
+
+[Contributors]
+[GenerateSection / COPYRIGHT AND LICENSE]
+text = Copyright (c) 2020 Troglodyne LLC
+text =
+text =
+text = Permission is hereby granted, free of charge, to any person obtaining a copy
+text = of this software and associated documentation files (the "Software"), to deal
+text = in the Software without restriction, including without limitation the rights
+text = to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+text = copies of the Software, and to permit persons to whom the Software is
+text =furnished to do so, subject to the following conditions:
+
+text = The above copyright notice and this permission notice shall be included in all
+text =copies or substantial portions of the Software.
+
+text = THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+text = IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+text = FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+text = AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+text = LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+text = OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+text = SOFTWARE.
+
+[-Transformer]
+transformer = List