0.52.76 • Published 3 years ago

selenium-query v0.52.76

Weekly downloads
105
License
-
Repository
github
Last release
3 years ago

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.

:exclamation: 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.

:exclamation: 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` <a name='slice'></a>
Get elements range.

##### `each(function<node:WebElement, index:number, Promise|void 0>):SQuery` <a name='each'></a>
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` <a name='map'></a>
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>>` <a name='toarray'></a>
Returns a promise which resolves with an Array instance of current elements in collection


## Traverse

##### `find(selector:string):SQuery` <a name='find'></a>
Find element(s).

##### `filter(selector:string):SQuery` <a name='filter'></a>
Filter element(s) out of the current collection.

##### `children([selector:string]):SQuery` <a name='children'></a>
Get, and optionally filter, children of every element in the collection.

##### `parent():SQuery` <a name='parent'></a>
Get parent elements of every element in the collection

##### `closest(selector):SQuery` <a name='closest'></a>
Find ancestor of every element in the collection


## Attributes

##### `attr(key:string | key:string, val:any | attributes:Object ):SQuery|Promise<any>` <a name='attr'></a>
Get attribute value of the first element in the collection, or set attribute(s) to each element.

##### `removeAttr(key:string):SQuery` <a name='removeAttr'></a>
Remove the attribute

##### `prop(key:string | key:string, val:any | properties:Object):SQuery|Promise<any>` <a name='prop'></a>
Get property value of the first element in the collection, or set property(ies) to each element.

##### `removeProp(key:string):SQuery` <a name='removeProp'></a>
Delete property

##### `val([value:string]):SQuery` <a name='val'></a>
Get or set `value` property, like `input.value`

##### `css(key:string | key:string, val:string | css:Object ):SQuery|Promise<any>` <a name='css'></a>
Get or set style properties

## Class

##### `hasClass(name:string):Promise<boolean>` <a name='hasClass'></a>
Check if the first element has the class name.

##### `addClass(name:string):SQuery` <a name='addClass'></a>
Add the class name(s) to every element in the collection

##### `removeClass(name:string):SQuery` <a name='removeClass'></a>
Remove the class name(s) of every element in the collection

##### `toggleClass(name:string):SQuery` <a name='toggleClass'></a>
Toggle the class name(s) of every element in the collection

## Manipulate

##### `remove():SQuery` <a name='remove'></a>
Remove the elements from the parent nodes

## Dimensions

##### `height():Promise<number>` <a name='height'></a>
##### `width():Promise<number>` <a name='width'></a>
##### `innerHeight():Promise<number>` <a name='innerHeight'></a>
##### `innerWidth():Promise<number>` <a name='innerWidth'></a>
##### `offset():Promise<object{top,left}>` <a name='offset'></a>
##### `position():Promise<object{top,left}>` <a name='position'></a>
##### `scrollTop():Promise<number>` <a name='scrollTop'></a>
##### `scrollLeft():Promise<number>` <a name='scrollLeft'></a>

## Content

##### `html([html:string]):SQuery|Promise<string>` <a name='html'></a>
##### `text([text:string]):SQuery|Promise<string>` <a name='text'></a>

##### `append(html:string):SQuery` <a name='append'></a>
##### `prepend(html:string):SQuery` <a name='prepend'></a>
##### `before(html:string):SQuery` <a name='before'></a>
##### `after(html:string):SQuery` <a name='after'></a>

## Events

##### `trigger(type:string [, data:Object]):SQuery` <a name='trigger'></a>
Trigger native or custom event.

##### `click():SQuery` <a name='click'></a>
##### `change():SQuery` <a name='change'></a>
Trigger `change` event
##### `focus():SQuery` <a name='click'></a>
##### `blur():SQuery` <a name='click'></a>

##### `type(text:string):SQuery` <a name='type'></a>
Enter the text.
> :exclamation: Meta keys are supported in `{}`

##### `press(combination:string):SQuery` <a name='press'></a>
Press key combination. E.g.: `ctrl+c`, `a+b+c`, `ctrl+alt+d`, `ctrl++` _(`control` and `plus` keys)_

##### `sendKeys(text:string):SQuery` <a name='sendKeys'></a>
Call native Selenums `sendKeys` fn on each element

##### `select(text:string | start:number[, end:number]):SQuery` <a name='select'></a>
Select an option from the `select` element, or if the `input` the selects a text or range


## Misc

##### `eval(fn:Function, ...args):Promise<any>` <a name='eval'></a>
Evaluate function in Browser.
> :exclamation: The first argument is the first element in the set
```typescript
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.

:checkered_flag:


:copyright: MIT, Alex Kit

0.52.76

3 years ago

0.52.75

3 years ago

0.52.74

3 years ago

0.52.73

3 years ago

0.52.72

3 years ago

0.52.66

3 years ago

0.52.64

3 years ago

0.52.63

3 years ago

0.52.69

3 years ago

0.52.68

3 years ago

0.52.67

3 years ago

0.52.62

3 years ago

0.52.71

3 years ago

0.52.70

3 years ago

0.52.61

3 years ago

0.52.60

3 years ago

0.52.54

3 years ago

0.52.53

3 years ago

0.52.52

3 years ago

0.52.59

3 years ago

0.52.58

3 years ago

0.52.56

3 years ago

0.52.51

3 years ago

0.52.50

3 years ago

0.52.44

3 years ago

0.52.43

3 years ago

0.52.42

3 years ago

0.52.41

3 years ago

0.52.48

3 years ago

0.52.47

3 years ago

0.52.46

3 years ago

0.52.45

3 years ago

0.52.49

3 years ago

0.52.40

3 years ago

0.52.37

4 years ago

0.52.36

4 years ago

0.52.35

4 years ago

0.52.34

4 years ago

0.52.33

5 years ago

0.52.31

5 years ago

0.52.29

5 years ago

0.52.28

5 years ago

0.52.27

5 years ago

0.52.26

5 years ago

0.52.25

5 years ago

0.52.24

5 years ago

0.52.23

5 years ago

0.52.22

5 years ago

0.52.21

5 years ago

0.52.20

5 years ago

0.52.19

5 years ago

0.52.18

5 years ago

0.52.17

5 years ago

0.52.16

6 years ago

0.52.15

6 years ago

0.52.13

6 years ago

0.52.12

6 years ago

0.52.11

6 years ago

0.52.10

6 years ago

0.52.8

6 years ago

0.52.7

6 years ago

0.52.6

6 years ago

0.52.4

6 years ago

0.52.3

6 years ago

0.52.1

6 years ago

0.52.0

6 years ago

0.51.99

6 years ago

0.51.98

6 years ago

0.51.96

6 years ago

0.51.95

6 years ago

0.51.94

6 years ago

0.51.93

6 years ago

0.51.91

6 years ago

0.51.90

6 years ago

0.51.89

6 years ago

0.51.88

6 years ago

0.51.87

6 years ago

0.51.86

6 years ago

0.51.85

6 years ago

0.51.84

6 years ago

0.51.83

6 years ago

0.51.82

6 years ago

0.51.80

6 years ago

0.51.78

6 years ago

0.51.77

6 years ago

0.51.76

6 years ago

0.51.75

6 years ago

0.51.74

6 years ago

0.51.73

6 years ago

0.51.71

6 years ago

0.51.70

6 years ago

0.51.69

6 years ago

0.51.68

6 years ago

0.51.65

6 years ago

0.51.64

6 years ago

0.51.63

6 years ago

0.51.61

6 years ago

0.51.60

7 years ago

0.51.58

7 years ago

0.51.56

7 years ago

0.51.52

7 years ago

0.51.51

7 years ago

0.51.50

7 years ago

0.51.49

7 years ago

0.51.47

7 years ago

0.51.45

7 years ago

0.51.44

7 years ago

0.51.43

7 years ago

0.51.42

7 years ago

0.51.41

7 years ago

0.50.40

7 years ago

0.50.39

7 years ago

0.50.36

7 years ago

0.50.35

10 years ago

0.50.34

10 years ago

0.50.33

10 years ago

0.50.32

10 years ago

0.50.31

10 years ago

0.50.30

10 years ago

0.50.29

10 years ago

0.50.28

10 years ago

0.50.27

10 years ago

0.50.26

10 years ago

0.50.25

10 years ago