2021-03-19 20:44:03 +01:00
|
|
|
---
|
|
|
|
|
id: events
|
|
|
|
|
title: "Events"
|
|
|
|
|
---
|
|
|
|
|
|
2021-03-24 01:17:59 +01:00
|
|
|
Playwright allows listening to various types of events happening in the web page, such
|
2021-03-19 20:44:03 +01:00
|
|
|
as network requests, creation of child pages, dedicated workers etc. There are several
|
|
|
|
|
ways to subscribe to such events:
|
|
|
|
|
|
|
|
|
|
<!-- TOC -->
|
|
|
|
|
|
|
|
|
|
## Waiting for event
|
|
|
|
|
|
2021-03-24 01:17:59 +01:00
|
|
|
Most of the time, scripts will need to wait for a particular event to happen. Below are some of the typical event
|
|
|
|
|
awaiting patterns.
|
2021-03-19 20:44:03 +01:00
|
|
|
|
2021-03-24 01:17:59 +01:00
|
|
|
Wait for a request with the specified url:
|
2021-03-19 20:44:03 +01:00
|
|
|
|
|
|
|
|
```js
|
2021-04-23 17:53:25 +02:00
|
|
|
// Note that Promise.all prevents a race condition
|
|
|
|
|
// between clicking and waiting for the request.
|
2021-03-19 20:44:03 +01:00
|
|
|
const [request] = await Promise.all([
|
|
|
|
|
page.waitForRequest('**/*logo*.png'),
|
2021-04-23 17:53:25 +02:00
|
|
|
// This action triggers the request
|
2021-03-19 20:44:03 +01:00
|
|
|
page.goto('https://wikipedia.org')
|
|
|
|
|
]);
|
|
|
|
|
console.log(request.url());
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
// The callback lambda defines scope of the code that is expected to
|
|
|
|
|
// trigger request.
|
|
|
|
|
Request request = page.waitForRequest("**/*logo*.png", () -> {
|
|
|
|
|
page.navigate("https://wikipedia.org");
|
|
|
|
|
});
|
|
|
|
|
System.out.println(request.url());
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```python async
|
|
|
|
|
async with page.expect_request("**/*logo*.png") as first:
|
|
|
|
|
await page.goto("https://wikipedia.org")
|
|
|
|
|
first_request = await first.value
|
|
|
|
|
print(first_request.url)
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```python sync
|
|
|
|
|
with page.expect_request("**/*logo*.png") as first:
|
|
|
|
|
page.goto("https://wikipedia.org")
|
|
|
|
|
print(first.value.url)
|
|
|
|
|
```
|
|
|
|
|
|
2021-05-15 20:57:20 +02:00
|
|
|
```csharp
|
|
|
|
|
var waitForRequestTask = page.WaitForRequestAsync("**/*logo*.png");
|
|
|
|
|
await page.GotoAsync("https://wikipedia.org");
|
|
|
|
|
var request = await waitForRequestTask;
|
|
|
|
|
Console.WriteLine(request.Url);
|
|
|
|
|
```
|
|
|
|
|
|
2021-03-24 01:17:59 +01:00
|
|
|
Wait for popup window:
|
2021-03-19 20:44:03 +01:00
|
|
|
|
|
|
|
|
```js
|
2021-04-23 17:53:25 +02:00
|
|
|
// Note that Promise.all prevents a race condition
|
|
|
|
|
// between clicking and waiting for the popup.
|
2021-03-19 20:44:03 +01:00
|
|
|
const [popup] = await Promise.all([
|
2022-01-13 19:38:22 +01:00
|
|
|
// It is important to call waitForEvent first.
|
2021-03-19 20:44:03 +01:00
|
|
|
page.waitForEvent('popup'),
|
2021-04-23 17:53:25 +02:00
|
|
|
// This action triggers the popup
|
2021-03-19 20:44:03 +01:00
|
|
|
page.evaluate('window.open()')
|
|
|
|
|
]);
|
|
|
|
|
await popup.goto('https://wikipedia.org');
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
// The callback lambda defines scope of the code that is expected to
|
|
|
|
|
// create popup window.
|
|
|
|
|
Page popup = page.waitForPopup(() -> {
|
|
|
|
|
page.evaluate("window.open()");
|
|
|
|
|
});
|
|
|
|
|
popup.navigate("https://wikipedia.org");
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```python async
|
|
|
|
|
async with page.expect_popup() as popup:
|
|
|
|
|
await page.evaluate("window.open()")
|
|
|
|
|
child_page = await popup.value
|
|
|
|
|
await child_page.goto("https://wikipedia.org")
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```python sync
|
|
|
|
|
with page.expect_popup() as popup:
|
|
|
|
|
page.evaluate("window.open()")
|
|
|
|
|
popup.value.goto("https://wikipedia.org")
|
|
|
|
|
```
|
|
|
|
|
|
2021-05-15 20:57:20 +02:00
|
|
|
```csharp
|
2021-05-27 00:11:31 +02:00
|
|
|
var popup = await page.RunAndWaitForPopupAsync(async =>
|
2021-05-20 02:19:25 +02:00
|
|
|
{
|
|
|
|
|
await page.EvaluateAsync("window.open()");
|
|
|
|
|
});
|
2021-05-15 20:57:20 +02:00
|
|
|
await popup.GotoAsync("https://wikipedia.org");
|
|
|
|
|
```
|
|
|
|
|
|
2021-03-19 20:44:03 +01:00
|
|
|
## Adding/removing event listener
|
|
|
|
|
|
2021-03-24 01:17:59 +01:00
|
|
|
Sometimes, events happen in random time and instead of waiting for them, they need to be handled.
|
|
|
|
|
Playwright supports traditional language mechanisms for subscribing and unsubscribing from the events:
|
2021-03-19 20:44:03 +01:00
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
page.on('request', request => console.log(`Request sent: ${request.url()}`));
|
|
|
|
|
const listener = request => console.log(`Request finished: ${request.url()}`);
|
|
|
|
|
page.on('requestfinished', listener);
|
|
|
|
|
await page.goto('https://wikipedia.org');
|
|
|
|
|
|
|
|
|
|
page.off('requestfinished', listener);
|
|
|
|
|
await page.goto('https://www.openstreetmap.org/');
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
page.onRequest(request -> System.out.println("Request sent: " + request.url()));
|
|
|
|
|
Consumer<Request> listener = request -> System.out.println("Request finished: " + request.url());
|
|
|
|
|
page.onRequestFinished(listener);
|
|
|
|
|
page.navigate("https://wikipedia.org");
|
|
|
|
|
|
|
|
|
|
// Remove previously added listener, each on* method has corresponding off*
|
|
|
|
|
page.offRequestFinished(listener);
|
|
|
|
|
page.navigate("https://www.openstreetmap.org/");
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```python async
|
|
|
|
|
def print_request_sent(request):
|
|
|
|
|
print("Request sent: " + request.url)
|
|
|
|
|
|
|
|
|
|
def print_request_finished(request):
|
|
|
|
|
print("Request finished: " + request.url)
|
|
|
|
|
|
|
|
|
|
page.on("request", print_request_sent)
|
|
|
|
|
page.on("requestfinished", print_request_finished)
|
|
|
|
|
await page.goto("https://wikipedia.org")
|
|
|
|
|
|
|
|
|
|
page.remove_listener("requestfinished", print_request_finished)
|
|
|
|
|
await page.goto("https://www.openstreetmap.org/")
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```python sync
|
|
|
|
|
def print_request_sent(request):
|
|
|
|
|
print("Request sent: " + request.url)
|
|
|
|
|
|
|
|
|
|
def print_request_finished(request):
|
|
|
|
|
print("Request finished: " + request.url)
|
|
|
|
|
|
|
|
|
|
page.on("request", print_request_sent)
|
|
|
|
|
page.on("requestfinished", print_request_finished)
|
|
|
|
|
page.goto("https://wikipedia.org")
|
|
|
|
|
|
|
|
|
|
page.remove_listener("requestfinished", print_request_finished)
|
|
|
|
|
page.goto("https://www.openstreetmap.org/")
|
|
|
|
|
```
|
|
|
|
|
|
2021-05-15 20:57:20 +02:00
|
|
|
```csharp
|
|
|
|
|
page.Request += (_, request) => Console.WriteLine("Request sent: " + request.Url);
|
2021-05-15 23:02:07 +02:00
|
|
|
void listener(object sender, IRequest request)
|
|
|
|
|
{
|
|
|
|
|
Console.WriteLine("Request finished: " + request.Url);
|
2021-05-15 20:57:20 +02:00
|
|
|
};
|
|
|
|
|
page.RequestFinished += listener;
|
|
|
|
|
await page.GotoAsync("https://wikipedia.org");
|
|
|
|
|
|
2021-05-15 23:02:07 +02:00
|
|
|
// Remove previously added listener.
|
2021-05-15 20:57:20 +02:00
|
|
|
page.RequestFinished -= listener;
|
|
|
|
|
await page.GotoAsync("https://www.openstreetmap.org/");
|
|
|
|
|
```
|
|
|
|
|
|
2021-03-19 20:44:03 +01:00
|
|
|
## Adding one-off listeners
|
2021-05-15 23:02:07 +02:00
|
|
|
* langs: js, python, java
|
2021-03-19 20:44:03 +01:00
|
|
|
|
2021-03-24 01:17:59 +01:00
|
|
|
If certain event needs to be handled once, there is a convenience API for that:
|
2021-03-19 20:44:03 +01:00
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
page.once('dialog', dialog => dialog.accept("2021"));
|
|
|
|
|
await page.evaluate("prompt('Enter a number:')");
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
page.onceDialog(dialog -> dialog.accept("2021"));
|
|
|
|
|
page.evaluate("prompt('Enter a number:')");
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```python async
|
|
|
|
|
page.once("dialog", lambda dialog: dialog.accept("2021"))
|
|
|
|
|
await page.evaluate("prompt('Enter a number:')")
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```python sync
|
|
|
|
|
page.once("dialog", lambda dialog: dialog.accept("2021"))
|
|
|
|
|
page.evaluate("prompt('Enter a number:')")
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### API reference
|
|
|
|
|
|
|
|
|
|
- [Browser]
|
|
|
|
|
- [BrowserContext]
|
|
|
|
|
- [Page]
|
|
|
|
|
- [Worker]
|