Skip to content

Commit c3d215b

Browse files
authored
Roll to Playwright v1.38.1 (#373)
* chore: roll to playwright v1.38.1 * fix: GetByRole options etc. * feat: uninstall driver and browsers
1 parent 8575a75 commit c3d215b

25 files changed

+846
-146
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,17 @@
55
[![PkgGoDev](https://pkg.go.dev/badge/github.com/playwright-community/playwright-go)](https://pkg.go.dev/github.com/playwright-community/playwright-go)
66
[![License](https://img.shields.io/badge/License-MIT-blue.svg)](http://opensource.org/licenses/MIT)
77
[![Go Report Card](https://goreportcard.com/badge/github.com/playwright-community/playwright-go)](https://goreportcard.com/report/github.com/playwright-community/playwright-go) ![Build Status](https://github.com/playwright-community/playwright-go/workflows/Go/badge.svg)
8-
[![Join Slack](https://img.shields.io/badge/join-slack-infomational)](https://aka.ms/playwright-slack) [![Coverage Status](https://coveralls.io/repos/github/playwright-community/playwright-go/badge.svg?branch=main)](https://coveralls.io/github/playwright-community/playwright-go?branch=main) <!-- GEN:chromium-version-badge -->[![Chromium version](https://img.shields.io/badge/chromium-116.0.5845.82-blue.svg?logo=google-chrome)](https://www.chromium.org/Home)<!-- GEN:stop --> <!-- GEN:firefox-version-badge -->[![Firefox version](https://img.shields.io/badge/firefox-115.0-blue.svg?logo=mozilla-firefox)](https://www.mozilla.org/en-US/firefox/new/)<!-- GEN:stop --> <!-- GEN:webkit-version-badge -->[![WebKit version](https://img.shields.io/badge/webkit-17.0-blue.svg?logo=safari)](https://webkit.org/)<!-- GEN:stop -->
8+
[![Join Slack](https://img.shields.io/badge/join-slack-infomational)](https://aka.ms/playwright-slack) [![Coverage Status](https://coveralls.io/repos/github/playwright-community/playwright-go/badge.svg?branch=main)](https://coveralls.io/github/playwright-community/playwright-go?branch=main) <!-- GEN:chromium-version-badge -->[![Chromium version](https://img.shields.io/badge/chromium-117.0.5938.62-blue.svg?logo=google-chrome)](https://www.chromium.org/Home)<!-- GEN:stop --> <!-- GEN:firefox-version-badge -->[![Firefox version](https://img.shields.io/badge/firefox-117.0-blue.svg?logo=mozilla-firefox)](https://www.mozilla.org/en-US/firefox/new/)<!-- GEN:stop --> <!-- GEN:webkit-version-badge -->[![WebKit version](https://img.shields.io/badge/webkit-17.0-blue.svg?logo=safari)](https://webkit.org/)<!-- GEN:stop -->
99

1010
[API reference](https://playwright.dev/docs/api/class-playwright) | [Example recipes](https://github.com/playwright-community/playwright-go/tree/main/examples)
1111

1212
Playwright is a Go library to automate [Chromium](https://www.chromium.org/Home), [Firefox](https://www.mozilla.org/en-US/firefox/new/) and [WebKit](https://webkit.org/) with a single API. Playwright is built to enable cross-browser web automation that is **ever-green**, **capable**, **reliable** and **fast**.
1313

1414
| | Linux | macOS | Windows |
1515
| :--- | :---: | :---: | :---: |
16-
| Chromium <!-- GEN:chromium-version -->116.0.5845.82<!-- GEN:stop --> ||||
16+
| Chromium <!-- GEN:chromium-version -->117.0.5938.62<!-- GEN:stop --> ||||
1717
| WebKit <!-- GEN:webkit-version -->17.0<!-- GEN:stop --> ||||
18-
| Firefox <!-- GEN:firefox-version -->115.0<!-- GEN:stop --> ||||
18+
| Firefox <!-- GEN:firefox-version -->117.0<!-- GEN:stop --> ||||
1919

2020
Headless execution is supported for all the browsers on all platforms.
2121

browser.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,14 @@ func (b *browserImpl) NewContext(options ...BrowserNewContextOptions) (BrowserCo
3333
if len(options) == 1 {
3434
option = options[0]
3535
}
36+
if option.AcceptDownloads != nil {
37+
if *option.AcceptDownloads {
38+
overrides["acceptDownloads"] = "accept"
39+
} else {
40+
overrides["acceptDownloads"] = "deny"
41+
}
42+
options[0].AcceptDownloads = nil
43+
}
3644
if option.ExtraHttpHeaders != nil {
3745
overrides["extraHTTPHeaders"] = serializeMapToNameAndValue(options[0].ExtraHttpHeaders)
3846
options[0].ExtraHttpHeaders = nil

browser_context.go

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -439,7 +439,7 @@ func (b *browserContextImpl) onClose() {
439439
b.Emit("close", b)
440440
}
441441

442-
func (b *browserContextImpl) onPage(page *pageImpl) {
442+
func (b *browserContextImpl) onPage(page Page) {
443443
b.Lock()
444444
b.pages = append(b.pages, page)
445445
b.Unlock()
@@ -454,6 +454,7 @@ func (b *browserContextImpl) onRoute(route *routeImpl) {
454454
go func() {
455455
b.Lock()
456456
defer b.Unlock()
457+
route.context = b
457458
routes := make([]*routeHandlerEntry, len(b.routes))
458459
copy(routes, b.routes)
459460

@@ -578,10 +579,15 @@ func (b *browserContextImpl) OnResponse(fn func(Response)) {
578579
b.On("response", fn)
579580
}
580581

582+
func (b *browserContextImpl) OnWebError(fn func(WebError)) {
583+
b.On("weberror", fn)
584+
}
585+
581586
func newBrowserContext(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *browserContextImpl {
582587
bt := &browserContextImpl{
583588
timeoutSettings: newTimeoutSettings(nil),
584589
pages: make([]Page, 0),
590+
backgroundPages: make([]Page, 0),
585591
routes: make([]*routeHandlerEntry, 0),
586592
bindings: make(map[string]BindingCallFunction),
587593
harRecorders: make(map[string]harRecordingMetadata),
@@ -639,6 +645,19 @@ func newBrowserContext(parent *channelOwner, objectType string, guid string, ini
639645
}
640646
}()
641647
})
648+
bt.channel.On(
649+
"pageError", func(ev map[string]interface{}) {
650+
err := &Error{}
651+
remapMapToStruct(ev["error"].(map[string]interface{})["error"], err)
652+
page := fromNullableChannel(ev["page"])
653+
if page != nil {
654+
bt.Emit("weberror", newWebError(page.(*pageImpl), err))
655+
page.(*pageImpl).Emit("pageerror", err)
656+
} else {
657+
bt.Emit("weberror", newWebError(nil, err))
658+
}
659+
},
660+
)
642661
bt.channel.On("request", func(ev map[string]interface{}) {
643662
request := fromChannel(ev["request"]).(*requestImpl)
644663
page := fromNullableChannel(ev["page"])

browser_type.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,14 @@ func (b *browserTypeImpl) LaunchPersistentContext(userDataDir string, options ..
4444
if err != nil {
4545
return nil, fmt.Errorf("can not convert options: %w", err)
4646
}
47+
if options[0].AcceptDownloads != nil {
48+
if *options[0].AcceptDownloads {
49+
overrides["acceptDownloads"] = "accept"
50+
} else {
51+
overrides["acceptDownloads"] = "deny"
52+
}
53+
options[0].AcceptDownloads = nil
54+
}
4755
if options[0].ExtraHttpHeaders != nil {
4856
overrides["extraHTTPHeaders"] = serializeMapToNameAndValue(options[0].ExtraHttpHeaders)
4957
options[0].ExtraHttpHeaders = nil

examples/end-to-end-testing/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ func main() {
5151

5252
// Adding a todo entry (click in the input, enter the todo title and press the Enter key)
5353
assertErrorToNilf("could not click: %v", page.Locator("input.new-todo").Click())
54-
assertErrorToNilf("could not type: %v", page.Locator("input.new-todo").Type(todoName))
54+
assertErrorToNilf("could not type: %v", page.Locator("input.new-todo").Fill(todoName))
5555
assertErrorToNilf("could not press: %v", page.Locator("input.new-todo").Press("Enter"))
5656

5757
// After adding 1 there should be 1 entry in the list

frame.go

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package playwright
22

33
import (
4+
"errors"
45
"fmt"
56
"os"
67
"sync"
@@ -138,7 +139,10 @@ func (f *frameImpl) waitForLoadStateImpl(state string, timeout *float64, cb func
138139
if f.loadStates.Has(state) {
139140
return nil
140141
}
141-
waiter := f.setNavigationWaiter(timeout)
142+
waiter, err := f.setNavigationWaiter(timeout)
143+
if err != nil {
144+
return err
145+
}
142146
waiter.WaitForEvent(f, "loadstate", func(payload interface{}) bool {
143147
gotState := payload.(string)
144148
return gotState == state
@@ -153,6 +157,9 @@ func (f *frameImpl) waitForLoadStateImpl(state string, timeout *float64, cb func
153157
}
154158

155159
func (f *frameImpl) WaitForURL(url interface{}, options ...FrameWaitForURLOptions) error {
160+
if f.page == nil {
161+
return errors.New("frame is detached")
162+
}
156163
matcher := newURLMatcher(url, f.page.browserContext.options.BaseURL)
157164
if matcher.Matches(f.URL()) {
158165
state := "load"
@@ -179,6 +186,9 @@ func (f *frameImpl) WaitForURL(url interface{}, options ...FrameWaitForURLOption
179186
}
180187

181188
func (f *frameImpl) ExpectNavigation(cb func() error, options ...FrameExpectNavigationOptions) (Response, error) {
189+
if f.page == nil {
190+
return nil, errors.New("frame is detached")
191+
}
182192
option := FrameExpectNavigationOptions{}
183193
if len(options) == 1 {
184194
option = options[0]
@@ -201,7 +211,10 @@ func (f *frameImpl) ExpectNavigation(cb func() error, options ...FrameExpectNavi
201211
}
202212
return matcher == nil || matcher.Matches(ev["url"].(string))
203213
}
204-
waiter := f.setNavigationWaiter(option.Timeout)
214+
waiter, err := f.setNavigationWaiter(option.Timeout)
215+
if err != nil {
216+
return nil, err
217+
}
205218

206219
eventData, err := waiter.WaitForEvent(f, "navigated", predicate).RunAndWait(cb)
207220
if err != nil || eventData == nil {
@@ -223,7 +236,10 @@ func (f *frameImpl) ExpectNavigation(cb func() error, options ...FrameExpectNavi
223236
return nil, nil
224237
}
225238

226-
func (f *frameImpl) setNavigationWaiter(timeout *float64) *waiter {
239+
func (f *frameImpl) setNavigationWaiter(timeout *float64) (*waiter, error) {
240+
if f.page == nil {
241+
return nil, errors.New("page does not exist")
242+
}
227243
waiter := newWaiter()
228244
if timeout != nil {
229245
waiter.WithTimeout(*timeout)
@@ -239,7 +255,7 @@ func (f *frameImpl) setNavigationWaiter(timeout *float64) *waiter {
239255
}
240256
return false
241257
})
242-
return waiter
258+
return waiter, nil
243259
}
244260

245261
func (f *frameImpl) onFrameNavigated(ev map[string]interface{}) {
@@ -248,7 +264,8 @@ func (f *frameImpl) onFrameNavigated(ev map[string]interface{}) {
248264
f.name = ev["name"].(string)
249265
f.Unlock()
250266
f.Emit("navigated", ev)
251-
if f.page != nil {
267+
_, ok := ev["error"]
268+
if !ok && f.page != nil {
252269
f.page.Emit("framenavigated", f)
253270
}
254271
}
@@ -258,6 +275,11 @@ func (f *frameImpl) onLoadState(ev map[string]interface{}) {
258275
add := ev["add"].(string)
259276
f.loadStates.Add(add)
260277
f.Emit("loadstate", add)
278+
if f.parentFrame == nil && f.page != nil {
279+
if add == "load" || add == "domcontentloaded" {
280+
f.Page().Emit(add, f.page)
281+
}
282+
}
261283
} else if ev["remove"] != nil {
262284
remove := ev["remove"].(string)
263285
f.loadStates.Remove(remove)

generated-interfaces.go

Lines changed: 47 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,10 @@ type BrowserContext interface {
245245
// most cases).
246246
OnPage(fn func(Page))
247247

248+
// Emitted when exception is unhandled in any of the pages in this context. To listen for errors from a particular
249+
// page, use [Page.OnPageError] instead.
250+
OnWebError(fn func(WebError))
251+
248252
// Emitted when a request is issued from any pages created through this context. The [request] object is read-only. To
249253
// only listen for requests from a particular page, use [Page.OnRequest].
250254
// In order to intercept and mutate requests, see [BrowserContext.Route] or [Page.Route].
@@ -585,7 +589,7 @@ type Dialog interface {
585589

586590
// [Download] objects are dispatched by page via the [Page.OnDownload] event.
587591
// All the downloaded files belonging to the browser context are deleted when the browser context is closed.
588-
// Download event is emitted once the download starts. Download path becomes available once download completes:
592+
// Download event is emitted once the download starts. Download path becomes available once download completes.
589593
type Download interface {
590594
// Cancels a download. Will not fail if the download is already finished or canceled. Upon successful cancellations,
591595
// `download.failure()` would resolve to `canceled`.
@@ -746,7 +750,7 @@ type ElementHandle interface {
746750
// error. However, if the element is inside the `<label>` element that has an associated
747751
// [control], the control will be filled
748752
// instead.
749-
// To send fine-grained keyboard events, use [ElementHandle.Type].
753+
// To send fine-grained keyboard events, use [Locator.PressSequentially].
750754
//
751755
// value: Value to set for the `<input>`, `<textarea>` or `[contenteditable]` element.
752756
//
@@ -946,6 +950,8 @@ type ElementHandle interface {
946950
// text.
947951
// To press a special key, like `Control` or `ArrowDown`, use [ElementHandle.Press].
948952
//
953+
// Deprecated: In most cases, you should use [Locator.Fill] instead. You only need to press keys one by one if there is special keyboard handling on the page - in this case use [Locator.PressSequentially].
954+
//
949955
// text: A text to type into a focused element.
950956
Type(text string, options ...ElementHandleTypeOptions) error
951957

@@ -1191,7 +1197,7 @@ type Frame interface {
11911197
// error. However, if the element is inside the `<label>` element that has an associated
11921198
// [control], the control will be filled
11931199
// instead.
1194-
// To send fine-grained keyboard events, use [Frame.Type].
1200+
// To send fine-grained keyboard events, use [Locator.PressSequentially].
11951201
//
11961202
// Deprecated: Use locator-based [Locator.Fill] instead. Read more about [locators].
11971203
//
@@ -1621,13 +1627,11 @@ type Frame interface {
16211627
// to send fine-grained keyboard events. To fill values in form fields, use [Frame.Fill].
16221628
// To press a special key, like `Control` or `ArrowDown`, use [Keyboard.Press].
16231629
//
1624-
// Deprecated: Use locator-based [Locator.Type] instead. Read more about [locators].
1630+
// Deprecated: In most cases, you should use [Locator.Fill] instead. You only need to press keys one by one if there is special keyboard handling on the page - in this case use [Locator.PressSequentially].
16251631
//
16261632
// 1. selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
16271633
// used.
16281634
// 2. text: A text to type into a focused element.
1629-
//
1630-
// [locators]: https://playwright.dev/docs/locators
16311635
Type(selector string, text string, options ...FrameTypeOptions) error
16321636

16331637
// This method checks an element matching “selector” by performing the following steps:
@@ -1904,6 +1908,7 @@ type Keyboard interface {
19041908
// text: Sets input to the specified text value.
19051909
InsertText(text string) error
19061910

1911+
// **NOTE** In most cases, you should use [Locator.Press] instead.
19071912
// “key” can specify the intended
19081913
// [keyboardEvent.Key] value or a single character
19091914
// to generate the text for. A superset of the “key” values can be found
@@ -1924,6 +1929,8 @@ type Keyboard interface {
19241929
// [here]: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values
19251930
Press(key string, options ...KeyboardPressOptions) error
19261931

1932+
// **NOTE** In most cases, you should use [Locator.Fill] instead. You only need to press keys one by one if there is
1933+
// special keyboard handling on the page - in this case use [Locator.PressSequentially].
19271934
// Sends a `keydown`, `keypress`/`input`, and `keyup` event for each character in the text.
19281935
// To press a special key, like `Control` or `ArrowDown`, use [Keyboard.Press].
19291936
//
@@ -2164,7 +2171,7 @@ type Locator interface {
21642171
// error. However, if the element is inside the `<label>` element that has an associated
21652172
// [control], the control will be filled
21662173
// instead.
2167-
// To send fine-grained keyboard events, use [Locator.Type].
2174+
// To send fine-grained keyboard events, use [Locator.PressSequentially].
21682175
//
21692176
// value: Value to set for the `<input>`, `<textarea>` or `[contenteditable]` element.
21702177
//
@@ -2380,6 +2387,15 @@ type Locator interface {
23802387
// [here]: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values
23812388
Press(key string, options ...LocatorPressOptions) error
23822389

2390+
// **NOTE** In most cases, you should use [Locator.Fill] instead. You only need to press keys one by one if there is
2391+
// special keyboard handling on the page.
2392+
// Focuses the element, and then sends a `keydown`, `keypress`/`input`, and `keyup` event for each character in the
2393+
// text.
2394+
// To press a special key, like `Control` or `ArrowDown`, use [Locator.Press].
2395+
//
2396+
// text: String of characters to sequentially press into a focused element.
2397+
PressSequentially(text string, options ...LocatorPressSequentiallyOptions) error
2398+
23832399
// Take a screenshot of the element matching the locator.
23842400
//
23852401
// # Details
@@ -2487,12 +2503,12 @@ type Locator interface {
24872503
// [`node.textContent`]: https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent
24882504
TextContent(options ...LocatorTextContentOptions) (string, error)
24892505

2490-
// **NOTE** In most cases, you should use [Locator.Fill] instead. You only need to type characters if there is special
2491-
// keyboard handling on the page.
24922506
// Focuses the element, and then sends a `keydown`, `keypress`/`input`, and `keyup` event for each character in the
24932507
// text.
24942508
// To press a special key, like `Control` or `ArrowDown`, use [Locator.Press].
24952509
//
2510+
// Deprecated: In most cases, you should use [Locator.Fill] instead. You only need to press keys one by one if there is special keyboard handling on the page - in this case use [Locator.PressSequentially].
2511+
//
24962512
// text: A text to type into a focused element.
24972513
Type(text string, options ...LocatorTypeOptions) error
24982514

@@ -2977,7 +2993,7 @@ type Page interface {
29772993
// error. However, if the element is inside the `<label>` element that has an associated
29782994
// [control], the control will be filled
29792995
// instead.
2980-
// To send fine-grained keyboard events, use [Page.Type].
2996+
// To send fine-grained keyboard events, use [Locator.PressSequentially].
29812997
//
29822998
// Deprecated: Use locator-based [Locator.Fill] instead. Read more about [locators].
29832999
//
@@ -3512,13 +3528,11 @@ type Page interface {
35123528
// send fine-grained keyboard events. To fill values in form fields, use [Page.Fill].
35133529
// To press a special key, like `Control` or `ArrowDown`, use [Keyboard.Press].
35143530
//
3515-
// Deprecated: Use locator-based [Locator.Type] instead. Read more about [locators].
3531+
// Deprecated: In most cases, you should use [Locator.Fill] instead. You only need to press keys one by one if there is special keyboard handling on the page - in this case use [Locator.PressSequentially].
35163532
//
35173533
// 1. selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
35183534
// used.
35193535
// 2. text: A text to type into a focused element.
3520-
//
3521-
// [locators]: https://playwright.dev/docs/locators
35223536
Type(selector string, text string, options ...PageTypeOptions) error
35233537

35243538
// This method unchecks an element matching “selector” by performing the following steps:
@@ -3746,6 +3760,14 @@ type Request interface {
37463760
Failure() error
37473761

37483762
// Returns the [Frame] that initiated this request.
3763+
//
3764+
// # Details
3765+
//
3766+
// Note that in some cases the frame is not available, and this method will throw.
3767+
// - When request originates in the Service Worker. You can use `request.serviceWorker()` to check that.
3768+
// - When navigation request is issued before the corresponding frame is created. You can use
3769+
// [Request.IsNavigationRequest] to check that.
3770+
// Here is an example that handles all the cases:
37493771
Frame() Frame
37503772

37513773
// An object with the request HTTP headers. The header names are lower-cased. Note that this method does not return
@@ -3763,6 +3785,8 @@ type Request interface {
37633785
HeaderValue(name string) (string, error)
37643786

37653787
// Whether this request is driving frame's navigation.
3788+
// Some navigation requests are issued before the corresponding frame is created, and therefore do not have
3789+
// [Request.Frame] available.
37663790
IsNavigationRequest() bool
37673791

37683792
// Request's method (GET, POST, etc.)
@@ -3982,6 +4006,16 @@ type Video interface {
39824006
SaveAs(path string) error
39834007
}
39844008

4009+
// [WebError] class represents an unhandled exeception thrown in the page. It is dispatched via the
4010+
// [BrowserContext.OnWebError] event.
4011+
type WebError interface {
4012+
// The page that produced this unhandled exception, if any.
4013+
Page() Page
4014+
4015+
// Unhandled error that was thrown.
4016+
Error() error
4017+
}
4018+
39854019
// The [WebSocket] class represents websocket connections in the page.
39864020
type WebSocket interface {
39874021
// Fired when the websocket closes.

0 commit comments

Comments
 (0)