Playwright-perl: Perl Bindings for Playwright

playwright-perl 

Perl bindings for playwright, the amazing cross browser testing framework from Microsoft

Has this ever happened to you?

You're writing some acceptance test with Selenium::Remote:Driver, but you figure out selenium is a dead protocol? Finally, a solution!

Here's how it works

A little node webserver written in express is spun up which exposes the entire playwright API. We ensure the node deps are installed in a BEGIN block, and then spin up the proxy server. You then use playwright more or less as normal; see the POD in Playwright.pm for more details.

See example.pl for usage examples.

Supported Perls

Everything newer than 5.28 is supported.

Things should work on 5.20 or newer, but... 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

Everything should more or less set itself up automatically, or explode and tell you what to do. I assume you know how to get cpanm.

You might want to use distro packages for some of these:

sudo cpanm Dist::Zilla
dzil authordeps --missing | sudo cpanm
dzil listdeps --missing | sudo cpanm

From there you'll need nvm to get the latest verison of node working:

wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash
source ~/.bashrc
nvm install
nvm use

Running dzil test should let you know if your kit is good to develop.

Actually running stuff will look like this after you generate the API json and modules:

PATH="$(pwd)/bin:$PATH" perl -Ilib example.pl

Dealing with api.json and generating modules

Playwright doesn't ship their api.json with the distribution on NPM. You have to generate it from their repo.

clone it in a directory that is the same as the one containing this repository. then run generate_api_json.sh to get things working such that the build scripts know what to do.

Then run generate_perl_modules.pl to get the accessor classes built based off of the spec, and insert the spec JSON into the playwright_server binary.

To make life simple, you can just run run_example in the TLD when debugging.

Questions?

Hop into the playwright slack, and check out the #playwright-perl channel therein. I'm watching that space and should be able to answer your questions. https://aka.ms/playwright-slack

Apparently Microsoft is trying to migrate to Github's built in forums, so I've activated discussions on this project too (see the tab at the top).

Author: Teodesian
Source Code: https://github.com/teodesian/playwright-perl 
License: MIT license

#node #playwright #perl 

What is GEEK

Buddha Community

Playwright-perl: Perl Bindings for Playwright

Playwright-perl: Perl Bindings for Playwright

playwright-perl 

Perl bindings for playwright, the amazing cross browser testing framework from Microsoft

Has this ever happened to you?

You're writing some acceptance test with Selenium::Remote:Driver, but you figure out selenium is a dead protocol? Finally, a solution!

Here's how it works

A little node webserver written in express is spun up which exposes the entire playwright API. We ensure the node deps are installed in a BEGIN block, and then spin up the proxy server. You then use playwright more or less as normal; see the POD in Playwright.pm for more details.

See example.pl for usage examples.

Supported Perls

Everything newer than 5.28 is supported.

Things should work on 5.20 or newer, but... 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

Everything should more or less set itself up automatically, or explode and tell you what to do. I assume you know how to get cpanm.

You might want to use distro packages for some of these:

sudo cpanm Dist::Zilla
dzil authordeps --missing | sudo cpanm
dzil listdeps --missing | sudo cpanm

From there you'll need nvm to get the latest verison of node working:

wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash
source ~/.bashrc
nvm install
nvm use

Running dzil test should let you know if your kit is good to develop.

Actually running stuff will look like this after you generate the API json and modules:

PATH="$(pwd)/bin:$PATH" perl -Ilib example.pl

Dealing with api.json and generating modules

Playwright doesn't ship their api.json with the distribution on NPM. You have to generate it from their repo.

clone it in a directory that is the same as the one containing this repository. then run generate_api_json.sh to get things working such that the build scripts know what to do.

Then run generate_perl_modules.pl to get the accessor classes built based off of the spec, and insert the spec JSON into the playwright_server binary.

To make life simple, you can just run run_example in the TLD when debugging.

Questions?

Hop into the playwright slack, and check out the #playwright-perl channel therein. I'm watching that space and should be able to answer your questions. https://aka.ms/playwright-slack

Apparently Microsoft is trying to migrate to Github's built in forums, so I've activated discussions on this project too (see the tab at the top).

Author: Teodesian
Source Code: https://github.com/teodesian/playwright-perl 
License: MIT license

#node #playwright #perl 

Apache Cayenne | Mirror Of Apache Cayenne Written in Java

Apache Cayenne

Apache Cayenne is an open source persistence framework licensed under the Apache License, providing object-relational mapping (ORM) and remoting services.

Quick Start

Create XML mapping

Modeler GUI application

You can use Cayenne Modeler to manually create Cayenne project without DB. Binary distributions can be downloaded from https://cayenne.apache.org/download/

Modeler

See tutorial https://cayenne.apache.org/docs/4.2/getting-started-guide/

Maven plugin

Additionally, you can use Cayenne Maven (or Gradle) plugin to create model based on existing DB structure. Here is example of Cayenne Maven plugin setup that will do it:

<plugin>
    <groupId>org.apache.cayenne.plugins</groupId>
    <artifactId>cayenne-maven-plugin</artifactId>
    <version>4.2.RC1</version>

    <dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.29</version>
        </dependency>
    </dependencies>

    <configuration>
        <map>${project.basedir}/src/main/resources/demo.map.xml</map>
        <cayenneProject>${project.basedir}/src/main/resources/cayenne-demo.xml</cayenneProject>
        <dataSource>
            <url>jdbc:mysql://localhost:3306/cayenne_demo</url>
            <driver>com.mysql.cj.jdbc.Driver</driver>
            <username>user</username>
            <password>password</password>
        </dataSource>
        <dbImport>
            <defaultPackage>org.apache.cayenne.demo.model</defaultPackage>
        </dbImport>
    </configuration>
</plugin>

Run it:

mvn cayenne:cdbimport
mvn cayenne:cgen

See tutorial https://cayenne.apache.org/docs/4.2/getting-started-db-first/

Gradle plugin

And here is example of Cayenne Gradle plugin setup:

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath group: 'org.apache.cayenne.plugins', name: 'cayenne-gradle-plugin', version: '4.2.RC1'
        classpath 'mysql:mysql-connector-java:8.0.29'
    }
}

apply plugin: 'org.apache.cayenne'
cayenne.defaultDataMap 'demo.map.xml'

cdbimport {   
    cayenneProject 'cayenne-demo.xml'

    dataSource {
        driver 'com.mysql.cj.jdbc.Driver'
        url 'jdbc:mysql://127.0.0.1:3306/cayenne_demo'
        username 'user'
        password 'password'
    }

    dbImport {
        defaultPackage = 'org.apache.cayenne.demo.model'
    }
}

cgen.dependsOn cdbimport
compileJava.dependsOn cgen

Run it:

gradlew build

Include Cayenne into project

Maven

<dependencies>
    <dependency>
        <groupId>org.apache.cayenne</groupId>
        <artifactId>cayenne-server</artifactId>
        <version>4.2.RC1</version>
    </dependency>
</dependencies>

Gradle

compile group: 'org.apache.cayenne', name: 'cayenne-server', version: '4.2.RC1'
 
// or, if Gradle plugin is used
compile cayenne.dependency('server')

Create Cayenne Runtime

ServerRuntime cayenneRuntime = ServerRuntime.builder()
    .addConfig("cayenne-demo.xml")
    .dataSource(DataSourceBuilder
             .url("jdbc:mysql://localhost:3306/cayenne_demo")
             .driver("com.mysql.cj.jdbc.Driver")
             .userName("username")
             .password("password")
             .build())
    .build();

Create New Objects

ObjectContext context = cayenneRuntime.newContext();

Artist picasso = context.newObject(Artist.class);
picasso.setName("Pablo Picasso");
picasso.setDateOfBirth(LocalDate.of(1881, 10, 25));

Gallery metropolitan = context.newObject(Gallery.class);
metropolitan.setName("Metropolitan Museum of Art");

Painting girl = context.newObject(Painting.class);
girl.setName("Girl Reading at a Table");

Painting stein = context.newObject(Painting.class);
stein.setName("Gertrude Stein");

picasso.addToPaintings(girl);
picasso.addToPaintings(stein);

girl.setGallery(metropolitan);
stein.setGallery(metropolitan);

context.commitChanges();

Queries

Select Objects

List<Painting> paintings = ObjectSelect.query(Painting.class)
        .where(Painting.ARTIST.dot(Artist.DATE_OF_BIRTH).year().lt(1900))
        .prefetch(Painting.ARTIST.joint())
        .select(context);

Aggregate functions

// this is artificial property signaling that we want to get full object
Property<Artist> artistProperty = Property.createSelf(Artist.class);

List<Object[]> artistAndPaintingCount = ObjectSelect.columnQuery(Artist.class, artistProperty, Artist.PAINTING_ARRAY.count())
    .where(Artist.ARTIST_NAME.like("a%"))
    .having(Artist.PAINTING_ARRAY.count().lt(5L))
    .orderBy(Artist.PAINTING_ARRAY.count().desc(), Artist.ARTIST_NAME.asc())
    .select(context);

for(Object[] next : artistAndPaintingCount) {
    Artist artist = (Artist)next[0];
    long paintingsCount = (Long)next[1];
    System.out.println(artist.getArtistName() + " has " + paintingsCount + " painting(s)");
}

Raw SQL queries

// Selecting objects
List<Painting> paintings = SQLSelect
    .query(Painting.class, "SELECT * FROM PAINTING WHERE PAINTING_TITLE LIKE #bind($title)")
    .params("title", "painting%")
    .upperColumnNames()
    .localCache()
    .limit(100)
    .select(context);

// Selecting scalar values
List<String> paintingNames = SQLSelect
    .scalarQuery(String.class, "SELECT PAINTING_TITLE FROM PAINTING WHERE ESTIMATED_PRICE > #bind($price)")
    .params("price", 100000)
    .select(context);

// Insert values
int inserted = SQLExec
    .query("INSERT INTO ARTIST (ARTIST_ID, ARTIST_NAME) VALUES (#bind($id), #bind($name))")
    .paramsArray(55, "Picasso")
    .update(context);

Documentation

Getting Started

https://cayenne.apache.org/docs/4.2/getting-started-guide/

Getting Started Db-First

https://cayenne.apache.org/docs/4.2/getting-started-db-first/

Full documentation

https://cayenne.apache.org/docs/4.2/cayenne-guide/

JavaDoc

https://cayenne.apache.org/docs/4.2/api/

About

With a wealth of unique and powerful features, Cayenne can address a wide range of persistence needs. Cayenne seamlessly binds one or more database schemas directly to Java objects, managing atomic commit and rollbacks, SQL generation, joins, sequences, and more.

Cayenne is designed to be easy to use, without sacrificing flexibility or design. To that end, Cayenne supports database reverse engineering and generation, as well as a Velocity-based class generation engine. All of these functions can be controlled directly through the CayenneModeler, a fully functional GUI tool. No cryptic XML or annotation based configuration is required! An entire database schema can be mapped directly to Java objects within minutes, all from the comfort of the GUI-based CayenneModeler.

Cayenne supports numerous other features, including caching, a complete object query syntax, relationship pre-fetching, on-demand object and relationship faulting, object inheritance, database auto-detection, and generic persisted objects. Most importantly, Cayenne can scale up or down to virtually any project size. With a mature, 100% open source framework, an energetic user community, and a track record of solid performance in high-volume environments, Cayenne is an exceptional choice for persistence services.

Collaboration

Download Details:
Author: apache
Source Code: https://github.com/apache/cayenne
License:

#java

Ray  Patel

Ray Patel

1623401100

How to Bind Methods or Constructors to Functional Interfaces

To bind methods or constructors to functional interfaces, we are going to use the FunctionalInterfaceFactory of Burningwave Core library. FunctionalInterfaceFactory component uses to cache all generated functional interfaces for faster access. Before we start coding, we must add the following dependency to our _pom.xm_l:

XML

1

<dependency>2
    <groupId>org.burningwave</groupId>3
    <artifactId>core</artifactId>4
    <version>8.12.6</version>5
</dependency>

Constructors Binding

Methods Binding

Void Methods Binding

Binding to Methods with Boolean Return

Conclusion

#java #method #constructor #binding #functional interface #functional interfaces #binding in java

Annalise  Hyatt

Annalise Hyatt

1598947500

Binding Concept in Javascript

Javascript binding is done using the Bind() method. With the help of the bind method, we can make one common function and bind different objects, so that the function gives different results when its need. otherwise, it gives the same result or gives an error while the code is executing.

In short, when a function or method is invoked, the bind() method allows us to easily set which object will be bound by this keyword.

var info= {

name : "XYZ",
printFunc: function(){
document.write(this.name);} // XYZ
}
info.printFunc();

In the above example, there is no problem accessing the name, this keyword bind the name variable to the function. This is called as default binding.

This keyword will here point to object i.e info object.

var info = {

name : "XYZ",
printFunc: function(){
    document.write(this);// window object or undefined(strict mode).
    document.write(this.name);
  }
}
var printFunc2= info.printFunc;
printFunc2();

In the above example, we are storing a reference of info.printFunc to printFunc2 variable. After that, we are calling it without an object reference, so this will now refer to the window (global) object or undefined (in strict mode). Hence, the binding of this is lost, so no output is produced.

So basically, the Bind() method is used so that binding of this is not lost.

By using bind() method we can set the context of _this or in simple terms we can bind this _to a particular object.


How to use bind?

  1. The bind() method creates a new function, when invoked, has the this sets to the provided value. See example below:-
var car1 = {
  name : "swift",
  color: "red",
}
var car2 = {
  name : "alto",
  color: "blue",
}
function infoFunc() {
   document.write(this.name + " " + this.color + "<br/>");
 }
infoFunc.bind(car1)(); // swift red
infoFunc.bind(car2)(); // alto blue

There is one common function infoFunc() which is invoked 2times with different objects so that different results are produced. This first binds to car1 object and then to car2 object.

2. Function borrowing which means the bind() allows an object to borrow a method from another object without making a copy of that method.

#this-keyword #binding #javascript #front-end-development #call-apply-bind

Anthony  Dach

Anthony Dach

1643249520

Selenium Remote Driver: Perl Bindings to The Selenium Webdriver Server

Selenium::Remote::Driver 

WARNING

Selenium has essentially been leapfrogged technologically by Playwright. (using the devtools protocol for all browsers) Use Chrome::DevToolsProtocol (or the Playwright interface on CPAN) instead of this unless you want to be frustrated by a tool which doesn't do half of what you want. Even then you are probably shooting yourself in the foot not using Javascript directly to automate the testing of webpages.

This module is also not ready for SeleniumHQ's 4.0 series JAR. For compatibility with that, try our next generation selenium client: Selenium::Client

Introduction

Selenium WebDriver is a test tool that allows you to write automated web application UI tests in any programming language against any HTTP website using any mainstream JavaScript-enabled browser. This module is a Perl implementation of the client for the Webdriver JSONWireProtocol that Selenium provides.

It also implements WC3 selenium.

Installation

It's probably easiest to use the cpanm or CPAN commands:

$ cpanm Selenium::Remote::Driver

If you want to install from this repository, see the installation docs for more details.

Usage

You can use this module to directly start the webdriver servers, after downloading the appropriate ones and putting the servers in your $PATH. This method does not require the JRE/JDK to be installed, nor does it require the standalone server jar, despite the name of the module. In this case, you'll want to use the appropriate class for driver construction: either Selenium::Chrome, Selenium::Firefox, Selenium::PhantomJS, or Selenium::InternetExplorer.

You can also use this module with the selenium-standalone-server.jar to let it handle browser start up for you, and also manage Remote connections where the server jar is not running on the same machine as your test script is executing. The main class for this method is Selenium::Remote::Driver.

Regardless of which method you use to construct your browser object, all of the classes use the functions listed in the S::R::Driver POD documentation, so interacting with the browser, the page, and its elements would be the same.

no standalone server

Firefox 48 & newer: install the Firefox browser, download geckodriver and put it in your $PATH. If the Firefox browser binary is not in the default place for your OS and we cannot locate it via which, you may have to specify the binary location during startup. We also will need to locate the Firefox browser; if the Firefox browser isn't in the default location, you must provide it during startup in the firefox_binary attr.

Firefox 47 & older: install the Firefox browser in the default place for your OS. If the Firefox browser binary is not in the default place for your OS, you may have to specify the firefox_binary constructor option during startup.

Chrome: install the Chrome browser, download Chromedriver and get chromedriver in your $PATH.

PhantomJS: install the PhantomJS binary and get phantomjs in your $PATH. The driver for PhantomJS, Ghostdriver, is bundled with PhantomJS.

When the browser(s) are installed and you have the appropriate binary in your path, you should be able to do the following:

my $firefox = Selenium::Firefox->new;
$firefox->get('http://www.google.com');

my $chrome = Selenium::Chrome->new;
$chrome->get('http://www.google.com');

my $ghost = Selenium::PhantomJS->new;
$ghost->get('http://www.google.com');

Note that you can also pass a binary argument to any of the above classes to manually specify what binary to start. Note that this binary refers to the driver server, not the browser executable.

my $chrome = Selenium::Chrome->new(binary => '~/Downloads/chromedriver');

See the pod for the different modules for more details.

Breaking Changes for Selenium::Firefox in v1.0+

There are breaking changes for Selenium::Firefox from v0.2701 of S:F to v1.0+. This is because in FF47 and older, Firefox didn't have a separate webdriver server executable - local startup was accomplished by starting your actual Firefox browser with a webdriver extension. However, in FF48 and newer, Mozilla have switched to using geckodriver to handle the Webdriver communication. Accordingly, v1.0+ of Selenium::Firefox assumes the geckodriver setup which only works for FF48 and higher:

# marionette_enabled defaults to 1 === assumes you're running FF48
my $fx48 = Selenium::Firefox->new;
my $fx48 = Selenium::Firefox->new( marionette_enabled => 1 );

To drive FF47 with v1.0+ of Selenium::Firefox, you must manually disable marionette:

my $fx47 = Selenium::Firefox->new( marionette_enabled => 0 );

Doing so will start up your Firefox browser with the webdriver extension. Note that in our tests, doing the old "webdriver-extension-startup" for Firefox 48 does not work. Likewise, geckodriver does not work with FF47.

with a standalone server

Download the standalone server and have it running on port 4444:

$ java -jar selenium-server-standalone-X.XX.X.jar

As before, have the browsers themselves installed on your machine, and download the appropriate binary server, passing its location to the server jar during startup.

Locally

use strict;
use warnings;
use Selenium::Remote::Driver;

my $driver = Selenium::Remote::Driver->new;
$driver->get('http://www.google.com');
print $driver->get_title . "\n"; # "Google"

my $query = $driver->find_element('q', 'name');
$query->send_keys('CPAN Selenium Remote Driver');

my $send_search = $driver->find_element('btnG', 'name');
$send_search->click;

# make the find_element blocking for a second to allow the title to change
$driver->set_implicit_wait_timeout(2000);
my $results = $driver->find_element('search', 'id');

print $driver->get_title . "\n"; # CPAN Selenium Remote Driver - Google Search
$driver->quit;

Saucelabs

If using Saucelabs, there's no need to have the standalone server running on a local port, since Saucelabs provides it.

use Selenium::Remote::Driver;

my $user = $ENV{SAUCE_USERNAME};
my $key = $ENV{SAUCE_ACCESS_KEY};

my $driver = Selenium::Remote::Driver->new(
    remote_server_addr => $user . ':' . $key . '@ondemand.saucelabs.com',
    port => 80
);

$driver->get('http://www.google.com');
print $driver->get_title();
$driver->quit();

There are additional usage examples on metacpan, and also in this project's wiki, including setting up the standalone server, running tests on Internet Explorer, Chrome, PhantomJS, and other useful example snippets.

Selenium IDE Plugin

ide-plugin.js is a Selenium IDE Plugin which allows you to export tests recorded in Selenium IDE to a perl script.

Installation in Selenium IDE

  1. Open Selenium IDE
  2. Options >> Options
  3. Formats Tab
  4. Click Add at the bottom
  5. In the name field call it 'Perl-Webdriver'
  6. Paste this entire source in the main textbox
  7. Click 'Save'
  8. Click 'Ok'
  9. Close Selenium IDE and open it again.

Note: The Code generated by this plugin currently assumes that you have firefox 48 or newer + the geckodriver plugin installed.

If you have an older version of firefox you can adjust the plugin the following way: In the options window of selenium IDE (Formats tab) there is a input box called "Header". Here you can modify the fixed header code beeing generatd. Change Selenium::Firefox->new(); according to the firefox init examples shown above in this README.

Support and Documentation

There is a mailing list available at

https://groups.google.com/forum/#!forum/selenium-remote-driver

for usage questions and ensuing discussions. If you've come across a bug, please open an issue in the Github issue tracker. The POD is available in the usual places, including metacpan, and in your shell via perldoc.

$ perldoc Selenium::Remote::Driver
$ perldoc Selenium::Remote::WebElement

Download Details:
Author: teodesian
Source Code: https://github.com/teodesian/Selenium-Remote-Driver
License: Apache

#selenium  #perl #driver