selenium-query
TypeScript icon, indicating that this package has built-in type declarations

0.52.76 • Public • Published

Web Query and Manipulation Library


Build Status NPM version TypeScript

jQuery-alike API for Selenium WebDriver, JSDom and Cheerio

Single API to query web-pages or html blocks with supported providers: Selenium WebDriver, JSDom, Cheerio, Plain-HTTP.

Use for tests, crawlers and automations.


Request

All cookies received from the backend will be reused for a domain.

import SQuery from 'selenium-query';
let $ = await SQuery.load(url, config?: IConfig)

Query and Manipulate

Asynchronous nature

As the WebDriver methods are async, Selenium Query instance implements Promise and you can chain the function calls or use async/await. A very basic example

import $ from 'selenium-query';

$(driver)
    .find('.foo')
    .filter('input')
    .attr('placeholder', 'Baz')
    .val()
    .then(value => console.log(value));

// or via await
let value = await $(driver).find('input.foo').val();
console.log(value);

Extension methods

As with jQuery you can define an extension method and call it in your tests

import $ from 'selenium-query';

$.fn.doBaz = function(){
    return this.each(el => {
        // do some usefull things with WebElement/JsDomElement/CherioElement
    });
};
$(driver)
    .find('input')
    .doBaz();

WebDriver network monitor

Allows to get and to listen for events emitted by the browser

import { BrowserNetworkMonitor  } from 'selenium-query';

let monitor = await BrowserNetworkMonitor.start(driver);

monitor
    .on('requestWillBeSent', req => console.log(req))
    .on('responseReceived', req => console.log(req))
    .on('loadingFinished', req => console.log(req));

// ... e.g. after the a page is loaded
let { request, response } = monitor.getRequest(/index.html/);
console.log(request.headers, response.headers);

// get the response body
let { base64Encoded, body } = monitor.getResponseBody(mainPageRequest);

WebDriver network interceptor

Allows to send custom responses for requests back to the browser

import { BrowserNetworkInterceptor  } from 'selenium-query';

let interceptor = await BrowserNetworkInterceptor.start(driver);
interceptor.register({
    match: /index.html/,
    response: {
        status: 200,
        headers: {
            'Content-Type': 'text/html'
        },
        body: '<!DOCTYPE html> <h1>Changed</h1>'
    }
});
// ... load index.html, and the modified content should be loaded

Pseudo selectors

:text and improved :has selectors
let html = `
    <ul>
        <li name='x'>Foo <span id='foo'></span></li>
        <li name='y'>Bar <span id='bar'></span></li>
    </ul>
`;
SQuery.pseudo.isBar = async ($el, innerQuery) => {
    let $children = await $el.find('#bar');
    return $children.length > 0;
};

let value1 = await $.find('li:text(Bar)').attr('name');
let value2 = await $.find('li:has(span#id)').attr('name');
let value3 = await $.find('li:isBar()').attr('name');
// value1 === value2 === value3 === 'y'

API

constructor(WebDriver|WebElement|Array<WebElement>|SQuery|Array<SQuery>)
let SQuery = require('selenium-query');
let $document = SQuery(driver);
let $inputs = $document.find('inputs');

Collection

length:number

Count of WebElements in a current set.

Due to asynchronous nature, sometimes you have to wait until the promise is resolved to get the correct length value

eq(index:number):SQuery

Get the SQuery instance with only one element at the index.

Once again, wait until the promise is resolved, or chain the manipulations

await $(driver)
    .find('button')
    .eq(0)
    .css('background-color', 'red')
// instead of an equivalent

let buttons = await $(driver).find('button')
let firstButton = await buttons.eq(0);

await firstButton.css('background-color', 'red');
console.log('The color has been changed.'));
slice([start:number = 0, end:number = .length]):SQuery

Get elements range.

each(function<node:WebElement, index:number, Promise|void 0>):SQuery

Enumerate the collection. The callback function can return a promise, if an async job is performed.

map(function<node:WebElement, index:number, Promise|any>):SQuery

Map the collection into the new one. Return the value from the function or a promise which resolves then with the value.

toArray():Promise<Array<any>>

Returns a promise which resolves with an Array instance of current elements in collection

Traverse

find(selector:string):SQuery

Find element(s).

filter(selector:string):SQuery

Filter element(s) out of the current collection.

children([selector:string]):SQuery

Get, and optionally filter, children of every element in the collection.

parent():SQuery

Get parent elements of every element in the collection

closest(selector):SQuery

Find ancestor of every element in the collection

Attributes

attr(key:string | key:string, val:any | attributes:Object ):SQuery|Promise<any>

Get attribute value of the first element in the collection, or set attribute(s) to each element.

removeAttr(key:string):SQuery

Remove the attribute

prop(key:string | key:string, val:any | properties:Object):SQuery|Promise<any>

Get property value of the first element in the collection, or set property(ies) to each element.

removeProp(key:string):SQuery

Delete property

val([value:string]):SQuery

Get or set value property, like input.value

css(key:string | key:string, val:string | css:Object ):SQuery|Promise<any>

Get or set style properties

Class

hasClass(name:string):Promise<boolean>

Check if the first element has the class name.

addClass(name:string):SQuery

Add the class name(s) to every element in the collection

removeClass(name:string):SQuery

Remove the class name(s) of every element in the collection

toggleClass(name:string):SQuery

Toggle the class name(s) of every element in the collection

Manipulate

remove():SQuery

Remove the elements from the parent nodes

Dimensions

height():Promise<number>
width():Promise<number>
innerHeight():Promise<number>
innerWidth():Promise<number>
offset():Promise<object{top,left}>
position():Promise<object{top,left}>
scrollTop():Promise<number>
scrollLeft():Promise<number>

Content

html([html:string]):SQuery|Promise<string>
text([text:string]):SQuery|Promise<string>
append(html:string):SQuery
prepend(html:string):SQuery
before(html:string):SQuery
after(html:string):SQuery

Events

trigger(type:string [, data:Object]):SQuery

Trigger native or custom event.

click():SQuery
change():SQuery

Trigger change event

focus():SQuery
blur():SQuery
type(text:string):SQuery

Enter the text.

Meta keys are supported in {}

press(combination:string):SQuery

Press key combination. E.g.: ctrl+c, a+b+c, ctrl+alt+d, ctrl++ (control and plus keys)

sendKeys(text:string):SQuery

Call native Selenums sendKeys fn on each element

select(text:string | start:number[, end:number]):SQuery

Select an option from the select element, or if the input the selects a text or range

Misc

eval(fn:Function, ...args):Promise<any>

Evaluate function in Browser.

The first argument is the first element in the set

let result = await $(driver)
    .find('button')
    .eval((el: HTMLButton) => {
        // browser context
        // do smth. with the Element and return a value
      return el.tagName;
    });

Document

static load(url:string[, config:WebDriverOptions]):SQuery

Create or reuse a WebDriver, and load the page.

WebDriverOptions defaults

{
    name: 'Chrome',
    args: ['no-sandbox'],
    binaryPath: null,

    // For better control and to change the behaviour of how the options are created and applied,
    // you can define next functions
    applyOptions: function(builder, options) {},
    setOptions (builder, options) {},
    setArguments (options) {},
    setBinaryPath (options) {},
    setLogging (options) {}
}

JsDom

static SQuery.jsdom.build(config: IJsdomParams):SQuery

interface IJsdomParams {
    html: string
}

Create SQuery collection with JsDom driver

static SQuery.jsdom.load(url: string, config: IJsdomLoadParams):SQuery

interface IJsdomLoadParams {
    headers?: {[name: string] : string }
    method?
    query?: {[name: string] : string }
    payload?
    cookies?: string | string[]
    cache?: {
        folder?: string
        maxAge?: number
    }
    cacheQueryIgnore?: string[]
    /** Webdriver will load this url, or requested url, to set the cookies first */
    cookieOrigin?: string
}

Cheerio

static SQuery.cheerio.build(config: ICheerioParams):SQuery

interface ICheerioParams {
    html: string
}

Create SQuery collection with Cheerio driver (Only query and manipulation methods are implemented)

static SQuery.cheerio.load(url: string, config: ICheerioLoadParams):SQuery

interface ICheerioLoadParams {
    headers?: {[name: string] : string }
    method?
    query?: {[name: string] : string }
    payload?
    cookies?: string | string[]
    cache?: {
        folder?: string
        maxAge?: number
    }
    cacheQueryIgnore?: string[]
    /** Webdriver will load this url, or requested url, to set the cookies first */
    cookieOrigin?: string
}

Network

HTTP Utils to load and submit data. Handles cache and cookies.

load SQuery.network.load(url: string, config: IHttpParams):IHttpResponse

interface IHttpParams {
    headers?: {[name: string] : string }
    method?: 'post' | 'get' | 'delete' | 'patch' | 'head' | string
    query?: {[name: string] : string }
    body?: string | Buffer

    cookies?: {[name: string] : string } | string[] | string
    cookiesDefault?: {[name: string] : string } | string[] | string

    cache?: boolean | {
        folder?: string
        maxAge?: number
        compress?: boolean
        //-ensureCacheAllowed? (resp): boolean
    }
    cacheQueryIgnore?: string[]

    retryCount?: number
    retryTimeout?: number
    follow?: number
    httpsProxy?: string
    ignoreSSLErrors?: boolean
}
interface IHttpResponse {
    status: number
    message?: string

    headers: {[name: string] : string }
    url: string
    body: any
}

Example

$
    .load('http://google.com')
    .find('input')
    .css('background-color', 'red');

Known "features"

This version of ChromeDriver only supports Chrome version XYZ

Means the installed version of the Chromedriver is not compatible with Chrome itself. Usually it doesn't required one-to-one version, means you can use v97 of the chrome driver, with Chrome v98.

All platforms: Download the required Chromedriver from https://chromedriver.chromium.org/downloads

Windows: choco upgrade chromedriver

Stale element not found

When creating HTML DOM Elements in Chrome, make sure they are attached to the DOM before returning them to the nodejs process.

🏁


©️ MIT, Alex Kit

Package Sidebar

Install

npm i selenium-query

Weekly Downloads

582

Version

0.52.76

License

none

Unpacked Size

450 kB

Total Files

74

Last publish

Collaborators

  • tenbits