UNPKG

16 kBMarkdownView Raw
1# Chromeless
2
3[![npm](https://img.shields.io/npm/v/chromeless.svg)](https://npmjs.com/package/chromeless)
4[![downloads](https://img.shields.io/npm/dm/chromeless.svg)](https://npmjs.com/package/chromeless)
5[![circleci](https://circleci.com/gh/graphcool/chromeless.svg?style=shield)](https://circleci.com/gh/graphcool/workflows/chromeless/tree/master)
6[![codecov](https://codecov.io/gh/graphcool/chromeless/branch/master/graph/badge.svg)](https://codecov.io/gh/graphcool/chromeless)
7[![dependencies](https://david-dm.org/graphcool/chromeless/status.svg)](https://david-dm.org/graphcool/chromeless)
8[![node](https://img.shields.io/node/v/chromeless.svg)]()
9[![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release)
10
11Chrome automation made simple. Runs locally or headless on AWS Lambda. (**[See Demo](https://chromeless.netlify.com/)**)
12
13## Chromeless can be used to...
14
15* Run 1000s of **browser integration tests in parallel** ⚡️
16* Crawl the web & automate screenshots
17* Write bots that require a real browser
18* *Do pretty much everything you've used __PhantomJS, NightmareJS or Selenium__ for before*
19
20### Examples
21
22* [JSON of Google Results](examples/extract-google-results.js): Google for `chromeless` and get a list of JSON results
23* [Screenshot of Google Results](examples/google-screenshot.js): Google for `chromeless` and take a screenshot of the results
24* [prep](https://github.com/graphcool/prep): Compile-time prerendering for SPA/PWA (like React, Vue...) instead of server-side rendering (SSR)
25* *See the full [examples list](/examples) for more*
26
27## ▶️ Try it out
28
29You can try out Chromeless and explore the API in the browser-based **[demo playground](https://chromeless.netlify.com/)** ([source](https://github.com/graphcool/chromeless-playground)).
30
31[![](http://i.imgur.com/i1gtCzy.png)](https://chromeless.netlify.com/)
32
33## Contents
341. [How it works](#how-it-works)
351. [Installation](#installation)
361. [Usage](#usage)
371. [API Documentation](#api-documentation)
381. [Configuring Development Environment](#configuring-development-environment)
391. [FAQ](#faq)
401. [Contributors](#contributors)
411. [Credits](#credits)
421. [Help & Community](#help-and-community)
43
44## How it works
45
46With Chromeless you can control Chrome (open website, click elements, fill out forms...) using an [elegant API](docs/api.md). This is useful for integration tests or any other scenario where you'd need to script a real browser.
47
48### There are 2 ways to use Chromeless
49
501. Running Chrome on your local computer
512. Running Chrome on AWS Lambda and controlling it remotely
52
53![](http://imgur.com/2bgTyAi.png)
54
55### 1. Local Setup
56
57For local development purposes where a fast feedback loop is necessary, the easiest way to use Chromeless is by controlling your local Chrome browser. Just follow the [usage guide](#usage) to get started.
58
59### 2. Remote Proxy Setup
60
61You can also run Chrome in [headless-mode](https://developers.google.com/web/updates/2017/04/headless-chrome) on AWS Lambda. This way you can speed up your tests by running them in parallel. (In [Graphcool](https://www.graph.cool/)'s case this decreased test durations from ~20min to a few seconds.)
62
63Chromeless comes out of the box with a remote proxy built-in - the usage stays completely the same. This way you can write and run your tests locally and have them be executed remotely on AWS Lambda. The proxy connects to Lambda through a Websocket connection to forward commands and return the evaluation results.
64
65## Installation
66```sh
67npm install chromeless
68```
69
70### Proxy Setup
71
72The project contains a [Serverless](https://serverless.com/) service for running and driving Chrome remotely on AWS Lambda.
73
741. Deploy The Proxy service to AWS Lambda. More details [here](serverless#setup)
752. Follow the usage instructions [here](serverless#using-the-proxy).
76
77
78## Usage
79
80Using Chromeless is similar to other browser automation tools. For example:
81
82```js
83const { Chromeless } = require('chromeless')
84
85async function run() {
86 const chromeless = new Chromeless()
87
88 const screenshot = await chromeless
89 .goto('https://www.google.com')
90 .type('chromeless', 'input[name="q"]')
91 .press(13)
92 .wait('#resultStats')
93 .screenshot()
94
95 console.log(screenshot) // prints local file path or S3 url
96
97 await chromeless.end()
98}
99
100run().catch(console.error.bind(console))
101```
102
103### Local Chrome Usage
104
105To run Chromeless locally, you need a recent version of Chrome or Chrome Canary installed (version 60 or greater). By default, chromeless will start Chrome automatically and will default to the most recent version found on your system if there's multiple. You can override this behavior by starting Chrome yourself, and passing a flag of `launchChrome: false` in the `Chromeless` constructor.
106
107To launch Chrome yourself, and open the port for chromeless, follow this example:
108
109```sh
110alias canary="/Applications/Google\ Chrome\ Canary.app/Contents/MacOS/Google\ Chrome\ Canary"
111canary --remote-debugging-port=9222
112```
113
114Or run Chrome Canary headless-ly:
115
116```sh
117canary --remote-debugging-port=9222 --disable-gpu --headless
118```
119
120Or run Chrome headless-ly on Windows:
121
122```sh
123cd "C:\Program Files (x86)\Google\Chrome\Application"
124chrome --remote-debugging-port=9222 --disable-gpu --headless
125```
126
127### Proxy Usage
128
129Follow the setup instructions [here](serverless#installation).
130
131Then using Chromeless with the Proxy service is the same as running it locally with the exception of the `remote` option.
132Alternatively you can configure the Proxy service's endpoint with environment variables. [Here's how](serverless#using-the-proxy).
133```js
134const chromeless = new Chromeless({
135 remote: {
136 endpointUrl: 'https://XXXXXXXXXX.execute-api.eu-west-1.amazonaws.com/dev',
137 apiKey: 'your-api-key-here',
138 },
139})
140```
141
142## API Documentation
143
144**Chromeless constructor options**
145- [`new Chromeless(options: ChromelessOptions)`](docs/api.md#chromeless-constructor-options)
146
147**Chromeless methods**
148- [`end()`](docs/api.md#api-end)
149
150**Chrome methods**
151- [`goto(url: string, timeout?: number)`](docs/api.md#api-goto)
152- [`setUserAgent(useragent: string)`](docs/api.md#api-setUserAgent)
153- [`click(selector: string)`](docs/api.md#api-click)
154- [`wait(timeout: number)`](docs/api.md#api-wait-timeout)
155- [`wait(selector: string)`](docs/api.md#api-wait-selector)
156- [`wait(fn: (...args: any[]) => boolean, ...args: any[])`] - Not implemented yet
157- [`clearCache()`](docs/api.md#api-clearcache)
158- [`clearStorage(origin: string, storageTypes: string)`](docs/api.md#api-clearstorage)
159- [`focus(selector: string)`](docs/api.md#api-focus)
160- [`press(keyCode: number, count?: number, modifiers?: any)`](docs/api.md#api-press)
161- [`type(input: string, selector?: string)`](docs/api.md#api-type)
162- [`back()`](docs/api.md#api-back) - Not implemented yet
163- [`forward()`](docs/api.md#api-forward) - Not implemented yet
164- [`refresh()`](docs/api.md#api-refresh) - Not implemented yet
165- [`mousedown(selector: string)`](docs/api.md#api-mousedown)
166- [`mouseup(selector: string)`](docs/api.md#api-mouseup)
167- [`scrollTo(x: number, y: number)`](docs/api.md#api-scrollto)
168- [`scrollToElement(selector: string)`](docs/api.md#api-scrolltoelement)
169- [`setHtml(html: string)`](docs/api.md#api-sethtml)
170- [`setExtraHTTPHeaders(headers: Headers)`](docs/api.md#api-setextrahttpheaders)
171- [`setViewport(options: DeviceMetrics)`](docs/api.md#api-setviewport)
172- [`evaluate<U extends any>(fn: (...args: any[]) => void, ...args: any[])`](docs/api.md#api-evaluate)
173- [`inputValue(selector: string)`](docs/api.md#api-inputvalue)
174- [`exists(selector: string)`](docs/api.md#api-exists)
175- [`screenshot(selector: string, options: ScreenshotOptions)`](docs/api.md#api-screenshot)
176- [`pdf(options?: PdfOptions)`](docs/api.md#api-pdf)
177- [`html()`](docs/api.md#api-html)
178- [`cookies()`](docs/api.md#api-cookies)
179- [`cookies(name: string)`](docs/api.md#api-cookies-name)
180- [`cookies(query: CookieQuery)`](docs/api.md#api-cookies-query) - Not implemented yet
181- [`allCookies()`](docs/api.md#api-all-cookies)
182- [`setCookies(name: string, value: string)`](docs/api.md#api-setcookies)
183- [`setCookies(cookie: Cookie)`](docs/api.md#api-setcookies-one)
184- [`setCookies(cookies: Cookie[])`](docs/api.md#api-setcookies-many)
185- [`deleteCookies(name: string)`](docs/api.md#api-deletecookies)
186- [`clearCookies()`](docs/api.md#api-clearcookies)
187- [`clearInput(selector: string)`](docs/api.md#api-clearInput)
188- [`setFileInput(selector: string, files: string | string[])`](docs/api.md#api-set-file-input)
189
190## Configuring Development Environment
191
192**Requirements:**
193- NodeJS version 8.2 and greater
194
1951) Clone this repository
1962) Run `npm install`
1973) To build: `npm run build`
198
199#### Linking this NPM repository
200
2011) Go to this repository locally
2022) Run `npm link`
2033) Go to the folder housing your chromeless scripts
2044) Run `npm link chromeless`
205
206Now your local chromeless scripts will use your local development of chromeless.
207
208## FAQ
209
210### How is this different from [NightmareJS](https://github.com/segmentio/nightmare), PhantomJS or Selenium?
211
212The `Chromeless` API is very similar to NightmareJS as their API is pretty awesome. The big difference is that `Chromeless` is based on Chrome in [headless-mode](https://developers.google.com/web/updates/2017/04/headless-chrome), and runs in a serverless function in AWS Lambda. The advantage of this is that you can run hundreds of browsers in parallel, without having to think about parallelisation. Running integration Tests for example is much faster.
213
214### I'm new to AWS Lambda, is this still for me?
215
216You still can use this locally without Lambda, so yes. Besides that, here is a [simple guide](https://github.com/graphcool/chromeless/tree/master/serverless) on how to set the lambda function up for `Chromeless`.
217
218### How much does it cost to run Chromeless in production?
219
220> The compute price is $0.00001667 per GB-s and the free tier provides 400,000 GB-s. The request price is $0.20 per 1 million requests and the free tier provides 1M requests per month.
221
222This means you can easily execute > 100.000 tests for free in the free tier.
223
224### Are there any limitations?
225
226If you're running Chromeless on AWS Lambda, the execution cannot take longer than 5 minutes which is the current limit of Lambda. Besides that, every feature that's supported in Chrome is also working with Chromeless. The maximal number of concurrent function executions is 1000. [AWS API Limits](http://docs.aws.amazon.com/lambda/latest/dg/limits.html)
227
228### Are there commercial options?
229
230Although Chromeless is the easiest way to get started running Chrome on Lambda, you may not have time to build and manage your own visual testing toolkit. Commercial options include:
231
232* [Chromatic](http://chromaticqa.com): Visual snapshot regression testing for [Storybook](https://storybook.js.org/).
233
234## Troubleshooting
235### Error: Unable to get presigned websocket URL and connect to it.
236In case you get an error like this when running the Chromeless client:
237```
238{ HTTPError: Response code 403 (Forbidden)
239 at stream.catch.then.data (/code/chromeless/node_modules/got/index.js:182:13)
240 at process._tickDomainCallback (internal/process/next_tick.js:129:7)
241 name: 'HTTPError',
242...
243Error: Unable to get presigned websocket URL and connect to it.
244```
245Make sure that you're running at least version `1.19.0` of [`serverless`](https://github.com/serverless/serverless). It is a known [issue](https://github.com/serverless/serverless/issues/2450), that the API Gateway API keys are not setup correctly in older Serverless versions. Best is to run `npm run deploy` within the project as this will use the local installed version of `serverless`.
246
247### Resource ServerlessDeploymentBucket does not exist for stack chromeless-serverless-dev
248In case the deployment of the serverless function returns an error like this:
249```
250 Serverless Error ---------------------------------------
251
252 Resource ServerlessDeploymentBucket does not exist for stack chromeless-serverless-dev
253```
254Please check, that there is no stack with the name `chromeless-serverless-dev` existing yet, otherwise serverless can't correctly provision the bucket.
255
256### No command gets executed
257In order for the commands to be processed, make sure, that you call one of the commands `screenshot`, `evaluate`, `cookiesGetAll` or `end` at the end of your execution chain.
258
259## Contributors
260
261A big thank you to all contributors and supporters of this repository 💚
262
263<a href="https://github.com/joelgriffith/" target="_blank">
264 <img src="https://github.com/joelgriffith.png?size=64" width="64" height="64" alt="joelgriffith">
265</a>
266<a href="https://github.com/adieuadieu/" target="_blank">
267 <img src="https://github.com/adieuadieu.png?size=64" width="64" height="64" alt="adieuadieu">
268</a>
269<a href="https://github.com/schickling/" target="_blank">
270 <img src="https://github.com/schickling.png?size=64" width="64" height="64" alt="schickling">
271</a>
272<a href="https://github.com/timsuchanek/" target="_blank">
273 <img src="https://github.com/timsuchanek.png?size=64" width="64" height="64" alt="timsuchanek">
274</a>
275
276
277<a href="https://github.com/Chrisgozd/" target="_blank">
278 <img src="https://github.com/Chrisgozd.png?size=64" width="64" height="64" alt="Chrisgozd">
279</a>
280<a href="https://github.com/criticalbh/" target="_blank">
281 <img src="https://github.com/criticalbh.png?size=64" width="64" height="64" alt="criticalbh">
282</a>
283<a href="https://github.com/d2s/" target="_blank">
284 <img src="https://github.com/d2s.png?size=64" width="64" height="64" alt="d2s">
285</a>
286<a href="https://github.com/emeth-/" target="_blank">
287 <img src="https://github.com/emeth-.png?size=64" width="64" height="64" alt="emeth-">
288</a>
289<a href="https://github.com/githubixx/" target="_blank">
290 <img src="https://github.com/githubixx.png?size=64" width="64" height="64" alt="githubixx">
291</a>
292<a href="https://github.com/hax/" target="_blank">
293 <img src="https://github.com/hax.png?size=64" width="64" height="64" alt="hax">
294</a>
295<a href="https://github.com/Hazealign/" target="_blank">
296 <img src="https://github.com/Hazealign.png?size=64" width="64" height="64" alt="Hazealign">
297</a>
298<a href="https://github.com/joeyvandijk/" target="_blank">
299 <img src="https://github.com/joeyvandijk.png?size=64" width="64" height="64" alt="joeyvandijk">
300</a>
301<a href="https://github.com/liady/" target="_blank">
302 <img src="https://github.com/liady.png?size=64" width="64" height="64" alt="liady">
303</a>
304<a href="https://github.com/matthewmueller/" target="_blank">
305 <img src="https://github.com/matthewmueller.png?size=64" width="64" height="64" alt="matthewmueller">
306</a>
307<a href="https://github.com/seangransee/" target="_blank">
308 <img src="https://github.com/seangransee.png?size=64" width="64" height="64" alt="seangransee">
309</a>
310<a href="https://github.com/sorenbs/" target="_blank">
311 <img src="https://github.com/sorenbs.png?size=64" width="64" height="64" alt="sorenbs">
312</a>
313<a href="https://github.com/toddwprice/" target="_blank">
314 <img src="https://github.com/toddwprice.png?size=64" width="64" height="64" alt="toddwprice">
315</a>
316<a href="https://github.com/vladgolubev/" target="_blank">
317 <img src="https://github.com/vladgolubev.png?size=64" width="64" height="64" alt="vladgolubev">
318</a>
319
320
321
322
323## Credits
324
325* [chrome-remote-interface](https://github.com/cyrus-and/chrome-remote-interface): Chromeless uses this package as an interface to Chrome
326* [serverless-chrome](https://github.com/adieuadieu/serverless-chrome): Compiled Chrome binary that runs on AWS Lambda (Azure and GCP soon, too.)
327* [NightmareJS](https://github.com/segmentio/nightmare): We draw a lot of inspiration for the API from this great tool
328
329
330<a name="help-and-community" />
331
332## Help & Community [![Slack Status](https://slack.graph.cool/badge.svg)](https://slack.graph.cool)
333
334Join our [Slack community](http://slack.graph.cool/) if you run into issues or have questions. We love talking to you!
335
336[![](http://i.imgur.com/5RHR6Ku.png)](https://www.graph.cool/)