diff --git a/README.md b/README.md
index 208b9b14..a96c8a12 100644
--- a/README.md
+++ b/README.md
@@ -148,7 +148,7 @@ const chromeless = new Chromeless({
- [`end()`](docs/api.md#api-end)
**Chrome methods**
-- [`goto(url: string)`](docs/api.md#api-goto)
+- [`goto(url: string, timeout?: number)`](docs/api.md#api-goto)
- [`setUserAgent(useragent: string)`](docs/api.md#api-setUserAgent)
- [`click(selector: string)`](docs/api.md#api-click)
- [`wait(timeout: number)`](docs/api.md#api-wait-timeout)
diff --git a/docs/api.md b/docs/api.md
index 35ca0af0..bd23d660 100644
--- a/docs/api.md
+++ b/docs/api.md
@@ -19,7 +19,7 @@ Chromeless provides TypeScript typings.
- [`end()`](#api-end)
### Chrome methods
-- [`goto(url: string)`](#api-goto)
+- [`goto(url: string, timeout?: number)`](#api-goto)
- [`setUserAgent(useragent: string)`](#api-setuseragent)
- [`click(selector: string)`](#api-click)
- [`wait(timeout: number)`](#api-wait-timeout)
@@ -73,12 +73,13 @@ await chromeless.end()
-### goto(url: string): Chromeless
+### goto(url: string, timeout?: number): Chromeless
Navigate to a URL.
__Arguments__
- `url` - URL to navigate to
+- `timeout` -How long to wait for page to load (default is value of waitTimeout option)
__Example__
@@ -173,7 +174,7 @@ __Arguments__
__Example__
```js
-await chromeless.wait(() => {
+await chromeless.wait(() => {
return new Promise((resolve, reject) => {
// do something async, setTimeout...
resolve();
diff --git a/package-lock.json b/package-lock.json
index d0db1e1d..8be9b7a5 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -2,7 +2,6 @@
"name": "chromeless",
"version": "1.4.0",
"lockfileVersion": 1,
- "requires": true,
"dependencies": {
"@ava/babel-plugin-throws-helper": {
"version": "2.0.0",
@@ -5958,6 +5957,16 @@
"integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=",
"dev": true
},
+ "JSONStream": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.2.tgz",
+ "integrity": "sha1-wQI3G27Dp887hHygDCC7D85Mbeo=",
+ "dev": true,
+ "requires": {
+ "jsonparse": "1.3.1",
+ "through": "2.3.8"
+ }
+ },
"jsprim": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
@@ -11082,6 +11091,14 @@
"resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz",
"integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM="
},
+ "string_decoder": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
+ "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
+ "requires": {
+ "safe-buffer": "5.1.1"
+ }
+ },
"string-width": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
@@ -11109,14 +11126,6 @@
}
}
},
- "string_decoder": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
- "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
- "requires": {
- "safe-buffer": "5.1.1"
- }
- },
"stringify-object": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.2.2.tgz",
diff --git a/src/api.ts b/src/api.ts
index 840a977e..24c3cbc6 100644
--- a/src/api.ts
+++ b/src/api.ts
@@ -73,8 +73,8 @@ export default class Chromeless implements Promise {
return this.lastReturnPromise.catch(onrejected) as Promise
}
- goto(url: string): Chromeless {
- this.queue.enqueue({ type: 'goto', url })
+ goto(url: string, timeout?: number): Chromeless {
+ this.queue.enqueue({ type: 'goto', url, timeout })
return this
}
diff --git a/src/chrome/local-runtime.ts b/src/chrome/local-runtime.ts
index af1f7392..016caa5b 100644
--- a/src/chrome/local-runtime.ts
+++ b/src/chrome/local-runtime.ts
@@ -40,6 +40,8 @@ import {
writeToFile,
isS3Configured,
uploadToS3,
+ eventToPromise,
+ waitForPromise,
} from '../util'
export default class LocalRuntime {
@@ -55,7 +57,7 @@ export default class LocalRuntime {
async run(command: Command): Promise {
switch (command.type) {
case 'goto':
- return this.goto(command.url)
+ return this.goto(command.url, command.timeout)
case 'setViewport':
return setViewport(this.client, command.options)
case 'wait': {
@@ -126,13 +128,18 @@ export default class LocalRuntime {
}
}
- private async goto(url: string): Promise {
+ private async goto(
+ url: string,
+ waitTimeout: number = this.chromelessOptions.waitTimeout,
+ ): Promise {
const { Network, Page } = this.client
await Promise.all([Network.enable(), Page.enable()])
if (!this.userAgentValue) this.userAgentValue = `Chromeless ${version}`
await Network.setUserAgentOverride({ userAgent: this.userAgentValue })
+ const e2p = eventToPromise()
+ Page.loadEventFired(e2p.onEvent)
await Page.navigate({ url })
- await Page.loadEventFired()
+ await waitForPromise(e2p.fired(), waitTimeout, 'page load event')
this.log(`Navigated to ${url}`)
}
diff --git a/src/types.ts b/src/types.ts
index 5f5c7f97..ef09ec64 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -64,6 +64,7 @@ export type Command =
| {
type: 'goto'
url: string
+ timeout?: number
}
| {
type: 'clearCache'
diff --git a/src/util.ts b/src/util.ts
index f46f9eb0..03d89947 100644
--- a/src/util.ts
+++ b/src/util.ts
@@ -106,6 +106,42 @@ export async function wait(timeout: number): Promise {
return new Promise((resolve, reject) => setTimeout(resolve, timeout))
}
+export async function waitForPromise(
+ promise: Promise,
+ waitTimeout: number,
+ label?: string,
+): Promise {
+ return new Promise((resolve, reject) => {
+ let fullfilled = false
+ setTimeout(() => {
+ fullfilled = true
+ reject(
+ new Error(
+ `wait(${label || 'Promise'}) timed out after ${waitTimeout}ms`,
+ ),
+ )
+ }, waitTimeout)
+ return promise
+ .then(res => (fullfilled ? void 0 : resolve(res)))
+ .catch(err => (fullfilled ? void 0 : reject(err)))
+ })
+}
+
+export function eventToPromise() {
+ let resolve
+ const promise = new Promise(res => {
+ resolve = res
+ })
+ return {
+ onEvent(...args) {
+ resolve(args.length > 1 ? args : args[0])
+ },
+ fired() {
+ return promise
+ },
+ }
+}
+
export async function nodeExists(
client: Client,
selector: string,