0.52.76 • Published 2 years ago

selenium-query v0.52.76

Weekly downloads
105
License
-
Repository
github
Last release
2 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

2 years ago

0.52.75

2 years ago

0.52.74

2 years ago

0.52.73

2 years ago

0.52.72

2 years ago

0.52.66

2 years ago

0.52.64

2 years ago

0.52.63

2 years ago

0.52.69

2 years ago

0.52.68

2 years ago

0.52.67

2 years ago

0.52.62

2 years ago

0.52.71

2 years ago

0.52.70

2 years ago

0.52.61

2 years ago

0.52.60

2 years ago

0.52.54

2 years ago

0.52.53

2 years ago

0.52.52

2 years ago

0.52.59

2 years ago

0.52.58

2 years ago

0.52.56

2 years ago

0.52.51

2 years ago

0.52.50

2 years ago

0.52.44

2 years ago

0.52.43

2 years ago

0.52.42

2 years ago

0.52.41

2 years ago

0.52.48

2 years ago

0.52.47

2 years ago

0.52.46

2 years ago

0.52.45

2 years ago

0.52.49

2 years ago

0.52.40

2 years ago

0.52.37

3 years ago

0.52.36

3 years ago

0.52.35

3 years ago

0.52.34

3 years ago

0.52.33

3 years ago

0.52.31

3 years ago

0.52.29

4 years ago

0.52.28

4 years ago

0.52.27

4 years ago

0.52.26

4 years ago

0.52.25

4 years ago

0.52.24

4 years ago

0.52.23

4 years ago

0.52.22

4 years ago

0.52.21

4 years ago

0.52.20

4 years ago

0.52.19

4 years ago

0.52.18

4 years ago

0.52.17

4 years ago

0.52.16

4 years ago

0.52.15

4 years ago

0.52.13

5 years ago

0.52.12

5 years ago

0.52.11

5 years ago

0.52.10

5 years ago

0.52.8

5 years ago

0.52.7

5 years ago

0.52.6

5 years ago

0.52.4

5 years ago

0.52.3

5 years ago

0.52.1

5 years ago

0.52.0

5 years ago

0.51.99

5 years ago

0.51.98

5 years ago

0.51.96

5 years ago

0.51.95

5 years ago

0.51.94

5 years ago

0.51.93

5 years ago

0.51.91

5 years ago

0.51.90

5 years ago

0.51.89

5 years ago

0.51.88

5 years ago

0.51.87

5 years ago

0.51.86

5 years ago

0.51.85

5 years ago

0.51.84

5 years ago

0.51.83

5 years ago

0.51.82

5 years ago

0.51.80

5 years ago

0.51.78

5 years ago

0.51.77

5 years ago

0.51.76

5 years ago

0.51.75

5 years ago

0.51.74

5 years ago

0.51.73

5 years ago

0.51.71

5 years ago

0.51.70

5 years ago

0.51.69

5 years ago

0.51.68

5 years ago

0.51.65

5 years ago

0.51.64

5 years ago

0.51.63

5 years ago

0.51.61

5 years ago

0.51.60

5 years ago

0.51.58

5 years ago

0.51.56

6 years ago

0.51.52

6 years ago

0.51.51

6 years ago

0.51.50

6 years ago

0.51.49

6 years ago

0.51.47

6 years ago

0.51.45

6 years ago

0.51.44

6 years ago

0.51.43

6 years ago

0.51.42

6 years ago

0.51.41

6 years ago

0.50.40

6 years ago

0.50.39

6 years ago

0.50.36

6 years ago

0.50.35

9 years ago

0.50.34

9 years ago

0.50.33

9 years ago

0.50.32

9 years ago

0.50.31

9 years ago

0.50.30

9 years ago

0.50.29

9 years ago

0.50.28

9 years ago

0.50.27

9 years ago

0.50.26

9 years ago

0.50.25

9 years ago