Playwright: import selectors from another file - playwright

I've only just started looking at playwright, having used WebdriverIO for a long time. In WebdriverIO, I was able to store all the locators of elements in seperate files and import these to the test. Example (wdio)
// loginPage.js
module.exports = {
btnLogn: '[name="login"]',
btnCancel: '[name="cancel"]',
};
// loginPageTest.js
var loginPage = require('path/to/loginPage.js')
loginPage.btnLogin.click() // or similar
I liked this approach as if names / locators chagned it was one place to update.
The playwright docs show all locators in the files, but I was looking to see if the above was possible with Playwright.
Typescript I am totally new to, so tried using the same logic as above with a javascript solution, but the locators were not being accepted.

Related

How to reflect Dart library name?

Is there a way to reflect specific library properties (like the library name) in Dart?
How do you get the library object reference?
First of all, not all Dart libraries have names. In fact, most don't. They used to, but the name isn't used for anything any more, so most library authors don't bother adding a name.
To do reflection on anything, including libraries, you need to use the dart:mirrors library, which does not exist on most platforms, including the web and Flutter.
If you are not running the stand-alone VM, you probably don't have dart:mirrors.
With dart:mirrors, you can get the program's libraries in various ways.
library my.library.name;
import "dart:mirrors";
final List<LibraryMirror> allLibraries =
[...currentMirrorSystem().libraries.values];
void main() {
// Recognize the library's mirror in *some* way.
var someLibrary = allLibraries.firstWhere((LibraryMirror library) =>
library.simpleName.toString().contains("name"));
// Find the library mirror by its name.
// Not great if you don't know the name and want to find it.
var currentLibrary = currentMirrorSystem().findLibrary(#my.library.name);
print(currentLibrary.simpleName);
// Find a declaration in the current library, and start from there.
var mainFunction = reflect(main) as ClosureMirror;
var alsoCurrentLibrary = mainFunction.function.owner as LibraryMirror;
print(alsoCurrentLibrary.simpleName);
}
What are you trying to do, which requires doing reflection?

Getting paperjs to work in an electron app

Another learning project in the works... I am trying to use paperjs in an electron app.
According to the instructions, I think I should be using paper-jsdom (please correct me if I'm wrong). BTW, I am using TypeScript if that makes a difference. I have an HTML document with nothing but an empty <canvas> and a <script> tag referencing this:
import paper, {Color, Point, Path} from 'paper-jsdom'
window.onload = (): void => {
let canvas = document.getElementById("workspace") as HTMLCanvasElement;
paper.setup(canvas);
let path = new Path();
path.strokeColor = Color.random();
let start = new Point(100, 100);
path.moveTo(start);
path.lineTo(start.add(new Point(200, -50)));
paper.view.update();
};
So right off the bat I get:
Uncaught TypeError: paper_jsdom_1.Path is not a constructor
Ugh... So I tried a few random things (it's late, I'm tired...) and changing my import to:
import paper from 'paper'
import {Color, Point, Path} from 'paper-jsdom'
works, or at least the code above works.
Am I supposed to be importing some things from 'paper' and others from 'paper-jsdom'? What is the correct way to use paperjs in an electron app?
Unfortunately paper-jsdom doesn't seem to have any type info for TS.
Thanks!!
Since you are using Paper.js in the renderer process of Electron, you are using it in the browser context and not in Node.js context so you should use the common paper package which relies on browser Canvas API (and not paper-jsdom which targets browserless usage).
So you should be able to use Paper.js as you would for a website.
From your code example, I see that you are using TypeScript so you can have a look at this simple quickstart project that I made to play with Paper.js and TypeScript.
It uses this kind of import:
import * as paper from 'paper';
And then access Paper.js classes through the imported paper object:
new paper.Path.Circle({
center : paper.view.center,
radius : 50,
fillColor: 'orange',
});
Edit
Here is a repository showing the simplest way of using Paper.js in an Electron app.

How can I interop with existing JS objects?

I'm trying to write Dart code that will generate a rough equivalent of this:
var disposable = vscode['commands'].registerCommand(
'extension.sayHello',
function () {
vscode['window'].showInformationMessage('Hello World!');
}
);
context.subscriptions.push(disposable);
The variables vscode and context are both globals available in the JavaScript which is executing my Dart (which is being compiled to JS with the Dart Dev Compiler).
I'm happy for context/vscode to be completely untyped for now, but I'm struggling to bend the JS package to output code like this (eg. if I put #JS() on a stub vscode, I get dart.global.vscode).
You can use the base dart:js features
Note that context happens to be dart's name for the javascript context.
var disposable = context['vscode']['commands'].callMethod('registerCommand', [
'extension.sayHello',
() {
context['vscode']['window'].callMethod('showInformationMessage', ['Hello World!']);
}]);
);
context['context']['subscriptions'].callMethod('push', [disposable]);
Let me put together a quick example on github with package:js.
Edit: OK, here you go:
https://github.com/matanlurey/js-interop-examples
It took me a couple tries to the package:js syntax correct (we probably need more documentation here and examples), but I ended up creating a "fake" visual studio code API (vscode.js), and interoping with it fine.
Watch out that you need to wrap your functions with allowInterop if you expect your examples to work in Dartium.

"document" in mozilla extension js modules?

I am building Firefox extension, that creates single XMPP chat connection, that can be accessed from all tabs and windows, so I figured, that only way to to this, is to create connection in javascript module and include it on every browser window. Correct me if I am wrong...
EDIT: I am building traditional extension with xul overlays, not using sdk, and talking about those modules: https://developer.mozilla.org/en-US/docs/Mozilla/JavaScript_code_modules
So I copied Strophe.js into js module. Strophe.js uses code like this:
/*_Private_ function that creates a dummy XML DOM document to serve as
* an element and text node generator.
*/
[---]
if (document.implementation.createDocument === undefined) {
doc = this._getIEXmlDom();
doc.appendChild(doc.createElement('strophe'));
} else {
doc = document.implementation
.createDocument('jabber:client', 'strophe', null);
}
and later uses doc.createElement() to create xml(or html?) nodes.
All worked fine, but in module I got error "Error: ReferenceError: document is not defined".
How to get around this?
(Larger piece of exact code: http://pastebin.com/R64gYiKC )
Use the hiddenDOMwindow
Cu.import("resource://gre/modules/Services.jsm");
var doc = Services.appShell.hiddenDOMWindow.document;
It sounds like you might not be correctly attaching your content script to the worker page. Make sure that you're using something like tabs.attach() to attach one or more content scripts to the worker page (see documentation here).
Otherwise you may need to wait for the DOM to load, waiting for the entire page to load
window.onload = function ()
{
Javascript code goes here
}
Should take at least diagnose that issue (even if the above isn't the best method to use in production). But if I had to wager, I'd say that you're not attaching the content script.

How do I share javascript code between background and content scripts in Firefox Jetpack add-ons?

I've written a library to mimic Chrome's request/response API for my Firefox add-on. Obviously I need to use this code in both my background process (main.js) and my content script. Surely there must be a better way than stringifying the imported module.
There is a semi-documented way of getting the URLs of the SDK code modules. This involves low-level modules which aren't guaranteed to stay stable. In fact, it is very likely that this part of the SDK will change and this solution won't work any more (like the solution originally presented here).
That said, the SDK allows you to access the loader module. So first you need to construct a loader with the same options as the one used by the SDK. Then you need to use the resolveURI utility function to resolve the module name using the mapping of this loader:
var {Loader, resolveURI} = require('toolkit/loader');
var options = require('#loader/options');
var loader = Loader(options);
var fooURI = resolveURI("./foo", loader.mapping);
The code above generates the URL for the module foo. Note that you need to use the module foo somewhere, otherwise it won't be included in your extension. If you don't use it yet then a dummy function will be sufficient:
function dummy()
{
require("foo");
}
Using the resulting URL as content script works just fine:
var pageMod = require("page-mod");
pageMod.PageMod({
include: "*.google.com",
contentScriptWhen: 'end',
contentScriptFile: [fooURI, ...]
});

Resources