summaryrefslogtreecommitdiff
path: root/vendor/github.com
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com')
-rw-r--r--vendor/github.com/deckarep/golang-set/v2/.gitignore23
-rw-r--r--vendor/github.com/deckarep/golang-set/v2/LICENSE22
-rw-r--r--vendor/github.com/deckarep/golang-set/v2/README.md190
-rw-r--r--vendor/github.com/deckarep/golang-set/v2/iterator.go58
-rw-r--r--vendor/github.com/deckarep/golang-set/v2/new_improved.jpegbin0 -> 120935 bytes
-rw-r--r--vendor/github.com/deckarep/golang-set/v2/set.go255
-rw-r--r--vendor/github.com/deckarep/golang-set/v2/sorted.go42
-rw-r--r--vendor/github.com/deckarep/golang-set/v2/threadsafe.go299
-rw-r--r--vendor/github.com/deckarep/golang-set/v2/threadunsafe.go332
-rw-r--r--vendor/github.com/go-stack/stack/LICENSE.md21
-rw-r--r--vendor/github.com/go-stack/stack/README.md38
-rw-r--r--vendor/github.com/go-stack/stack/stack.go400
-rw-r--r--vendor/github.com/magiconair/properties/properties.go112
-rw-r--r--vendor/github.com/playwright-community/playwright-go/.gitattributes3
-rw-r--r--vendor/github.com/playwright-community/playwright-go/.gitignore34
-rw-r--r--vendor/github.com/playwright-community/playwright-go/.gitmodules3
-rw-r--r--vendor/github.com/playwright-community/playwright-go/.golangci.yaml6
-rw-r--r--vendor/github.com/playwright-community/playwright-go/.nojekyll0
-rw-r--r--vendor/github.com/playwright-community/playwright-go/404.html25
-rw-r--r--vendor/github.com/playwright-community/playwright-go/CONTRIBUTING.md39
-rw-r--r--vendor/github.com/playwright-community/playwright-go/Dockerfile.example25
-rw-r--r--vendor/github.com/playwright-community/playwright-go/LICENSE21
-rw-r--r--vendor/github.com/playwright-community/playwright-go/README.md148
-rw-r--r--vendor/github.com/playwright-community/playwright-go/_config.yml21
-rw-r--r--vendor/github.com/playwright-community/playwright-go/apiresponse_assertions.go75
-rw-r--r--vendor/github.com/playwright-community/playwright-go/artifact.go70
-rw-r--r--vendor/github.com/playwright-community/playwright-go/assertions.go146
-rw-r--r--vendor/github.com/playwright-community/playwright-go/binding_call.go87
-rw-r--r--vendor/github.com/playwright-community/playwright-go/browser.go274
-rw-r--r--vendor/github.com/playwright-community/playwright-go/browser_context.go914
-rw-r--r--vendor/github.com/playwright-community/playwright-go/browser_type.go181
-rw-r--r--vendor/github.com/playwright-community/playwright-go/cdp_session.go38
-rw-r--r--vendor/github.com/playwright-community/playwright-go/channel.go92
-rw-r--r--vendor/github.com/playwright-community/playwright-go/channel_owner.go122
-rw-r--r--vendor/github.com/playwright-community/playwright-go/clock.go111
-rw-r--r--vendor/github.com/playwright-community/playwright-go/connection.go401
-rw-r--r--vendor/github.com/playwright-community/playwright-go/console_message.go47
-rw-r--r--vendor/github.com/playwright-community/playwright-go/dialog.go48
-rw-r--r--vendor/github.com/playwright-community/playwright-go/download.go56
-rw-r--r--vendor/github.com/playwright-community/playwright-go/element_handle.go403
-rw-r--r--vendor/github.com/playwright-community/playwright-go/errors.go58
-rw-r--r--vendor/github.com/playwright-community/playwright-go/event_emitter.go163
-rw-r--r--vendor/github.com/playwright-community/playwright-go/fetch.go451
-rw-r--r--vendor/github.com/playwright-community/playwright-go/file_chooser.go44
-rw-r--r--vendor/github.com/playwright-community/playwright-go/frame.go792
-rw-r--r--vendor/github.com/playwright-community/playwright-go/frame_locator.go130
-rw-r--r--vendor/github.com/playwright-community/playwright-go/generated-enums.go404
-rw-r--r--vendor/github.com/playwright-community/playwright-go/generated-interfaces.go4658
-rw-r--r--vendor/github.com/playwright-community/playwright-go/generated-structs.go4364
-rw-r--r--vendor/github.com/playwright-community/playwright-go/glob.go170
-rw-r--r--vendor/github.com/playwright-community/playwright-go/har_router.go110
-rw-r--r--vendor/github.com/playwright-community/playwright-go/helpers.go628
-rw-r--r--vendor/github.com/playwright-community/playwright-go/input.go117
-rw-r--r--vendor/github.com/playwright-community/playwright-go/input_files_helper.go202
-rw-r--r--vendor/github.com/playwright-community/playwright-go/internal/safe/map.go90
-rw-r--r--vendor/github.com/playwright-community/playwright-go/js_handle.go421
-rw-r--r--vendor/github.com/playwright-community/playwright-go/jsonPipe.go64
-rw-r--r--vendor/github.com/playwright-community/playwright-go/local_utils.go165
-rw-r--r--vendor/github.com/playwright-community/playwright-go/locator.go914
-rw-r--r--vendor/github.com/playwright-community/playwright-go/locator_assertions.go568
-rw-r--r--vendor/github.com/playwright-community/playwright-go/locator_helpers.go133
-rw-r--r--vendor/github.com/playwright-community/playwright-go/network.go62
-rw-r--r--vendor/github.com/playwright-community/playwright-go/objectFactory.go74
-rw-r--r--vendor/github.com/playwright-community/playwright-go/page.go1384
-rw-r--r--vendor/github.com/playwright-community/playwright-go/page_assertions.go70
-rw-r--r--vendor/github.com/playwright-community/playwright-go/playwright.go64
-rw-r--r--vendor/github.com/playwright-community/playwright-go/request.go274
-rw-r--r--vendor/github.com/playwright-community/playwright-go/response.go162
-rw-r--r--vendor/github.com/playwright-community/playwright-go/route.go270
-rw-r--r--vendor/github.com/playwright-community/playwright-go/run.go409
-rw-r--r--vendor/github.com/playwright-community/playwright-go/run_unix.go10
-rw-r--r--vendor/github.com/playwright-community/playwright-go/run_win.go10
-rw-r--r--vendor/github.com/playwright-community/playwright-go/selectors.go88
-rw-r--r--vendor/github.com/playwright-community/playwright-go/stream.go68
-rw-r--r--vendor/github.com/playwright-community/playwright-go/tracing.go164
-rw-r--r--vendor/github.com/playwright-community/playwright-go/transport.go141
-rw-r--r--vendor/github.com/playwright-community/playwright-go/type_helpers.go72
-rw-r--r--vendor/github.com/playwright-community/playwright-go/video.go97
-rw-r--r--vendor/github.com/playwright-community/playwright-go/waiter.go181
-rw-r--r--vendor/github.com/playwright-community/playwright-go/web_error.go21
-rw-r--r--vendor/github.com/playwright-community/playwright-go/websocket.go134
-rw-r--r--vendor/github.com/playwright-community/playwright-go/websocket_route.go220
-rw-r--r--vendor/github.com/playwright-community/playwright-go/worker.go78
-rw-r--r--vendor/github.com/playwright-community/playwright-go/writable_stream.go44
-rw-r--r--vendor/github.com/testcontainers/testcontainers-go/.golangci.yml149
-rw-r--r--vendor/github.com/testcontainers/testcontainers-go/Makefile2
-rw-r--r--vendor/github.com/testcontainers/testcontainers-go/Pipfile4
-rw-r--r--vendor/github.com/testcontainers/testcontainers-go/Pipfile.lock265
-rw-r--r--vendor/github.com/testcontainers/testcontainers-go/commons-test.mk2
-rw-r--r--vendor/github.com/testcontainers/testcontainers-go/container.go52
-rw-r--r--vendor/github.com/testcontainers/testcontainers-go/docker.go30
-rw-r--r--vendor/github.com/testcontainers/testcontainers-go/docker_client.go2
-rw-r--r--vendor/github.com/testcontainers/testcontainers-go/docker_mounts.go54
-rw-r--r--vendor/github.com/testcontainers/testcontainers-go/generic.go31
-rw-r--r--vendor/github.com/testcontainers/testcontainers-go/internal/core/bootstrap.go2
-rw-r--r--vendor/github.com/testcontainers/testcontainers-go/internal/version.go2
-rw-r--r--vendor/github.com/testcontainers/testcontainers-go/lifecycle.go30
-rw-r--r--vendor/github.com/testcontainers/testcontainers-go/mkdocs.yml10
-rw-r--r--vendor/github.com/testcontainers/testcontainers-go/mounts.go51
-rw-r--r--vendor/github.com/testcontainers/testcontainers-go/options.go125
-rw-r--r--vendor/github.com/testcontainers/testcontainers-go/port_forwarding.go2
-rw-r--r--vendor/github.com/testcontainers/testcontainers-go/reaper.go2
-rw-r--r--vendor/github.com/testcontainers/testcontainers-go/runtime.txt2
-rw-r--r--vendor/github.com/testcontainers/testcontainers-go/testing.go15
-rw-r--r--vendor/github.com/testcontainers/testcontainers-go/validator.go7
-rw-r--r--vendor/github.com/testcontainers/testcontainers-go/wait/all.go8
-rw-r--r--vendor/github.com/testcontainers/testcontainers-go/wait/http.go4
-rw-r--r--vendor/github.com/testcontainers/testcontainers-go/wait/walk.go24
108 files changed, 24530 insertions, 270 deletions
diff --git a/vendor/github.com/deckarep/golang-set/v2/.gitignore b/vendor/github.com/deckarep/golang-set/v2/.gitignore
new file mode 100644
index 0000000..4eb156d
--- /dev/null
+++ b/vendor/github.com/deckarep/golang-set/v2/.gitignore
@@ -0,0 +1,23 @@
+# Compiled Object files, Static and Dynamic libs (Shared Objects)
+*.o
+*.a
+*.so
+
+# Folders
+_obj
+_test
+
+# Architecture specific extensions/prefixes
+*.[568vq]
+[568vq].out
+
+*.cgo1.go
+*.cgo2.c
+_cgo_defun.c
+_cgo_gotypes.go
+_cgo_export.*
+
+_testmain.go
+
+*.exe
+.idea \ No newline at end of file
diff --git a/vendor/github.com/deckarep/golang-set/v2/LICENSE b/vendor/github.com/deckarep/golang-set/v2/LICENSE
new file mode 100644
index 0000000..efd4827
--- /dev/null
+++ b/vendor/github.com/deckarep/golang-set/v2/LICENSE
@@ -0,0 +1,22 @@
+Open Source Initiative OSI - The MIT License (MIT):Licensing
+
+The MIT License (MIT)
+Copyright (c) 2013 - 2022 Ralph Caraveo (deckarep@gmail.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE. \ No newline at end of file
diff --git a/vendor/github.com/deckarep/golang-set/v2/README.md b/vendor/github.com/deckarep/golang-set/v2/README.md
new file mode 100644
index 0000000..bb691b1
--- /dev/null
+++ b/vendor/github.com/deckarep/golang-set/v2/README.md
@@ -0,0 +1,190 @@
+![example workflow](https://github.com/deckarep/golang-set/actions/workflows/ci.yml/badge.svg)
+[![Go Report Card](https://goreportcard.com/badge/github.com/deckarep/golang-set/v2)](https://goreportcard.com/report/github.com/deckarep/golang-set/v2)
+[![GoDoc](https://godoc.org/github.com/deckarep/golang-set/v2?status.svg)](http://godoc.org/github.com/deckarep/golang-set/v2)
+
+# golang-set
+
+The missing `generic` set collection for the Go language. Until Go has sets built-in...use this.
+
+## Psst
+* Hi there, 👋! Do you use or have interest in the [Zig programming language](https://ziglang.org/) created by Andrew Kelley? If so, the golang-set project has a new sibling project: [ziglang-set](https://github.com/deckarep/ziglang-set)! Come check it out!
+
+## Update 12/3/2024
+* Packaged version: `2.7.0` fixes a long-standing bug with *JSON Unmarshaling*. A large refactor in the interest of performance
+introduced this bug and there was no way around it but to revert the code back to how it was previously. The performance
+difference was likely negligible to begin with. JSON Marshaling and Unmarshaling is now properly supported again without
+needing to do workarounds.
+
+## Update 3/5/2023
+* Packaged version: `2.2.0` release includes a refactor to minimize pointer indirection, better method documentation standards and a few constructor convenience methods to increase ergonomics when appending items `Append` or creating a new set from an exist `Map`.
+* supports `new generic` syntax
+* Go `1.18.0` or higher
+* Workflow tested on Go `1.20`
+
+![With Generics](new_improved.jpeg)
+
+Coming from Python one of the things I miss is the superbly wonderful set collection. This is my attempt to mimic the primary features of the set collection from Python.
+You can of course argue that there is no need for a set in Go, otherwise the creators would have added one to the standard library. To those I say simply ignore this repository and carry-on and to the rest that find this useful please contribute in helping me make it better by contributing with suggestions or PRs.
+
+## Install
+
+Use `go get` to install this package.
+
+```shell
+go get github.com/deckarep/golang-set/v2
+```
+
+## Features
+
+* *NEW* [Generics](https://go.dev/doc/tutorial/generics) based implementation (requires [Go 1.18](https://go.dev/blog/go1.18beta1) or higher)
+* One common *interface* to both implementations
+ * a **non threadsafe** implementation favoring *performance*
+ * a **threadsafe** implementation favoring *concurrent* use
+* Feature complete set implementation modeled after [Python's set implementation](https://docs.python.org/3/library/stdtypes.html#set).
+* Exhaustive unit-test and benchmark suite
+
+## Trusted by
+
+This package is trusted by many companies and thousands of open-source packages. Here are just a few sample users of this package.
+
+* Notable projects/companies using this package
+ * Ethereum
+ * Docker
+ * 1Password
+ * Hashicorp
+
+## Star History
+
+[![Star History Chart](https://api.star-history.com/svg?repos=deckarep/golang-set&type=Date)](https://star-history.com/#deckarep/golang-set&Date)
+
+
+## Usage
+
+The code below demonstrates how a Set collection can better manage data and actually minimize boilerplate and needless loops in code. This package now fully supports *generic* syntax so you are now able to instantiate a collection for any [comparable](https://flaviocopes.com/golang-comparing-values/) type object.
+
+What is considered comparable in Go?
+* `Booleans`, `integers`, `strings`, `floats` or basically primitive types.
+* `Pointers`
+* `Arrays`
+* `Structs` if *all of their fields* are also comparable independently
+
+Using this library is as simple as creating either a threadsafe or non-threadsafe set and providing a `comparable` type for instantiation of the collection.
+
+```go
+// Syntax example, doesn't compile.
+mySet := mapset.NewSet[T]() // where T is some concrete comparable type.
+
+// Therefore this code creates an int set
+mySet := mapset.NewSet[int]()
+
+// Or perhaps you want a string set
+mySet := mapset.NewSet[string]()
+
+type myStruct struct {
+ name string
+ age uint8
+}
+
+// Alternatively a set of structs
+mySet := mapset.NewSet[myStruct]()
+
+// Lastly a set that can hold anything using the any or empty interface keyword: interface{}. This is effectively removes type safety.
+mySet := mapset.NewSet[any]()
+```
+
+## Comprehensive Example
+
+```go
+package main
+
+import (
+ "fmt"
+ mapset "github.com/deckarep/golang-set/v2"
+)
+
+func main() {
+ // Create a string-based set of required classes.
+ required := mapset.NewSet[string]()
+ required.Add("cooking")
+ required.Add("english")
+ required.Add("math")
+ required.Add("biology")
+
+ // Create a string-based set of science classes.
+ sciences := mapset.NewSet[string]()
+ sciences.Add("biology")
+ sciences.Add("chemistry")
+
+ // Create a string-based set of electives.
+ electives := mapset.NewSet[string]()
+ electives.Add("welding")
+ electives.Add("music")
+ electives.Add("automotive")
+
+ // Create a string-based set of bonus programming classes.
+ bonus := mapset.NewSet[string]()
+ bonus.Add("beginner go")
+ bonus.Add("python for dummies")
+}
+```
+
+Create a set of all unique classes.
+Sets will *automatically* deduplicate the same data.
+
+```go
+ all := required
+ .Union(sciences)
+ .Union(electives)
+ .Union(bonus)
+
+ fmt.Println(all)
+```
+
+Output:
+```sh
+Set{cooking, english, math, chemistry, welding, biology, music, automotive, beginner go, python for dummies}
+```
+
+Is cooking considered a science class?
+```go
+result := sciences.Contains("cooking")
+fmt.Println(result)
+```
+
+Output:
+```false
+false
+```
+
+Show me all classes that are not science classes, since I don't enjoy science.
+```go
+notScience := all.Difference(sciences)
+fmt.Println(notScience)
+```
+
+```sh
+Set{ music, automotive, beginner go, python for dummies, cooking, english, math, welding }
+```
+
+Which science classes are also required classes?
+```go
+reqScience := sciences.Intersect(required)
+```
+
+Output:
+```sh
+Set{biology}
+```
+
+How many bonus classes do you offer?
+```go
+fmt.Println(bonus.Cardinality())
+```
+Output:
+```sh
+2
+```
+
+Thanks for visiting!
+
+-deckarep
diff --git a/vendor/github.com/deckarep/golang-set/v2/iterator.go b/vendor/github.com/deckarep/golang-set/v2/iterator.go
new file mode 100644
index 0000000..fc14e70
--- /dev/null
+++ b/vendor/github.com/deckarep/golang-set/v2/iterator.go
@@ -0,0 +1,58 @@
+/*
+Open Source Initiative OSI - The MIT License (MIT):Licensing
+
+The MIT License (MIT)
+Copyright (c) 2013 - 2022 Ralph Caraveo (deckarep@gmail.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+package mapset
+
+// Iterator defines an iterator over a Set, its C channel can be used to range over the Set's
+// elements.
+type Iterator[T comparable] struct {
+ C <-chan T
+ stop chan struct{}
+}
+
+// Stop stops the Iterator, no further elements will be received on C, C will be closed.
+func (i *Iterator[T]) Stop() {
+ // Allows for Stop() to be called multiple times
+ // (close() panics when called on already closed channel)
+ defer func() {
+ recover()
+ }()
+
+ close(i.stop)
+
+ // Exhaust any remaining elements.
+ for range i.C {
+ }
+}
+
+// newIterator returns a new Iterator instance together with its item and stop channels.
+func newIterator[T comparable]() (*Iterator[T], chan<- T, <-chan struct{}) {
+ itemChan := make(chan T)
+ stopChan := make(chan struct{})
+ return &Iterator[T]{
+ C: itemChan,
+ stop: stopChan,
+ }, itemChan, stopChan
+}
diff --git a/vendor/github.com/deckarep/golang-set/v2/new_improved.jpeg b/vendor/github.com/deckarep/golang-set/v2/new_improved.jpeg
new file mode 100644
index 0000000..429752a
--- /dev/null
+++ b/vendor/github.com/deckarep/golang-set/v2/new_improved.jpeg
Binary files differ
diff --git a/vendor/github.com/deckarep/golang-set/v2/set.go b/vendor/github.com/deckarep/golang-set/v2/set.go
new file mode 100644
index 0000000..292089d
--- /dev/null
+++ b/vendor/github.com/deckarep/golang-set/v2/set.go
@@ -0,0 +1,255 @@
+/*
+Open Source Initiative OSI - The MIT License (MIT):Licensing
+
+The MIT License (MIT)
+Copyright (c) 2013 - 2022 Ralph Caraveo (deckarep@gmail.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+// Package mapset implements a simple and set collection.
+// Items stored within it are unordered and unique. It supports
+// typical set operations: membership testing, intersection, union,
+// difference, symmetric difference and cloning.
+//
+// Package mapset provides two implementations of the Set
+// interface. The default implementation is safe for concurrent
+// access, but a non-thread-safe implementation is also provided for
+// programs that can benefit from the slight speed improvement and
+// that can enforce mutual exclusion through other means.
+package mapset
+
+// Set is the primary interface provided by the mapset package. It
+// represents an unordered set of data and a large number of
+// operations that can be applied to that set.
+type Set[T comparable] interface {
+ // Add adds an element to the set. Returns whether
+ // the item was added.
+ Add(val T) bool
+
+ // Append multiple elements to the set. Returns
+ // the number of elements added.
+ Append(val ...T) int
+
+ // Cardinality returns the number of elements in the set.
+ Cardinality() int
+
+ // Clear removes all elements from the set, leaving
+ // the empty set.
+ Clear()
+
+ // Clone returns a clone of the set using the same
+ // implementation, duplicating all keys.
+ Clone() Set[T]
+
+ // Contains returns whether the given items
+ // are all in the set.
+ Contains(val ...T) bool
+
+ // ContainsOne returns whether the given item
+ // is in the set.
+ //
+ // Contains may cause the argument to escape to the heap.
+ // See: https://github.com/deckarep/golang-set/issues/118
+ ContainsOne(val T) bool
+
+ // ContainsAny returns whether at least one of the
+ // given items are in the set.
+ ContainsAny(val ...T) bool
+
+ // Difference returns the difference between this set
+ // and other. The returned set will contain
+ // all elements of this set that are not also
+ // elements of other.
+ //
+ // Note that the argument to Difference
+ // must be of the same type as the receiver
+ // of the method. Otherwise, Difference will
+ // panic.
+ Difference(other Set[T]) Set[T]
+
+ // Equal determines if two sets are equal to each
+ // other. If they have the same cardinality
+ // and contain the same elements, they are
+ // considered equal. The order in which
+ // the elements were added is irrelevant.
+ //
+ // Note that the argument to Equal must be
+ // of the same type as the receiver of the
+ // method. Otherwise, Equal will panic.
+ Equal(other Set[T]) bool
+
+ // Intersect returns a new set containing only the elements
+ // that exist only in both sets.
+ //
+ // Note that the argument to Intersect
+ // must be of the same type as the receiver
+ // of the method. Otherwise, Intersect will
+ // panic.
+ Intersect(other Set[T]) Set[T]
+
+ // IsEmpty determines if there are elements in the set.
+ IsEmpty() bool
+
+ // IsProperSubset determines if every element in this set is in
+ // the other set but the two sets are not equal.
+ //
+ // Note that the argument to IsProperSubset
+ // must be of the same type as the receiver
+ // of the method. Otherwise, IsProperSubset
+ // will panic.
+ IsProperSubset(other Set[T]) bool
+
+ // IsProperSuperset determines if every element in the other set
+ // is in this set but the two sets are not
+ // equal.
+ //
+ // Note that the argument to IsSuperset
+ // must be of the same type as the receiver
+ // of the method. Otherwise, IsSuperset will
+ // panic.
+ IsProperSuperset(other Set[T]) bool
+
+ // IsSubset determines if every element in this set is in
+ // the other set.
+ //
+ // Note that the argument to IsSubset
+ // must be of the same type as the receiver
+ // of the method. Otherwise, IsSubset will
+ // panic.
+ IsSubset(other Set[T]) bool
+
+ // IsSuperset determines if every element in the other set
+ // is in this set.
+ //
+ // Note that the argument to IsSuperset
+ // must be of the same type as the receiver
+ // of the method. Otherwise, IsSuperset will
+ // panic.
+ IsSuperset(other Set[T]) bool
+
+ // Each iterates over elements and executes the passed func against each element.
+ // If passed func returns true, stop iteration at the time.
+ Each(func(T) bool)
+
+ // Iter returns a channel of elements that you can
+ // range over.
+ Iter() <-chan T
+
+ // Iterator returns an Iterator object that you can
+ // use to range over the set.
+ Iterator() *Iterator[T]
+
+ // Remove removes a single element from the set.
+ Remove(i T)
+
+ // RemoveAll removes multiple elements from the set.
+ RemoveAll(i ...T)
+
+ // String provides a convenient string representation
+ // of the current state of the set.
+ String() string
+
+ // SymmetricDifference returns a new set with all elements which are
+ // in either this set or the other set but not in both.
+ //
+ // Note that the argument to SymmetricDifference
+ // must be of the same type as the receiver
+ // of the method. Otherwise, SymmetricDifference
+ // will panic.
+ SymmetricDifference(other Set[T]) Set[T]
+
+ // Union returns a new set with all elements in both sets.
+ //
+ // Note that the argument to Union must be of the
+ // same type as the receiver of the method.
+ // Otherwise, Union will panic.
+ Union(other Set[T]) Set[T]
+
+ // Pop removes and returns an arbitrary item from the set.
+ Pop() (T, bool)
+
+ // ToSlice returns the members of the set as a slice.
+ ToSlice() []T
+
+ // MarshalJSON will marshal the set into a JSON-based representation.
+ MarshalJSON() ([]byte, error)
+
+ // UnmarshalJSON will unmarshal a JSON-based byte slice into a full Set datastructure.
+ // For this to work, set subtypes must implemented the Marshal/Unmarshal interface.
+ UnmarshalJSON(b []byte) error
+}
+
+// NewSet creates and returns a new set with the given elements.
+// Operations on the resulting set are thread-safe.
+func NewSet[T comparable](vals ...T) Set[T] {
+ s := newThreadSafeSetWithSize[T](len(vals))
+ for _, item := range vals {
+ s.Add(item)
+ }
+ return s
+}
+
+// NewSetWithSize creates and returns a reference to an empty set with a specified
+// capacity. Operations on the resulting set are thread-safe.
+func NewSetWithSize[T comparable](cardinality int) Set[T] {
+ s := newThreadSafeSetWithSize[T](cardinality)
+ return s
+}
+
+// NewThreadUnsafeSet creates and returns a new set with the given elements.
+// Operations on the resulting set are not thread-safe.
+func NewThreadUnsafeSet[T comparable](vals ...T) Set[T] {
+ s := newThreadUnsafeSetWithSize[T](len(vals))
+ for _, item := range vals {
+ s.Add(item)
+ }
+ return s
+}
+
+// NewThreadUnsafeSetWithSize creates and returns a reference to an empty set with
+// a specified capacity. Operations on the resulting set are not thread-safe.
+func NewThreadUnsafeSetWithSize[T comparable](cardinality int) Set[T] {
+ s := newThreadUnsafeSetWithSize[T](cardinality)
+ return s
+}
+
+// NewSetFromMapKeys creates and returns a new set with the given keys of the map.
+// Operations on the resulting set are thread-safe.
+func NewSetFromMapKeys[T comparable, V any](val map[T]V) Set[T] {
+ s := NewSetWithSize[T](len(val))
+
+ for k := range val {
+ s.Add(k)
+ }
+
+ return s
+}
+
+// NewThreadUnsafeSetFromMapKeys creates and returns a new set with the given keys of the map.
+// Operations on the resulting set are not thread-safe.
+func NewThreadUnsafeSetFromMapKeys[T comparable, V any](val map[T]V) Set[T] {
+ s := NewThreadUnsafeSetWithSize[T](len(val))
+
+ for k := range val {
+ s.Add(k)
+ }
+
+ return s
+}
diff --git a/vendor/github.com/deckarep/golang-set/v2/sorted.go b/vendor/github.com/deckarep/golang-set/v2/sorted.go
new file mode 100644
index 0000000..8ee2e70
--- /dev/null
+++ b/vendor/github.com/deckarep/golang-set/v2/sorted.go
@@ -0,0 +1,42 @@
+//go:build go1.21
+// +build go1.21
+
+/*
+Open Source Initiative OSI - The MIT License (MIT):Licensing
+
+The MIT License (MIT)
+Copyright (c) 2013 - 2023 Ralph Caraveo (deckarep@gmail.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+package mapset
+
+import (
+ "cmp"
+ "slices"
+)
+
+// Sorted returns a sorted slice of a set of any ordered type in ascending order.
+// When sorting floating-point numbers, NaNs are ordered before other values.
+func Sorted[E cmp.Ordered](set Set[E]) []E {
+ s := set.ToSlice()
+ slices.Sort(s)
+ return s
+}
diff --git a/vendor/github.com/deckarep/golang-set/v2/threadsafe.go b/vendor/github.com/deckarep/golang-set/v2/threadsafe.go
new file mode 100644
index 0000000..93f20c8
--- /dev/null
+++ b/vendor/github.com/deckarep/golang-set/v2/threadsafe.go
@@ -0,0 +1,299 @@
+/*
+Open Source Initiative OSI - The MIT License (MIT):Licensing
+
+The MIT License (MIT)
+Copyright (c) 2013 - 2022 Ralph Caraveo (deckarep@gmail.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+package mapset
+
+import "sync"
+
+type threadSafeSet[T comparable] struct {
+ sync.RWMutex
+ uss *threadUnsafeSet[T]
+}
+
+func newThreadSafeSet[T comparable]() *threadSafeSet[T] {
+ return &threadSafeSet[T]{
+ uss: newThreadUnsafeSet[T](),
+ }
+}
+
+func newThreadSafeSetWithSize[T comparable](cardinality int) *threadSafeSet[T] {
+ return &threadSafeSet[T]{
+ uss: newThreadUnsafeSetWithSize[T](cardinality),
+ }
+}
+
+func (t *threadSafeSet[T]) Add(v T) bool {
+ t.Lock()
+ ret := t.uss.Add(v)
+ t.Unlock()
+ return ret
+}
+
+func (t *threadSafeSet[T]) Append(v ...T) int {
+ t.Lock()
+ ret := t.uss.Append(v...)
+ t.Unlock()
+ return ret
+}
+
+func (t *threadSafeSet[T]) Contains(v ...T) bool {
+ t.RLock()
+ ret := t.uss.Contains(v...)
+ t.RUnlock()
+
+ return ret
+}
+
+func (t *threadSafeSet[T]) ContainsOne(v T) bool {
+ t.RLock()
+ ret := t.uss.ContainsOne(v)
+ t.RUnlock()
+
+ return ret
+}
+
+func (t *threadSafeSet[T]) ContainsAny(v ...T) bool {
+ t.RLock()
+ ret := t.uss.ContainsAny(v...)
+ t.RUnlock()
+
+ return ret
+}
+
+func (t *threadSafeSet[T]) IsEmpty() bool {
+ return t.Cardinality() == 0
+}
+
+func (t *threadSafeSet[T]) IsSubset(other Set[T]) bool {
+ o := other.(*threadSafeSet[T])
+
+ t.RLock()
+ o.RLock()
+
+ ret := t.uss.IsSubset(o.uss)
+ t.RUnlock()
+ o.RUnlock()
+ return ret
+}
+
+func (t *threadSafeSet[T]) IsProperSubset(other Set[T]) bool {
+ o := other.(*threadSafeSet[T])
+
+ t.RLock()
+ defer t.RUnlock()
+ o.RLock()
+ defer o.RUnlock()
+
+ return t.uss.IsProperSubset(o.uss)
+}
+
+func (t *threadSafeSet[T]) IsSuperset(other Set[T]) bool {
+ return other.IsSubset(t)
+}
+
+func (t *threadSafeSet[T]) IsProperSuperset(other Set[T]) bool {
+ return other.IsProperSubset(t)
+}
+
+func (t *threadSafeSet[T]) Union(other Set[T]) Set[T] {
+ o := other.(*threadSafeSet[T])
+
+ t.RLock()
+ o.RLock()
+
+ unsafeUnion := t.uss.Union(o.uss).(*threadUnsafeSet[T])
+ ret := &threadSafeSet[T]{uss: unsafeUnion}
+ t.RUnlock()
+ o.RUnlock()
+ return ret
+}
+
+func (t *threadSafeSet[T]) Intersect(other Set[T]) Set[T] {
+ o := other.(*threadSafeSet[T])
+
+ t.RLock()
+ o.RLock()
+
+ unsafeIntersection := t.uss.Intersect(o.uss).(*threadUnsafeSet[T])
+ ret := &threadSafeSet[T]{uss: unsafeIntersection}
+ t.RUnlock()
+ o.RUnlock()
+ return ret
+}
+
+func (t *threadSafeSet[T]) Difference(other Set[T]) Set[T] {
+ o := other.(*threadSafeSet[T])
+
+ t.RLock()
+ o.RLock()
+
+ unsafeDifference := t.uss.Difference(o.uss).(*threadUnsafeSet[T])
+ ret := &threadSafeSet[T]{uss: unsafeDifference}
+ t.RUnlock()
+ o.RUnlock()
+ return ret
+}
+
+func (t *threadSafeSet[T]) SymmetricDifference(other Set[T]) Set[T] {
+ o := other.(*threadSafeSet[T])
+
+ t.RLock()
+ o.RLock()
+
+ unsafeDifference := t.uss.SymmetricDifference(o.uss).(*threadUnsafeSet[T])
+ ret := &threadSafeSet[T]{uss: unsafeDifference}
+ t.RUnlock()
+ o.RUnlock()
+ return ret
+}
+
+func (t *threadSafeSet[T]) Clear() {
+ t.Lock()
+ t.uss.Clear()
+ t.Unlock()
+}
+
+func (t *threadSafeSet[T]) Remove(v T) {
+ t.Lock()
+ delete(*t.uss, v)
+ t.Unlock()
+}
+
+func (t *threadSafeSet[T]) RemoveAll(i ...T) {
+ t.Lock()
+ t.uss.RemoveAll(i...)
+ t.Unlock()
+}
+
+func (t *threadSafeSet[T]) Cardinality() int {
+ t.RLock()
+ defer t.RUnlock()
+ return len(*t.uss)
+}
+
+func (t *threadSafeSet[T]) Each(cb func(T) bool) {
+ t.RLock()
+ for elem := range *t.uss {
+ if cb(elem) {
+ break
+ }
+ }
+ t.RUnlock()
+}
+
+func (t *threadSafeSet[T]) Iter() <-chan T {
+ ch := make(chan T)
+ go func() {
+ t.RLock()
+
+ for elem := range *t.uss {
+ ch <- elem
+ }
+ close(ch)
+ t.RUnlock()
+ }()
+
+ return ch
+}
+
+func (t *threadSafeSet[T]) Iterator() *Iterator[T] {
+ iterator, ch, stopCh := newIterator[T]()
+
+ go func() {
+ t.RLock()
+ L:
+ for elem := range *t.uss {
+ select {
+ case <-stopCh:
+ break L
+ case ch <- elem:
+ }
+ }
+ close(ch)
+ t.RUnlock()
+ }()
+
+ return iterator
+}
+
+func (t *threadSafeSet[T]) Equal(other Set[T]) bool {
+ o := other.(*threadSafeSet[T])
+
+ t.RLock()
+ o.RLock()
+
+ ret := t.uss.Equal(o.uss)
+ t.RUnlock()
+ o.RUnlock()
+ return ret
+}
+
+func (t *threadSafeSet[T]) Clone() Set[T] {
+ t.RLock()
+
+ unsafeClone := t.uss.Clone().(*threadUnsafeSet[T])
+ ret := &threadSafeSet[T]{uss: unsafeClone}
+ t.RUnlock()
+ return ret
+}
+
+func (t *threadSafeSet[T]) String() string {
+ t.RLock()
+ ret := t.uss.String()
+ t.RUnlock()
+ return ret
+}
+
+func (t *threadSafeSet[T]) Pop() (T, bool) {
+ t.Lock()
+ defer t.Unlock()
+ return t.uss.Pop()
+}
+
+func (t *threadSafeSet[T]) ToSlice() []T {
+ keys := make([]T, 0, t.Cardinality())
+ t.RLock()
+ for elem := range *t.uss {
+ keys = append(keys, elem)
+ }
+ t.RUnlock()
+ return keys
+}
+
+func (t *threadSafeSet[T]) MarshalJSON() ([]byte, error) {
+ t.RLock()
+ b, err := t.uss.MarshalJSON()
+ t.RUnlock()
+
+ return b, err
+}
+
+func (t *threadSafeSet[T]) UnmarshalJSON(p []byte) error {
+ t.RLock()
+ err := t.uss.UnmarshalJSON(p)
+ t.RUnlock()
+
+ return err
+}
diff --git a/vendor/github.com/deckarep/golang-set/v2/threadunsafe.go b/vendor/github.com/deckarep/golang-set/v2/threadunsafe.go
new file mode 100644
index 0000000..7e3243b
--- /dev/null
+++ b/vendor/github.com/deckarep/golang-set/v2/threadunsafe.go
@@ -0,0 +1,332 @@
+/*
+Open Source Initiative OSI - The MIT License (MIT):Licensing
+
+The MIT License (MIT)
+Copyright (c) 2013 - 2022 Ralph Caraveo (deckarep@gmail.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+package mapset
+
+import (
+ "encoding/json"
+ "fmt"
+ "strings"
+)
+
+type threadUnsafeSet[T comparable] map[T]struct{}
+
+// Assert concrete type:threadUnsafeSet adheres to Set interface.
+var _ Set[string] = (*threadUnsafeSet[string])(nil)
+
+func newThreadUnsafeSet[T comparable]() *threadUnsafeSet[T] {
+ t := make(threadUnsafeSet[T])
+ return &t
+}
+
+func newThreadUnsafeSetWithSize[T comparable](cardinality int) *threadUnsafeSet[T] {
+ t := make(threadUnsafeSet[T], cardinality)
+ return &t
+}
+
+func (s threadUnsafeSet[T]) Add(v T) bool {
+ prevLen := len(s)
+ s[v] = struct{}{}
+ return prevLen != len(s)
+}
+
+func (s *threadUnsafeSet[T]) Append(v ...T) int {
+ prevLen := len(*s)
+ for _, val := range v {
+ (*s)[val] = struct{}{}
+ }
+ return len(*s) - prevLen
+}
+
+// private version of Add which doesn't return a value
+func (s *threadUnsafeSet[T]) add(v T) {
+ (*s)[v] = struct{}{}
+}
+
+func (s *threadUnsafeSet[T]) Cardinality() int {
+ return len(*s)
+}
+
+func (s *threadUnsafeSet[T]) Clear() {
+ // Constructions like this are optimised by compiler, and replaced by
+ // mapclear() function, defined in
+ // https://github.com/golang/go/blob/29bbca5c2c1ad41b2a9747890d183b6dd3a4ace4/src/runtime/map.go#L993)
+ for key := range *s {
+ delete(*s, key)
+ }
+}
+
+func (s *threadUnsafeSet[T]) Clone() Set[T] {
+ clonedSet := newThreadUnsafeSetWithSize[T](s.Cardinality())
+ for elem := range *s {
+ clonedSet.add(elem)
+ }
+ return clonedSet
+}
+
+func (s *threadUnsafeSet[T]) Contains(v ...T) bool {
+ for _, val := range v {
+ if _, ok := (*s)[val]; !ok {
+ return false
+ }
+ }
+ return true
+}
+
+func (s *threadUnsafeSet[T]) ContainsOne(v T) bool {
+ _, ok := (*s)[v]
+ return ok
+}
+
+func (s *threadUnsafeSet[T]) ContainsAny(v ...T) bool {
+ for _, val := range v {
+ if _, ok := (*s)[val]; ok {
+ return true
+ }
+ }
+ return false
+}
+
+// private version of Contains for a single element v
+func (s *threadUnsafeSet[T]) contains(v T) (ok bool) {
+ _, ok = (*s)[v]
+ return ok
+}
+
+func (s *threadUnsafeSet[T]) Difference(other Set[T]) Set[T] {
+ o := other.(*threadUnsafeSet[T])
+
+ diff := newThreadUnsafeSet[T]()
+ for elem := range *s {
+ if !o.contains(elem) {
+ diff.add(elem)
+ }
+ }
+ return diff
+}
+
+func (s *threadUnsafeSet[T]) Each(cb func(T) bool) {
+ for elem := range *s {
+ if cb(elem) {
+ break
+ }
+ }
+}
+
+func (s *threadUnsafeSet[T]) Equal(other Set[T]) bool {
+ o := other.(*threadUnsafeSet[T])
+
+ if s.Cardinality() != other.Cardinality() {
+ return false
+ }
+ for elem := range *s {
+ if !o.contains(elem) {
+ return false
+ }
+ }
+ return true
+}
+
+func (s *threadUnsafeSet[T]) Intersect(other Set[T]) Set[T] {
+ o := other.(*threadUnsafeSet[T])
+
+ intersection := newThreadUnsafeSet[T]()
+ // loop over smaller set
+ if s.Cardinality() < other.Cardinality() {
+ for elem := range *s {
+ if o.contains(elem) {
+ intersection.add(elem)
+ }
+ }
+ } else {
+ for elem := range *o {
+ if s.contains(elem) {
+ intersection.add(elem)
+ }
+ }
+ }
+ return intersection
+}
+
+func (s *threadUnsafeSet[T]) IsEmpty() bool {
+ return s.Cardinality() == 0
+}
+
+func (s *threadUnsafeSet[T]) IsProperSubset(other Set[T]) bool {
+ return s.Cardinality() < other.Cardinality() && s.IsSubset(other)
+}
+
+func (s *threadUnsafeSet[T]) IsProperSuperset(other Set[T]) bool {
+ return s.Cardinality() > other.Cardinality() && s.IsSuperset(other)
+}
+
+func (s *threadUnsafeSet[T]) IsSubset(other Set[T]) bool {
+ o := other.(*threadUnsafeSet[T])
+ if s.Cardinality() > other.Cardinality() {
+ return false
+ }
+ for elem := range *s {
+ if !o.contains(elem) {
+ return false
+ }
+ }
+ return true
+}
+
+func (s *threadUnsafeSet[T]) IsSuperset(other Set[T]) bool {
+ return other.IsSubset(s)
+}
+
+func (s *threadUnsafeSet[T]) Iter() <-chan T {
+ ch := make(chan T)
+ go func() {
+ for elem := range *s {
+ ch <- elem
+ }
+ close(ch)
+ }()
+
+ return ch
+}
+
+func (s *threadUnsafeSet[T]) Iterator() *Iterator[T] {
+ iterator, ch, stopCh := newIterator[T]()
+
+ go func() {
+ L:
+ for elem := range *s {
+ select {
+ case <-stopCh:
+ break L
+ case ch <- elem:
+ }
+ }
+ close(ch)
+ }()
+
+ return iterator
+}
+
+// Pop returns a popped item in case set is not empty, or nil-value of T
+// if set is already empty
+func (s *threadUnsafeSet[T]) Pop() (v T, ok bool) {
+ for item := range *s {
+ delete(*s, item)
+ return item, true
+ }
+ return v, false
+}
+
+func (s threadUnsafeSet[T]) Remove(v T) {
+ delete(s, v)
+}
+
+func (s threadUnsafeSet[T]) RemoveAll(i ...T) {
+ for _, elem := range i {
+ delete(s, elem)
+ }
+}
+
+func (s threadUnsafeSet[T]) String() string {
+ items := make([]string, 0, len(s))
+
+ for elem := range s {
+ items = append(items, fmt.Sprintf("%v", elem))
+ }
+ return fmt.Sprintf("Set{%s}", strings.Join(items, ", "))
+}
+
+func (s *threadUnsafeSet[T]) SymmetricDifference(other Set[T]) Set[T] {
+ o := other.(*threadUnsafeSet[T])
+
+ sd := newThreadUnsafeSet[T]()
+ for elem := range *s {
+ if !o.contains(elem) {
+ sd.add(elem)
+ }
+ }
+ for elem := range *o {
+ if !s.contains(elem) {
+ sd.add(elem)
+ }
+ }
+ return sd
+}
+
+func (s threadUnsafeSet[T]) ToSlice() []T {
+ keys := make([]T, 0, s.Cardinality())
+ for elem := range s {
+ keys = append(keys, elem)
+ }
+
+ return keys
+}
+
+func (s threadUnsafeSet[T]) Union(other Set[T]) Set[T] {
+ o := other.(*threadUnsafeSet[T])
+
+ n := s.Cardinality()
+ if o.Cardinality() > n {
+ n = o.Cardinality()
+ }
+ unionedSet := make(threadUnsafeSet[T], n)
+
+ for elem := range s {
+ unionedSet.add(elem)
+ }
+ for elem := range *o {
+ unionedSet.add(elem)
+ }
+ return &unionedSet
+}
+
+// MarshalJSON creates a JSON array from the set, it marshals all elements
+func (s threadUnsafeSet[T]) MarshalJSON() ([]byte, error) {
+ items := make([]string, 0, s.Cardinality())
+
+ for elem := range s {
+ b, err := json.Marshal(elem)
+ if err != nil {
+ return nil, err
+ }
+
+ items = append(items, string(b))
+ }
+
+ return []byte(fmt.Sprintf("[%s]", strings.Join(items, ","))), nil
+}
+
+// UnmarshalJSON recreates a set from a JSON array, it only decodes
+// primitive types. Numbers are decoded as json.Number.
+func (s *threadUnsafeSet[T]) UnmarshalJSON(b []byte) error {
+ var i []T
+ err := json.Unmarshal(b, &i)
+ if err != nil {
+ return err
+ }
+ s.Append(i...)
+
+ return nil
+}
diff --git a/vendor/github.com/go-stack/stack/LICENSE.md b/vendor/github.com/go-stack/stack/LICENSE.md
new file mode 100644
index 0000000..2abf98e
--- /dev/null
+++ b/vendor/github.com/go-stack/stack/LICENSE.md
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 Chris Hines
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/vendor/github.com/go-stack/stack/README.md b/vendor/github.com/go-stack/stack/README.md
new file mode 100644
index 0000000..f11cccc
--- /dev/null
+++ b/vendor/github.com/go-stack/stack/README.md
@@ -0,0 +1,38 @@
+[![GoDoc](https://godoc.org/github.com/go-stack/stack?status.svg)](https://godoc.org/github.com/go-stack/stack)
+[![Go Report Card](https://goreportcard.com/badge/go-stack/stack)](https://goreportcard.com/report/go-stack/stack)
+[![TravisCI](https://travis-ci.org/go-stack/stack.svg?branch=master)](https://travis-ci.org/go-stack/stack)
+[![Coverage Status](https://coveralls.io/repos/github/go-stack/stack/badge.svg?branch=master)](https://coveralls.io/github/go-stack/stack?branch=master)
+
+# stack
+
+Package stack implements utilities to capture, manipulate, and format call
+stacks. It provides a simpler API than package runtime.
+
+The implementation takes care of the minutia and special cases of interpreting
+the program counter (pc) values returned by runtime.Callers.
+
+## Versioning
+
+Package stack publishes releases via [semver](http://semver.org/) compatible Git
+tags prefixed with a single 'v'. The master branch always contains the latest
+release. The develop branch contains unreleased commits.
+
+## Formatting
+
+Package stack's types implement fmt.Formatter, which provides a simple and
+flexible way to declaratively configure formatting when used with logging or
+error tracking packages.
+
+```go
+func DoTheThing() {
+ c := stack.Caller(0)
+ log.Print(c) // "source.go:10"
+ log.Printf("%+v", c) // "pkg/path/source.go:10"
+ log.Printf("%n", c) // "DoTheThing"
+
+ s := stack.Trace().TrimRuntime()
+ log.Print(s) // "[source.go:15 caller.go:42 main.go:14]"
+}
+```
+
+See the docs for all of the supported formatting options.
diff --git a/vendor/github.com/go-stack/stack/stack.go b/vendor/github.com/go-stack/stack/stack.go
new file mode 100644
index 0000000..ac3b93b
--- /dev/null
+++ b/vendor/github.com/go-stack/stack/stack.go
@@ -0,0 +1,400 @@
+// +build go1.7
+
+// Package stack implements utilities to capture, manipulate, and format call
+// stacks. It provides a simpler API than package runtime.
+//
+// The implementation takes care of the minutia and special cases of
+// interpreting the program counter (pc) values returned by runtime.Callers.
+//
+// Package stack's types implement fmt.Formatter, which provides a simple and
+// flexible way to declaratively configure formatting when used with logging
+// or error tracking packages.
+package stack
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "io"
+ "runtime"
+ "strconv"
+ "strings"
+)
+
+// Call records a single function invocation from a goroutine stack.
+type Call struct {
+ frame runtime.Frame
+}
+
+// Caller returns a Call from the stack of the current goroutine. The argument
+// skip is the number of stack frames to ascend, with 0 identifying the
+// calling function.
+func Caller(skip int) Call {
+ // As of Go 1.9 we need room for up to three PC entries.
+ //
+ // 0. An entry for the stack frame prior to the target to check for
+ // special handling needed if that prior entry is runtime.sigpanic.
+ // 1. A possible second entry to hold metadata about skipped inlined
+ // functions. If inline functions were not skipped the target frame
+ // PC will be here.
+ // 2. A third entry for the target frame PC when the second entry
+ // is used for skipped inline functions.
+ var pcs [3]uintptr
+ n := runtime.Callers(skip+1, pcs[:])
+ frames := runtime.CallersFrames(pcs[:n])
+ frame, _ := frames.Next()
+ frame, _ = frames.Next()
+
+ return Call{
+ frame: frame,
+ }
+}
+
+// String implements fmt.Stinger. It is equivalent to fmt.Sprintf("%v", c).
+func (c Call) String() string {
+ return fmt.Sprint(c)
+}
+
+// MarshalText implements encoding.TextMarshaler. It formats the Call the same
+// as fmt.Sprintf("%v", c).
+func (c Call) MarshalText() ([]byte, error) {
+ if c.frame == (runtime.Frame{}) {
+ return nil, ErrNoFunc
+ }
+
+ buf := bytes.Buffer{}
+ fmt.Fprint(&buf, c)
+ return buf.Bytes(), nil
+}
+
+// ErrNoFunc means that the Call has a nil *runtime.Func. The most likely
+// cause is a Call with the zero value.
+var ErrNoFunc = errors.New("no call stack information")
+
+// Format implements fmt.Formatter with support for the following verbs.
+//
+// %s source file
+// %d line number
+// %n function name
+// %k last segment of the package path
+// %v equivalent to %s:%d
+//
+// It accepts the '+' and '#' flags for most of the verbs as follows.
+//
+// %+s path of source file relative to the compile time GOPATH,
+// or the module path joined to the path of source file relative
+// to module root
+// %#s full path of source file
+// %+n import path qualified function name
+// %+k full package path
+// %+v equivalent to %+s:%d
+// %#v equivalent to %#s:%d
+func (c Call) Format(s fmt.State, verb rune) {
+ if c.frame == (runtime.Frame{}) {
+ fmt.Fprintf(s, "%%!%c(NOFUNC)", verb)
+ return
+ }
+
+ switch verb {
+ case 's', 'v':
+ file := c.frame.File
+ switch {
+ case s.Flag('#'):
+ // done
+ case s.Flag('+'):
+ file = pkgFilePath(&c.frame)
+ default:
+ const sep = "/"
+ if i := strings.LastIndex(file, sep); i != -1 {
+ file = file[i+len(sep):]
+ }
+ }
+ io.WriteString(s, file)
+ if verb == 'v' {
+ buf := [7]byte{':'}
+ s.Write(strconv.AppendInt(buf[:1], int64(c.frame.Line), 10))
+ }
+
+ case 'd':
+ buf := [6]byte{}
+ s.Write(strconv.AppendInt(buf[:0], int64(c.frame.Line), 10))
+
+ case 'k':
+ name := c.frame.Function
+ const pathSep = "/"
+ start, end := 0, len(name)
+ if i := strings.LastIndex(name, pathSep); i != -1 {
+ start = i + len(pathSep)
+ }
+ const pkgSep = "."
+ if i := strings.Index(name[start:], pkgSep); i != -1 {
+ end = start + i
+ }
+ if s.Flag('+') {
+ start = 0
+ }
+ io.WriteString(s, name[start:end])
+
+ case 'n':
+ name := c.frame.Function
+ if !s.Flag('+') {
+ const pathSep = "/"
+ if i := strings.LastIndex(name, pathSep); i != -1 {
+ name = name[i+len(pathSep):]
+ }
+ const pkgSep = "."
+ if i := strings.Index(name, pkgSep); i != -1 {
+ name = name[i+len(pkgSep):]
+ }
+ }
+ io.WriteString(s, name)
+ }
+}
+
+// Frame returns the call frame infomation for the Call.
+func (c Call) Frame() runtime.Frame {
+ return c.frame
+}
+
+// PC returns the program counter for this call frame; multiple frames may
+// have the same PC value.
+//
+// Deprecated: Use Call.Frame instead.
+func (c Call) PC() uintptr {
+ return c.frame.PC
+}
+
+// CallStack records a sequence of function invocations from a goroutine
+// stack.
+type CallStack []Call
+
+// String implements fmt.Stinger. It is equivalent to fmt.Sprintf("%v", cs).
+func (cs CallStack) String() string {
+ return fmt.Sprint(cs)
+}
+
+var (
+ openBracketBytes = []byte("[")
+ closeBracketBytes = []byte("]")
+ spaceBytes = []byte(" ")
+)
+
+// MarshalText implements encoding.TextMarshaler. It formats the CallStack the
+// same as fmt.Sprintf("%v", cs).
+func (cs CallStack) MarshalText() ([]byte, error) {
+ buf := bytes.Buffer{}
+ buf.Write(openBracketBytes)
+ for i, pc := range cs {
+ if i > 0 {
+ buf.Write(spaceBytes)
+ }
+ fmt.Fprint(&buf, pc)
+ }
+ buf.Write(closeBracketBytes)
+ return buf.Bytes(), nil
+}
+
+// Format implements fmt.Formatter by printing the CallStack as square brackets
+// ([, ]) surrounding a space separated list of Calls each formatted with the
+// supplied verb and options.
+func (cs CallStack) Format(s fmt.State, verb rune) {
+ s.Write(openBracketBytes)
+ for i, pc := range cs {
+ if i > 0 {
+ s.Write(spaceBytes)
+ }
+ pc.Format(s, verb)
+ }
+ s.Write(closeBracketBytes)
+}
+
+// Trace returns a CallStack for the current goroutine with element 0
+// identifying the calling function.
+func Trace() CallStack {
+ var pcs [512]uintptr
+ n := runtime.Callers(1, pcs[:])
+
+ frames := runtime.CallersFrames(pcs[:n])
+ cs := make(CallStack, 0, n)
+
+ // Skip extra frame retrieved just to make sure the runtime.sigpanic
+ // special case is handled.
+ frame, more := frames.Next()
+
+ for more {
+ frame, more = frames.Next()
+ cs = append(cs, Call{frame: frame})
+ }
+
+ return cs
+}
+
+// TrimBelow returns a slice of the CallStack with all entries below c
+// removed.
+func (cs CallStack) TrimBelow(c Call) CallStack {
+ for len(cs) > 0 && cs[0] != c {
+ cs = cs[1:]
+ }
+ return cs
+}
+
+// TrimAbove returns a slice of the CallStack with all entries above c
+// removed.
+func (cs CallStack) TrimAbove(c Call) CallStack {
+ for len(cs) > 0 && cs[len(cs)-1] != c {
+ cs = cs[:len(cs)-1]
+ }
+ return cs
+}
+
+// pkgIndex returns the index that results in file[index:] being the path of
+// file relative to the compile time GOPATH, and file[:index] being the
+// $GOPATH/src/ portion of file. funcName must be the name of a function in
+// file as returned by runtime.Func.Name.
+func pkgIndex(file, funcName string) int {
+ // As of Go 1.6.2 there is no direct way to know the compile time GOPATH
+ // at runtime, but we can infer the number of path segments in the GOPATH.
+ // We note that runtime.Func.Name() returns the function name qualified by
+ // the import path, which does not include the GOPATH. Thus we can trim
+ // segments from the beginning of the file path until the number of path
+ // separators remaining is one more than the number of path separators in
+ // the function name. For example, given:
+ //
+ // GOPATH /home/user
+ // file /home/user/src/pkg/sub/file.go
+ // fn.Name() pkg/sub.Type.Method
+ //
+ // We want to produce:
+ //
+ // file[:idx] == /home/user/src/
+ // file[idx:] == pkg/sub/file.go
+ //
+ // From this we can easily see that fn.Name() has one less path separator
+ // than our desired result for file[idx:]. We count separators from the
+ // end of the file path until it finds two more than in the function name
+ // and then move one character forward to preserve the initial path
+ // segment without a leading separator.
+ const sep = "/"
+ i := len(file)
+ for n := strings.Count(funcName, sep) + 2; n > 0; n-- {
+ i = strings.LastIndex(file[:i], sep)
+ if i == -1 {
+ i = -len(sep)
+ break
+ }
+ }
+ // get back to 0 or trim the leading separator
+ return i + len(sep)
+}
+
+// pkgFilePath returns the frame's filepath relative to the compile-time GOPATH,
+// or its module path joined to its path relative to the module root.
+//
+// As of Go 1.11 there is no direct way to know the compile time GOPATH or
+// module paths at runtime, but we can piece together the desired information
+// from available information. We note that runtime.Frame.Function contains the
+// function name qualified by the package path, which includes the module path
+// but not the GOPATH. We can extract the package path from that and append the
+// last segments of the file path to arrive at the desired package qualified
+// file path. For example, given:
+//
+// GOPATH /home/user
+// import path pkg/sub
+// frame.File /home/user/src/pkg/sub/file.go
+// frame.Function pkg/sub.Type.Method
+// Desired return pkg/sub/file.go
+//
+// It appears that we simply need to trim ".Type.Method" from frame.Function and
+// append "/" + path.Base(file).
+//
+// But there are other wrinkles. Although it is idiomatic to do so, the internal
+// name of a package is not required to match the last segment of its import
+// path. In addition, the introduction of modules in Go 1.11 allows working
+// without a GOPATH. So we also must make these work right:
+//
+// GOPATH /home/user
+// import path pkg/go-sub
+// package name sub
+// frame.File /home/user/src/pkg/go-sub/file.go
+// frame.Function pkg/sub.Type.Method
+// Desired return pkg/go-sub/file.go
+//
+// Module path pkg/v2
+// import path pkg/v2/go-sub
+// package name sub
+// frame.File /home/user/cloned-pkg/go-sub/file.go
+// frame.Function pkg/v2/sub.Type.Method
+// Desired return pkg/v2/go-sub/file.go
+//
+// We can handle all of these situations by using the package path extracted
+// from frame.Function up to, but not including, the last segment as the prefix
+// and the last two segments of frame.File as the suffix of the returned path.
+// This preserves the existing behavior when working in a GOPATH without modules
+// and a semantically equivalent behavior when used in module aware project.
+func pkgFilePath(frame *runtime.Frame) string {
+ pre := pkgPrefix(frame.Function)
+ post := pathSuffix(frame.File)
+ if pre == "" {
+ return post
+ }
+ return pre + "/" + post
+}
+
+// pkgPrefix returns the import path of the function's package with the final
+// segment removed.
+func pkgPrefix(funcName string) string {
+ const pathSep = "/"
+ end := strings.LastIndex(funcName, pathSep)
+ if end == -1 {
+ return ""
+ }
+ return funcName[:end]
+}
+
+// pathSuffix returns the last two segments of path.
+func pathSuffix(path string) string {
+ const pathSep = "/"
+ lastSep := strings.LastIndex(path, pathSep)
+ if lastSep == -1 {
+ return path
+ }
+ return path[strings.LastIndex(path[:lastSep], pathSep)+1:]
+}
+
+var runtimePath string
+
+func init() {
+ var pcs [3]uintptr
+ runtime.Callers(0, pcs[:])
+ frames := runtime.CallersFrames(pcs[:])
+ frame, _ := frames.Next()
+ file := frame.File
+
+ idx := pkgIndex(frame.File, frame.Function)
+
+ runtimePath = file[:idx]
+ if runtime.GOOS == "windows" {
+ runtimePath = strings.ToLower(runtimePath)
+ }
+}
+
+func inGoroot(c Call) bool {
+ file := c.frame.File
+ if len(file) == 0 || file[0] == '?' {
+ return true
+ }
+ if runtime.GOOS == "windows" {
+ file = strings.ToLower(file)
+ }
+ return strings.HasPrefix(file, runtimePath) || strings.HasSuffix(file, "/_testmain.go")
+}
+
+// TrimRuntime returns a slice of the CallStack with the topmost entries from
+// the go runtime removed. It considers any calls originating from unknown
+// files, files under GOROOT, or _testmain.go as part of the runtime.
+func (cs CallStack) TrimRuntime() CallStack {
+ for len(cs) > 0 && inGoroot(cs[len(cs)-1]) {
+ cs = cs[:len(cs)-1]
+ }
+ return cs
+}
diff --git a/vendor/github.com/magiconair/properties/properties.go b/vendor/github.com/magiconair/properties/properties.go
index fb2f7b4..5829761 100644
--- a/vendor/github.com/magiconair/properties/properties.go
+++ b/vendor/github.com/magiconair/properties/properties.go
@@ -18,6 +18,7 @@ import (
"strconv"
"strings"
"time"
+ "unicode"
"unicode/utf8"
)
@@ -306,6 +307,40 @@ func (p *Properties) getFloat64(key string) (value float64, err error) {
// ----------------------------------------------------------------------------
+// GetFloat32 parses the expanded value as a float32 if the key exists.
+// If key does not exist or the value cannot be parsed the default
+// value is returned.
+func (p *Properties) GetFloat32(key string, def float32) float32 {
+ v, err := p.getFloat32(key)
+ if err != nil {
+ return def
+ }
+ return v
+}
+
+// MustGetFloat32 parses the expanded value as a float32 if the key exists.
+// If key does not exist or the value cannot be parsed the function panics.
+func (p *Properties) MustGetFloat32(key string) float32 {
+ v, err := p.getFloat32(key)
+ if err != nil {
+ ErrorHandler(err)
+ }
+ return v
+}
+
+func (p *Properties) getFloat32(key string) (value float32, err error) {
+ if v, ok := p.Get(key); ok {
+ n, err := strconv.ParseFloat(v, 32)
+ if err != nil {
+ return 0, err
+ }
+ return float32(n), nil
+ }
+ return 0, invalidKeyError(key)
+}
+
+// ----------------------------------------------------------------------------
+
// GetInt parses the expanded value as an int if the key exists.
// If key does not exist or the value cannot be parsed the default
// value is returned. If the value does not fit into an int the
@@ -366,6 +401,40 @@ func (p *Properties) getInt64(key string) (value int64, err error) {
// ----------------------------------------------------------------------------
+// GetInt32 parses the expanded value as an int32 if the key exists.
+// If key does not exist or the value cannot be parsed the default
+// value is returned.
+func (p *Properties) GetInt32(key string, def int32) int32 {
+ v, err := p.getInt32(key)
+ if err != nil {
+ return def
+ }
+ return v
+}
+
+// MustGetInt32 parses the expanded value as an int if the key exists.
+// If key does not exist or the value cannot be parsed the function panics.
+func (p *Properties) MustGetInt32(key string) int32 {
+ v, err := p.getInt32(key)
+ if err != nil {
+ ErrorHandler(err)
+ }
+ return v
+}
+
+func (p *Properties) getInt32(key string) (value int32, err error) {
+ if v, ok := p.Get(key); ok {
+ n, err := strconv.ParseInt(v, 10, 32)
+ if err != nil {
+ return 0, err
+ }
+ return int32(n), nil
+ }
+ return 0, invalidKeyError(key)
+}
+
+// ----------------------------------------------------------------------------
+
// GetUint parses the expanded value as an uint if the key exists.
// If key does not exist or the value cannot be parsed the default
// value is returned. If the value does not fit into an int the
@@ -426,6 +495,40 @@ func (p *Properties) getUint64(key string) (value uint64, err error) {
// ----------------------------------------------------------------------------
+// GetUint32 parses the expanded value as an uint32 if the key exists.
+// If key does not exist or the value cannot be parsed the default
+// value is returned.
+func (p *Properties) GetUint32(key string, def uint32) uint32 {
+ v, err := p.getUint32(key)
+ if err != nil {
+ return def
+ }
+ return v
+}
+
+// MustGetUint32 parses the expanded value as an int if the key exists.
+// If key does not exist or the value cannot be parsed the function panics.
+func (p *Properties) MustGetUint32(key string) uint32 {
+ v, err := p.getUint32(key)
+ if err != nil {
+ ErrorHandler(err)
+ }
+ return v
+}
+
+func (p *Properties) getUint32(key string) (value uint32, err error) {
+ if v, ok := p.Get(key); ok {
+ n, err := strconv.ParseUint(v, 10, 32)
+ if err != nil {
+ return 0, err
+ }
+ return uint32(n), nil
+ }
+ return 0, invalidKeyError(key)
+}
+
+// ----------------------------------------------------------------------------
+
// GetString returns the expanded value for the given key if exists or
// the default value otherwise.
func (p *Properties) GetString(key, def string) string {
@@ -799,8 +902,13 @@ func encodeUtf8(s string, special string) string {
v := ""
for pos := 0; pos < len(s); {
r, w := utf8.DecodeRuneInString(s[pos:])
+ switch {
+ case pos == 0 && unicode.IsSpace(r): // escape leading whitespace
+ v += escape(r, " ")
+ default:
+ v += escape(r, special) // escape special chars only
+ }
pos += w
- v += escape(r, special)
}
return v
}
@@ -811,6 +919,8 @@ func encodeIso(s string, special string) string {
var v string
for pos := 0; pos < len(s); {
switch r, w = utf8.DecodeRuneInString(s[pos:]); {
+ case pos == 0 && unicode.IsSpace(r): // escape leading whitespace
+ v += escape(r, " ")
case r < 1<<8: // single byte rune -> escape special chars only
v += escape(r, special)
case r < 1<<16: // two byte rune -> unicode literal
diff --git a/vendor/github.com/playwright-community/playwright-go/.gitattributes b/vendor/github.com/playwright-community/playwright-go/.gitattributes
new file mode 100644
index 0000000..c976050
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/.gitattributes
@@ -0,0 +1,3 @@
+# text files must be lf for golden file tests to work
+* text=auto eol=lf
+
diff --git a/vendor/github.com/playwright-community/playwright-go/.gitignore b/vendor/github.com/playwright-community/playwright-go/.gitignore
new file mode 100644
index 0000000..83e2355
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/.gitignore
@@ -0,0 +1,34 @@
+# Created by https://www.toptal.com/developers/gitignore/api/go
+# Edit at https://www.toptal.com/developers/gitignore?templates=go
+
+### Go ###
+# Binaries for programs and plugins
+*.exe
+*.exe~
+*.dll
+*.so
+*.dylib
+
+# Test binary, built with `go test -c`
+*.test
+
+# Output of the go coverage tool, specifically when used with LiteIDE
+*.out
+
+# Dependency directories (remove the comment below to include it)
+# vendor/
+
+### Go Patch ###
+/vendor/
+/Godeps/
+
+# End of https://www.toptal.com/developers/gitignore/api/go
+covprofile
+.idea/
+.DS_Store
+
+api.json
+_site/
+.jekyll-cache/
+
+.vscode/settings.json \ No newline at end of file
diff --git a/vendor/github.com/playwright-community/playwright-go/.gitmodules b/vendor/github.com/playwright-community/playwright-go/.gitmodules
new file mode 100644
index 0000000..9ab899d
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "playwright"]
+ path = playwright
+ url = https://github.com/microsoft/playwright
diff --git a/vendor/github.com/playwright-community/playwright-go/.golangci.yaml b/vendor/github.com/playwright-community/playwright-go/.golangci.yaml
new file mode 100644
index 0000000..1557a3f
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/.golangci.yaml
@@ -0,0 +1,6 @@
+---
+linters:
+ enable-all: false
+ disable-all: false
+ enable:
+ - gofumpt \ No newline at end of file
diff --git a/vendor/github.com/playwright-community/playwright-go/.nojekyll b/vendor/github.com/playwright-community/playwright-go/.nojekyll
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/.nojekyll
diff --git a/vendor/github.com/playwright-community/playwright-go/404.html b/vendor/github.com/playwright-community/playwright-go/404.html
new file mode 100644
index 0000000..086a5c9
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/404.html
@@ -0,0 +1,25 @@
+---
+permalink: /404.html
+layout: default
+---
+
+<style type="text/css" media="screen">
+ .container {
+ margin: 10px auto;
+ max-width: 600px;
+ text-align: center;
+ }
+ h1 {
+ margin: 30px 0;
+ font-size: 4em;
+ line-height: 1;
+ letter-spacing: -1px;
+ }
+</style>
+
+<div class="container">
+ <h1>404</h1>
+
+ <p><strong>Page not found :(</strong></p>
+ <p>The requested page could not be found.</p>
+</div>
diff --git a/vendor/github.com/playwright-community/playwright-go/CONTRIBUTING.md b/vendor/github.com/playwright-community/playwright-go/CONTRIBUTING.md
new file mode 100644
index 0000000..3b11995
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/CONTRIBUTING.md
@@ -0,0 +1,39 @@
+# Contributing
+
+## Code style
+The Go code is linted with [golangci-lint](https://golangci-lint.run/) and formatted with [gofumpt](https://github.com/mvdan/gofumpt). Please configure your editor to run the tools while developing and make sure to run the tools before committing any code.
+
+## Tests
+
+### Test coverage
+
+For every Pull Request on GitHub and on the main branch the coverage data will get sent over to [Coveralls](https://coveralls.io/github/playwright-community/playwright-go), this is helpful for finding functions that aren't covered by tests.
+
+### Running tests
+
+You can use the `BROWSER` environment variable to use a different browser than Chromium for the tests and use the `HEADLESS` environment variable which is useful for debugging.
+
+```
+BROWSER=chromium HEADLESS=1 go test -v --race ./...
+```
+
+### Roll
+
+1. Find out to which upstream version you want to roll, and change the value of `playwrightCliVersion` in the **run.go** to the new version.
+1. Download current version of Playwright driver `go run scripts/install-browsers/main.go`
+1. Apply patch `bash scripts/apply-patch.sh`
+1. Fix merge conflicts if any, otherwise ignore this step. Once you are happy you can commit the changes `cd playwright; git commit -am "apply patch" && cd ..`
+1. Regenerate a new patch `bash scripts/update-patch.sh`
+1. Generate go code `go generate ./...`
+
+To adapt to the new version of Playwright's protocol and feature updates, you may need to modify the patch. Refer to the following steps:
+
+1. Apply patch `bash scripts/apply-patch.sh`
+1. `cd playwright`
+1. Revert the patch`git reset HEAD~1`
+1. Modify the files under `docs/src/api`, etc. as needed. Available references:
+ - Protocol `packages/protocol/src/protocol.yml`
+ - [Playwright python](https://github.com/microsoft/playwright-python)
+1. Commit the changes `git commit -am "apply patch"`
+1. Regenerate a new patch `bash scripts/update-patch.sh`
+1. Generate go code `go generate ./...`.
diff --git a/vendor/github.com/playwright-community/playwright-go/Dockerfile.example b/vendor/github.com/playwright-community/playwright-go/Dockerfile.example
new file mode 100644
index 0000000..3077cf3
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/Dockerfile.example
@@ -0,0 +1,25 @@
+# Stage 1: Modules caching
+FROM golang:1.22 as modules
+COPY go.mod go.sum /modules/
+WORKDIR /modules
+RUN go mod download
+
+# Stage 2: Build
+FROM golang:1.22 as builder
+COPY --from=modules /go/pkg /go/pkg
+COPY . /workdir
+WORKDIR /workdir
+# Install playwright cli with right version for later use
+RUN PWGO_VER=$(grep -oE "playwright-go v\S+" /workdir/go.mod | sed 's/playwright-go //g') \
+ && go install github.com/playwright-community/playwright-go/cmd/playwright@${PWGO_VER}
+# Build your app
+RUN GOOS=linux GOARCH=amd64 go build -o /bin/myapp
+
+# Stage 3: Final
+FROM ubuntu:noble
+COPY --from=builder /go/bin/playwright /bin/myapp /
+RUN apt-get update && apt-get install -y ca-certificates tzdata \
+ # Install dependencies and all browsers (or specify one)
+ && /playwright install --with-deps \
+ && rm -rf /var/lib/apt/lists/*
+CMD ["/myapp"] \ No newline at end of file
diff --git a/vendor/github.com/playwright-community/playwright-go/LICENSE b/vendor/github.com/playwright-community/playwright-go/LICENSE
new file mode 100644
index 0000000..d4f29b3
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 Max Schmitt
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/vendor/github.com/playwright-community/playwright-go/README.md b/vendor/github.com/playwright-community/playwright-go/README.md
new file mode 100644
index 0000000..a9e3dd7
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/README.md
@@ -0,0 +1,148 @@
+# 🎭 [Playwright](https://github.com/microsoft/playwright#readme) for <img src="https://user-images.githubusercontent.com/17984549/91302719-343a1d80-e7a7-11ea-8d6a-9448ef598420.png" height="35" />
+
+## Looking for maintainers and see [here](https://github.com/playwright-community/playwright-go/issues/122). Thanks!
+
+[![PkgGoDev](https://pkg.go.dev/badge/github.com/playwright-community/playwright-go)](https://pkg.go.dev/github.com/playwright-community/playwright-go)
+[![License](https://img.shields.io/badge/License-MIT-blue.svg)](http://opensource.org/licenses/MIT)
+[![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)
+[![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-136.0.7103.25-blue.svg?logo=google-chrome)](https://www.chromium.org/Home)<!-- GEN:stop --> <!-- GEN:firefox-version-badge -->[![Firefox version](https://img.shields.io/badge/firefox-137.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-18.4-blue.svg?logo=safari)](https://webkit.org/)<!-- GEN:stop -->
+
+[API reference](https://playwright.dev/docs/api/class-playwright) | [Example recipes](https://github.com/playwright-community/playwright-go/tree/main/examples)
+
+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**.
+
+| | Linux | macOS | Windows |
+| :--- | :---: | :---: | :---: |
+| Chromium <!-- GEN:chromium-version -->136.0.7103.25<!-- GEN:stop --> | ✅ | ✅ | ✅ |
+| WebKit <!-- GEN:webkit-version -->18.4<!-- GEN:stop --> | ✅ | ✅ | ✅ |
+| Firefox <!-- GEN:firefox-version -->137.0<!-- GEN:stop --> | ✅ | ✅ | ✅ |
+
+Headless execution is supported for all the browsers on all platforms.
+
+## Installation
+
+```txt
+go get -u github.com/playwright-community/playwright-go
+```
+
+Install the browsers and OS dependencies:
+
+```bash
+go run github.com/playwright-community/playwright-go/cmd/playwright@latest install --with-deps
+# Or
+go install github.com/playwright-community/playwright-go/cmd/playwright@latest
+playwright install --with-deps
+```
+
+Alternatively you can do it inside your program via which downloads the driver and browsers:
+
+```go
+err := playwright.Install()
+```
+
+## Capabilities
+
+Playwright is built to automate the broad and growing set of web browser capabilities used by Single Page Apps and Progressive Web Apps.
+
+* Scenarios that span multiple page, domains and iframes
+* Auto-wait for elements to be ready before executing actions (like click, fill)
+* Intercept network activity for stubbing and mocking network requests
+* Emulate mobile devices, geolocation, permissions
+* Support for web components via shadow-piercing selectors
+* Native input events for mouse and keyboard
+* Upload and download files
+
+## Example
+
+The following example crawls the current top voted items from [Hacker News](https://news.ycombinator.com).
+
+```go
+
+package main
+
+import (
+ "fmt"
+ "log"
+
+ "github.com/playwright-community/playwright-go"
+)
+
+func main() {
+ pw, err := playwright.Run()
+ if err != nil {
+ log.Fatalf("could not start playwright: %v", err)
+ }
+ browser, err := pw.Chromium.Launch()
+ if err != nil {
+ log.Fatalf("could not launch browser: %v", err)
+ }
+ page, err := browser.NewPage()
+ if err != nil {
+ log.Fatalf("could not create page: %v", err)
+ }
+ if _, err = page.Goto("https://news.ycombinator.com"); err != nil {
+ log.Fatalf("could not goto: %v", err)
+ }
+ entries, err := page.Locator(".athing").All()
+ if err != nil {
+ log.Fatalf("could not get entries: %v", err)
+ }
+ for i, entry := range entries {
+ title, err := entry.Locator("td.title > span > a").TextContent()
+ if err != nil {
+ log.Fatalf("could not get text content: %v", err)
+ }
+ fmt.Printf("%d: %s\n", i+1, title)
+ }
+ if err = browser.Close(); err != nil {
+ log.Fatalf("could not close browser: %v", err)
+ }
+ if err = pw.Stop(); err != nil {
+ log.Fatalf("could not stop Playwright: %v", err)
+ }
+}
+```
+
+## Docker
+Refer to the [Dockerfile.example](./Dockerfile.example) to build your own docker image.
+
+## More examples
+
+* Refer to [helper_test.go](./tests/helper_test.go) for End-To-End testing
+* [Downloading files](./examples/download/main.go)
+* [End-To-End testing a website](./examples/end-to-end-testing/main.go)
+* [Executing JavaScript in the browser](./examples/javascript/main.go)
+* [Emulate mobile and geolocation](./examples/mobile-and-geolocation/main.go)
+* [Parallel scraping using a WaitGroup](./examples/parallel-scraping/main.go)
+* [Rendering a PDF of a website](./examples/pdf/main.go)
+* [Scraping HackerNews](./examples/scraping/main.go)
+* [Take a screenshot](./examples/screenshot/main.go)
+* [Record a video](./examples/video/main.go)
+* [Monitor network activity](./examples/network-monitoring/main.go)
+
+## How does it work?
+
+Playwright is a Node.js library which uses:
+
+* Chrome DevTools Protocol to communicate with Chromium
+* Patched Firefox to communicate with Firefox
+* Patched WebKit to communicate with WebKit
+
+These patches are based on the original sources of the browsers and don't modify the browser behaviour so the browsers are basically the same (see [here](https://github.com/microsoft/playwright/tree/main/browser_patches)) as you see them in the wild. The support for different programming languages is based on exposing a RPC server in the Node.js land which can be used to allow other languages to use Playwright without implementing all the custom logic:
+
+* [Playwright for Python](https://github.com/microsoft/playwright-python)
+* [Playwright for .NET](https://github.com/microsoft/playwright-sharp)
+* [Playwright for Java](https://github.com/microsoft/playwright-java)
+* [Playwright for Go](https://github.com/playwright-community/playwright-go)
+
+The bridge between Node.js and the other languages is basically a Node.js runtime combined with Playwright which gets shipped for each of these languages (around 50MB) and then communicates over stdio to send the relevant commands. This will also download the pre-compiled browsers.
+
+## Is Playwright for Go ready?
+
+We are ready for your feedback, but we are still covering Playwright Go with the tests.
+
+## Resources
+
+* [Playwright for Go Documentation](https://pkg.go.dev/github.com/playwright-community/playwright-go)
+* [Playwright Documentation](https://playwright.dev/docs/api/class-playwright)
+* [Example recipes](https://github.com/playwright-community/playwright-go/tree/main/examples)
diff --git a/vendor/github.com/playwright-community/playwright-go/_config.yml b/vendor/github.com/playwright-community/playwright-go/_config.yml
new file mode 100644
index 0000000..15ec3b2
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/_config.yml
@@ -0,0 +1,21 @@
+title: Playwright for Go
+email: max@schmitt.mx
+description: >- # this means to ignore newlines until "baseurl:"
+ Playwright is a Node.js library to automate Chromium, Firefox and WebKit with a single API.
+ Playwright is built to enable cross-browser web automation that is ever-green, capable, reliable and fast.
+baseurl: "/playwright-go"
+url: "https://playwright-community.github.io/"
+twitter_username: maxibanki
+github_username: playwright-community
+remote_theme: pages-themes/cayman@v0.2.0
+plugins:
+ - jekyll-remote-theme
+ - jekyll-optional-front-matter
+ - jekyll-readme-index
+exclude:
+ - playwright/
+defaults:
+ - scope:
+ path: "" # an empty string here means all files in the project
+ values:
+ layout: "default"
diff --git a/vendor/github.com/playwright-community/playwright-go/apiresponse_assertions.go b/vendor/github.com/playwright-community/playwright-go/apiresponse_assertions.go
new file mode 100644
index 0000000..187618e
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/apiresponse_assertions.go
@@ -0,0 +1,75 @@
+package playwright
+
+import (
+ "errors"
+ "fmt"
+ "regexp"
+ "strings"
+)
+
+type apiResponseAssertionsImpl struct {
+ actual APIResponse
+ isNot bool
+}
+
+func newAPIResponseAssertions(actual APIResponse, isNot bool) *apiResponseAssertionsImpl {
+ return &apiResponseAssertionsImpl{
+ actual: actual,
+ isNot: isNot,
+ }
+}
+
+func (ar *apiResponseAssertionsImpl) Not() APIResponseAssertions {
+ return newAPIResponseAssertions(ar.actual, true)
+}
+
+func (ar *apiResponseAssertionsImpl) ToBeOK() error {
+ if ar.isNot != ar.actual.Ok() {
+ return nil
+ }
+ message := fmt.Sprintf(`Response status expected to be within [200..299] range, was %v`, ar.actual.Status())
+ if ar.isNot {
+ message = strings.ReplaceAll(message, "expected to", "expected not to")
+ }
+ logList, err := ar.actual.(*apiResponseImpl).fetchLog()
+ if err != nil {
+ return err
+ }
+ log := strings.Join(logList, "\n")
+ if log != "" {
+ message += "\nCall log:\n" + log
+ }
+
+ isTextEncoding := false
+ contentType, ok := ar.actual.Headers()["content-type"]
+ if ok {
+ isTextEncoding = isTexualMimeType(contentType)
+ }
+ if isTextEncoding {
+ text, err := ar.actual.Text()
+ if err == nil {
+ message += fmt.Sprintf(`\n Response Text:\n %s`, subString(text, 0, 1000))
+ }
+ }
+ return errors.New(message)
+}
+
+func isTexualMimeType(mimeType string) bool {
+ re := regexp.MustCompile(`^(text\/.*?|application\/(json|(x-)?javascript|xml.*?|ecmascript|graphql|x-www-form-urlencoded)|image\/svg(\+xml)?|application\/.*?(\+json|\+xml))(;\s*charset=.*)?$`)
+ return re.MatchString(mimeType)
+}
+
+func subString(s string, start, length int) string {
+ if start < 0 {
+ start = 0
+ }
+ if length < 0 {
+ length = 0
+ }
+ rs := []rune(s)
+ end := start + length
+ if end > len(rs) {
+ end = len(rs)
+ }
+ return string(rs[start:end])
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/artifact.go b/vendor/github.com/playwright-community/playwright-go/artifact.go
new file mode 100644
index 0000000..c76b892
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/artifact.go
@@ -0,0 +1,70 @@
+package playwright
+
+import (
+ "errors"
+ "fmt"
+)
+
+type artifactImpl struct {
+ channelOwner
+}
+
+func (a *artifactImpl) AbsolutePath() string {
+ return a.initializer["absolutePath"].(string)
+}
+
+func (a *artifactImpl) PathAfterFinished() (string, error) {
+ if a.connection.isRemote {
+ return "", errors.New("Path is not available when connecting remotely. Use SaveAs() to save a local copy")
+ }
+ path, err := a.channel.Send("pathAfterFinished")
+ return path.(string), err
+}
+
+func (a *artifactImpl) SaveAs(path string) error {
+ if !a.connection.isRemote {
+ _, err := a.channel.Send("saveAs", map[string]interface{}{
+ "path": path,
+ })
+ return err
+ }
+ streamChannel, err := a.channel.Send("saveAsStream")
+ if err != nil {
+ return err
+ }
+ stream := fromChannel(streamChannel).(*streamImpl)
+ return stream.SaveAs(path)
+}
+
+func (a *artifactImpl) Failure() error {
+ reason, err := a.channel.Send("failure")
+ if reason == nil {
+ return err
+ }
+ return fmt.Errorf("%w: %v", ErrPlaywright, reason)
+}
+
+func (a *artifactImpl) Delete() error {
+ _, err := a.channel.Send("delete")
+ return err
+}
+
+func (a *artifactImpl) Cancel() error {
+ _, err := a.channel.Send("cancel")
+ return err
+}
+
+func (a *artifactImpl) ReadIntoBuffer() ([]byte, error) {
+ streamChannel, err := a.channel.Send("stream")
+ if err != nil {
+ return nil, err
+ }
+ stream := fromChannel(streamChannel)
+ return stream.(*streamImpl).ReadAll()
+}
+
+func newArtifact(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *artifactImpl {
+ artifact := &artifactImpl{}
+ artifact.createChannelOwner(artifact, parent, objectType, guid, initializer)
+ return artifact
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/assertions.go b/vendor/github.com/playwright-community/playwright-go/assertions.go
new file mode 100644
index 0000000..5e0e710
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/assertions.go
@@ -0,0 +1,146 @@
+package playwright
+
+import (
+ "errors"
+ "fmt"
+ "reflect"
+ "regexp"
+ "strings"
+)
+
+const assertionsDefaultTimeout = 5000 // 5s
+
+type playwrightAssertionsImpl struct {
+ defaultTimeout *float64
+}
+
+// NewPlaywrightAssertions creates a new instance of PlaywrightAssertions
+// - timeout: default value is 5000 (ms)
+func NewPlaywrightAssertions(timeout ...float64) PlaywrightAssertions {
+ if len(timeout) > 0 {
+ return &playwrightAssertionsImpl{Float(timeout[0])}
+ }
+ return &playwrightAssertionsImpl{Float(assertionsDefaultTimeout)}
+}
+
+func (pa *playwrightAssertionsImpl) APIResponse(response APIResponse) APIResponseAssertions {
+ return newAPIResponseAssertions(response, false)
+}
+
+func (pa *playwrightAssertionsImpl) Locator(locator Locator) LocatorAssertions {
+ return newLocatorAssertions(locator, false, pa.defaultTimeout)
+}
+
+func (pa *playwrightAssertionsImpl) Page(page Page) PageAssertions {
+ return newPageAssertions(page, false, pa.defaultTimeout)
+}
+
+type expectedTextValue struct {
+ Str *string `json:"string,omitempty"`
+ RegexSource *string `json:"regexSource,omitempty"`
+ RegexFlags *string `json:"regexFlags,omitempty"`
+ MatchSubstring *bool `json:"matchSubstring,omitempty"`
+ IgnoreCase *bool `json:"ignoreCase,omitempty"`
+ NormalizeWhiteSpace *bool `json:"normalizeWhiteSpace,omitempty"`
+}
+
+type frameExpectOptions struct {
+ ExpressionArg interface{} `json:"expressionArg,omitempty"`
+ ExpectedText []expectedTextValue `json:"expectedText,omitempty"`
+ ExpectedNumber *float64 `json:"expectedNumber,omitempty"`
+ ExpectedValue interface{} `json:"expectedValue,omitempty"`
+ UseInnerText *bool `json:"useInnerText,omitempty"`
+ IsNot bool `json:"isNot"`
+ Timeout *float64 `json:"timeout"`
+}
+
+type frameExpectResult struct {
+ Matches bool `json:"matches"`
+ Received interface{} `json:"received,omitempty"`
+ TimedOut *bool `json:"timedOut,omitempty"`
+ Log []string `json:"log,omitempty"`
+}
+
+type assertionsBase struct {
+ actualLocator Locator
+ isNot bool
+ defaultTimeout *float64
+}
+
+func (b *assertionsBase) expect(
+ expression string,
+ options frameExpectOptions,
+ expected interface{},
+ message string,
+) error {
+ options.IsNot = b.isNot
+ if options.Timeout == nil {
+ options.Timeout = b.defaultTimeout
+ }
+ if options.IsNot {
+ message = strings.ReplaceAll(message, "expected to", "expected not to")
+ }
+ result, err := b.actualLocator.(*locatorImpl).expect(expression, options)
+ if err != nil {
+ return err
+ }
+
+ if result.Matches == b.isNot {
+ actual := result.Received
+ log := strings.Join(result.Log, "\n")
+ if log != "" {
+ log = "\nCall log:\n" + log
+ }
+ if expected != nil {
+ return fmt.Errorf("%s '%v'\nActual value: %v %s", message, expected, actual, log)
+ }
+ return fmt.Errorf("%s\nActual value: %v %s", message, actual, log)
+ }
+
+ return nil
+}
+
+func toExpectedTextValues(
+ items []interface{},
+ matchSubstring bool,
+ normalizeWhiteSpace bool,
+ ignoreCase *bool,
+) ([]expectedTextValue, error) {
+ var out []expectedTextValue
+ for _, item := range items {
+ switch item := item.(type) {
+ case string:
+ out = append(out, expectedTextValue{
+ Str: String(item),
+ MatchSubstring: Bool(matchSubstring),
+ NormalizeWhiteSpace: Bool(normalizeWhiteSpace),
+ IgnoreCase: ignoreCase,
+ })
+ case *regexp.Regexp:
+ pattern, flags := convertRegexp(item)
+ out = append(out, expectedTextValue{
+ RegexSource: String(pattern),
+ RegexFlags: String(flags),
+ MatchSubstring: Bool(matchSubstring),
+ NormalizeWhiteSpace: Bool(normalizeWhiteSpace),
+ IgnoreCase: ignoreCase,
+ })
+ default:
+ return nil, errors.New("value must be a string or regexp")
+ }
+ }
+ return out, nil
+}
+
+func convertToInterfaceList(v interface{}) []interface{} {
+ rv := reflect.ValueOf(v)
+ if rv.Kind() != reflect.Slice {
+ return []interface{}{v}
+ }
+
+ list := make([]interface{}, rv.Len())
+ for i := 0; i < rv.Len(); i++ {
+ list[i] = rv.Index(i).Interface()
+ }
+ return list
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/binding_call.go b/vendor/github.com/playwright-community/playwright-go/binding_call.go
new file mode 100644
index 0000000..8468992
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/binding_call.go
@@ -0,0 +1,87 @@
+package playwright
+
+import (
+ "fmt"
+ "strings"
+
+ "github.com/go-stack/stack"
+)
+
+type BindingCall interface {
+ Call(f BindingCallFunction)
+}
+
+type bindingCallImpl struct {
+ channelOwner
+}
+
+// BindingSource is the value passed to a binding call execution
+type BindingSource struct {
+ Context BrowserContext
+ Page Page
+ Frame Frame
+}
+
+// ExposedFunction represents the func signature of an exposed function
+type ExposedFunction = func(args ...interface{}) interface{}
+
+// BindingCallFunction represents the func signature of an exposed binding call func
+type BindingCallFunction func(source *BindingSource, args ...interface{}) interface{}
+
+func (b *bindingCallImpl) Call(f BindingCallFunction) {
+ defer func() {
+ if r := recover(); r != nil {
+ if _, err := b.channel.Send("reject", map[string]interface{}{
+ "error": serializeError(r.(error)),
+ }); err != nil {
+ logger.Error("could not reject BindingCall", "error", err)
+ }
+ }
+ }()
+
+ frame := fromChannel(b.initializer["frame"]).(*frameImpl)
+ source := &BindingSource{
+ Context: frame.Page().Context(),
+ Page: frame.Page(),
+ Frame: frame,
+ }
+ var result interface{}
+ if handle, ok := b.initializer["handle"]; ok {
+ result = f(source, fromChannel(handle))
+ } else {
+ initializerArgs := b.initializer["args"].([]interface{})
+ funcArgs := []interface{}{}
+ for i := 0; i < len(initializerArgs); i++ {
+ funcArgs = append(funcArgs, parseResult(initializerArgs[i]))
+ }
+ result = f(source, funcArgs...)
+ }
+ _, err := b.channel.Send("resolve", map[string]interface{}{
+ "result": serializeArgument(result),
+ })
+ if err != nil {
+ logger.Error("could not resolve BindingCall", "error", err)
+ }
+}
+
+func serializeError(err error) map[string]interface{} {
+ st := stack.Trace().TrimRuntime()
+ if len(st) == 0 { // https://github.com/go-stack/stack/issues/27
+ st = stack.Trace()
+ }
+ return map[string]interface{}{
+ "error": &Error{
+ Name: "Playwright for Go Error",
+ Message: err.Error(),
+ Stack: strings.ReplaceAll(strings.TrimFunc(fmt.Sprintf("%+v", st), func(r rune) bool {
+ return r == '[' || r == ']'
+ }), " ", "\n"),
+ },
+ }
+}
+
+func newBindingCall(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *bindingCallImpl {
+ bt := &bindingCallImpl{}
+ bt.createChannelOwner(bt, parent, objectType, guid, initializer)
+ return bt
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/browser.go b/vendor/github.com/playwright-community/playwright-go/browser.go
new file mode 100644
index 0000000..c87540a
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/browser.go
@@ -0,0 +1,274 @@
+package playwright
+
+import (
+ "encoding/base64"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "os"
+ "path/filepath"
+)
+
+type browserImpl struct {
+ channelOwner
+ isConnected bool
+ shouldCloseConnectionOnClose bool
+ contexts []BrowserContext
+ browserType BrowserType
+ chromiumTracingPath *string
+ closeReason *string
+}
+
+func (b *browserImpl) BrowserType() BrowserType {
+ return b.browserType
+}
+
+func (b *browserImpl) IsConnected() bool {
+ b.RLock()
+ defer b.RUnlock()
+ return b.isConnected
+}
+
+func (b *browserImpl) NewContext(options ...BrowserNewContextOptions) (BrowserContext, error) {
+ overrides := map[string]interface{}{}
+ option := BrowserNewContextOptions{}
+ if len(options) == 1 {
+ option = options[0]
+ }
+ if option.AcceptDownloads != nil {
+ if *option.AcceptDownloads {
+ overrides["acceptDownloads"] = "accept"
+ } else {
+ overrides["acceptDownloads"] = "deny"
+ }
+ options[0].AcceptDownloads = nil
+ }
+ if option.ExtraHttpHeaders != nil {
+ overrides["extraHTTPHeaders"] = serializeMapToNameAndValue(options[0].ExtraHttpHeaders)
+ options[0].ExtraHttpHeaders = nil
+ }
+ if option.ClientCertificates != nil {
+ certs, err := transformClientCertificate(option.ClientCertificates)
+ if err != nil {
+ return nil, err
+ }
+ overrides["clientCertificates"] = certs
+ options[0].ClientCertificates = nil
+ }
+ if option.StorageStatePath != nil {
+ var storageState *OptionalStorageState
+ storageString, err := os.ReadFile(*options[0].StorageStatePath)
+ if err != nil {
+ return nil, fmt.Errorf("could not read storage state file: %w", err)
+ }
+ err = json.Unmarshal(storageString, &storageState)
+ if err != nil {
+ return nil, fmt.Errorf("could not parse storage state file: %w", err)
+ }
+ options[0].StorageState = storageState
+ options[0].StorageStatePath = nil
+ }
+ if option.NoViewport != nil && *options[0].NoViewport {
+ overrides["noDefaultViewport"] = true
+ options[0].NoViewport = nil
+ }
+ if option.RecordHarPath != nil {
+ overrides["recordHar"] = prepareRecordHarOptions(recordHarInputOptions{
+ Path: *options[0].RecordHarPath,
+ URL: options[0].RecordHarURLFilter,
+ Mode: options[0].RecordHarMode,
+ Content: options[0].RecordHarContent,
+ OmitContent: options[0].RecordHarOmitContent,
+ })
+ options[0].RecordHarPath = nil
+ options[0].RecordHarURLFilter = nil
+ options[0].RecordHarMode = nil
+ options[0].RecordHarContent = nil
+ options[0].RecordHarOmitContent = nil
+ }
+ channel, err := b.channel.Send("newContext", options, overrides)
+ if err != nil {
+ return nil, err
+ }
+ context := fromChannel(channel).(*browserContextImpl)
+ context.browser = b
+ b.browserType.(*browserTypeImpl).didCreateContext(context, &option, nil)
+ return context, nil
+}
+
+func (b *browserImpl) NewPage(options ...BrowserNewPageOptions) (Page, error) {
+ opts := make([]BrowserNewContextOptions, 0)
+ if len(options) == 1 {
+ opts = append(opts, BrowserNewContextOptions(options[0]))
+ }
+ context, err := b.NewContext(opts...)
+ if err != nil {
+ return nil, err
+ }
+ page, err := context.NewPage()
+ if err != nil {
+ return nil, err
+ }
+ page.(*pageImpl).ownedContext = context
+ context.(*browserContextImpl).ownedPage = page
+ return page, nil
+}
+
+func (b *browserImpl) NewBrowserCDPSession() (CDPSession, error) {
+ channel, err := b.channel.Send("newBrowserCDPSession")
+ if err != nil {
+ return nil, err
+ }
+
+ cdpSession := fromChannel(channel).(*cdpSessionImpl)
+
+ return cdpSession, nil
+}
+
+func (b *browserImpl) Contexts() []BrowserContext {
+ b.Lock()
+ defer b.Unlock()
+ return b.contexts
+}
+
+func (b *browserImpl) Close(options ...BrowserCloseOptions) (err error) {
+ if len(options) == 1 {
+ b.closeReason = options[0].Reason
+ }
+
+ if b.shouldCloseConnectionOnClose {
+ err = b.connection.Stop()
+ } else if b.closeReason != nil {
+ _, err = b.channel.Send("close", map[string]interface{}{
+ "reason": b.closeReason,
+ })
+ } else {
+ _, err = b.channel.Send("close")
+ }
+ if err != nil && !errors.Is(err, ErrTargetClosed) {
+ return fmt.Errorf("close browser failed: %w", err)
+ }
+ return nil
+}
+
+func (b *browserImpl) Version() string {
+ return b.initializer["version"].(string)
+}
+
+func (b *browserImpl) StartTracing(options ...BrowserStartTracingOptions) error {
+ overrides := map[string]interface{}{}
+ option := BrowserStartTracingOptions{}
+ if len(options) == 1 {
+ option = options[0]
+ }
+ if option.Page != nil {
+ overrides["page"] = option.Page.(*pageImpl).channel
+ option.Page = nil
+ }
+ if option.Path != nil {
+ b.chromiumTracingPath = option.Path
+ option.Path = nil
+ }
+ _, err := b.channel.Send("startTracing", option, overrides)
+ return err
+}
+
+func (b *browserImpl) StopTracing() ([]byte, error) {
+ channel, err := b.channel.Send("stopTracing")
+ if err != nil {
+ return nil, err
+ }
+ artifact := fromChannel(channel).(*artifactImpl)
+ binary, err := artifact.ReadIntoBuffer()
+ if err != nil {
+ return nil, err
+ }
+ err = artifact.Delete()
+ if err != nil {
+ return binary, err
+ }
+ if b.chromiumTracingPath != nil {
+ err := os.MkdirAll(filepath.Dir(*b.chromiumTracingPath), 0o777)
+ if err != nil {
+ return binary, err
+ }
+ err = os.WriteFile(*b.chromiumTracingPath, binary, 0o644)
+ if err != nil {
+ return binary, err
+ }
+ }
+ return binary, nil
+}
+
+func (b *browserImpl) onClose() {
+ b.Lock()
+ if b.isConnected {
+ b.isConnected = false
+ b.Unlock()
+ b.Emit("disconnected", b)
+ return
+ }
+ b.Unlock()
+}
+
+func (b *browserImpl) OnDisconnected(fn func(Browser)) {
+ b.On("disconnected", fn)
+}
+
+func newBrowser(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *browserImpl {
+ b := &browserImpl{
+ isConnected: true,
+ contexts: make([]BrowserContext, 0),
+ }
+ b.createChannelOwner(b, parent, objectType, guid, initializer)
+ // convert parent to *browserTypeImpl
+ b.browserType = newBrowserType(parent.parent, parent.objectType, parent.guid, parent.initializer)
+ b.channel.On("close", b.onClose)
+ return b
+}
+
+func transformClientCertificate(clientCertificates []ClientCertificate) ([]map[string]interface{}, error) {
+ results := make([]map[string]interface{}, 0)
+
+ for _, cert := range clientCertificates {
+ data := map[string]interface{}{
+ "origin": cert.Origin,
+ "passphrase": cert.Passphrase,
+ }
+ if len(cert.Cert) > 0 {
+ data["cert"] = base64.StdEncoding.EncodeToString(cert.Cert)
+ } else if cert.CertPath != nil {
+ content, err := os.ReadFile(*cert.CertPath)
+ if err != nil {
+ return nil, err
+ }
+ data["cert"] = base64.StdEncoding.EncodeToString(content)
+ }
+
+ if len(cert.Key) > 0 {
+ data["key"] = base64.StdEncoding.EncodeToString(cert.Key)
+ } else if cert.KeyPath != nil {
+ content, err := os.ReadFile(*cert.KeyPath)
+ if err != nil {
+ return nil, err
+ }
+ data["key"] = base64.StdEncoding.EncodeToString(content)
+ }
+
+ if len(cert.Pfx) > 0 {
+ data["pfx"] = base64.StdEncoding.EncodeToString(cert.Pfx)
+ } else if cert.PfxPath != nil {
+ content, err := os.ReadFile(*cert.PfxPath)
+ if err != nil {
+ return nil, err
+ }
+ data["pfx"] = base64.StdEncoding.EncodeToString(content)
+ }
+
+ results = append(results, data)
+ }
+ if len(results) == 0 {
+ return nil, nil
+ }
+ return results, nil
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/browser_context.go b/vendor/github.com/playwright-community/playwright-go/browser_context.go
new file mode 100644
index 0000000..1d420d3
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/browser_context.go
@@ -0,0 +1,914 @@
+package playwright
+
+import (
+ "encoding/json"
+ "errors"
+ "fmt"
+ "os"
+ "regexp"
+ "slices"
+ "strings"
+ "sync"
+
+ "github.com/playwright-community/playwright-go/internal/safe"
+)
+
+type browserContextImpl struct {
+ channelOwner
+ timeoutSettings *timeoutSettings
+ closeWasCalled bool
+ options *BrowserNewContextOptions
+ pages []Page
+ routes []*routeHandlerEntry
+ webSocketRoutes []*webSocketRouteHandler
+ ownedPage Page
+ browser *browserImpl
+ serviceWorkers []Worker
+ backgroundPages []Page
+ bindings *safe.SyncMap[string, BindingCallFunction]
+ tracing *tracingImpl
+ request *apiRequestContextImpl
+ harRecorders map[string]harRecordingMetadata
+ closed chan struct{}
+ closeReason *string
+ harRouters []*harRouter
+ clock Clock
+}
+
+func (b *browserContextImpl) Clock() Clock {
+ return b.clock
+}
+
+func (b *browserContextImpl) SetDefaultNavigationTimeout(timeout float64) {
+ b.setDefaultNavigationTimeoutImpl(&timeout)
+}
+
+func (b *browserContextImpl) setDefaultNavigationTimeoutImpl(timeout *float64) {
+ b.timeoutSettings.SetDefaultNavigationTimeout(timeout)
+ b.channel.SendNoReplyInternal("setDefaultNavigationTimeoutNoReply", map[string]interface{}{
+ "timeout": timeout,
+ })
+}
+
+func (b *browserContextImpl) SetDefaultTimeout(timeout float64) {
+ b.setDefaultTimeoutImpl(&timeout)
+}
+
+func (b *browserContextImpl) setDefaultTimeoutImpl(timeout *float64) {
+ b.timeoutSettings.SetDefaultTimeout(timeout)
+ b.channel.SendNoReplyInternal("setDefaultTimeoutNoReply", map[string]interface{}{
+ "timeout": timeout,
+ })
+}
+
+func (b *browserContextImpl) Pages() []Page {
+ b.Lock()
+ defer b.Unlock()
+ return b.pages
+}
+
+func (b *browserContextImpl) Browser() Browser {
+ return b.browser
+}
+
+func (b *browserContextImpl) Tracing() Tracing {
+ return b.tracing
+}
+
+func (b *browserContextImpl) NewCDPSession(page interface{}) (CDPSession, error) {
+ params := map[string]interface{}{}
+
+ if p, ok := page.(*pageImpl); ok {
+ params["page"] = p.channel
+ } else if f, ok := page.(*frameImpl); ok {
+ params["frame"] = f.channel
+ } else {
+ return nil, fmt.Errorf("not page or frame: %v", page)
+ }
+
+ channel, err := b.channel.Send("newCDPSession", params)
+ if err != nil {
+ return nil, err
+ }
+
+ cdpSession := fromChannel(channel).(*cdpSessionImpl)
+
+ return cdpSession, nil
+}
+
+func (b *browserContextImpl) NewPage() (Page, error) {
+ if b.ownedPage != nil {
+ return nil, errors.New("Please use browser.NewContext()")
+ }
+ channel, err := b.channel.Send("newPage")
+ if err != nil {
+ return nil, err
+ }
+ return fromChannel(channel).(*pageImpl), nil
+}
+
+func (b *browserContextImpl) Cookies(urls ...string) ([]Cookie, error) {
+ result, err := b.channel.Send("cookies", map[string]interface{}{
+ "urls": urls,
+ })
+ if err != nil {
+ return nil, err
+ }
+ cookies := make([]Cookie, len(result.([]interface{})))
+ for i, item := range result.([]interface{}) {
+ cookie := &Cookie{}
+ remapMapToStruct(item, cookie)
+ cookies[i] = *cookie
+ }
+ return cookies, nil
+}
+
+func (b *browserContextImpl) AddCookies(cookies []OptionalCookie) error {
+ _, err := b.channel.Send("addCookies", map[string]interface{}{
+ "cookies": cookies,
+ })
+ return err
+}
+
+func (b *browserContextImpl) ClearCookies(options ...BrowserContextClearCookiesOptions) error {
+ params := map[string]interface{}{}
+ if len(options) == 1 {
+ if options[0].Domain != nil {
+ switch t := options[0].Domain.(type) {
+ case string:
+ params["domain"] = t
+ case *string:
+ params["domain"] = t
+ case *regexp.Regexp:
+ pattern, flag := convertRegexp(t)
+ params["domainRegexSource"] = pattern
+ params["domainRegexFlags"] = flag
+ default:
+ return errors.New("invalid type for domain, expected string or *regexp.Regexp")
+ }
+ }
+ if options[0].Name != nil {
+ switch t := options[0].Name.(type) {
+ case string:
+ params["name"] = t
+ case *string:
+ params["name"] = t
+ case *regexp.Regexp:
+ pattern, flag := convertRegexp(t)
+ params["nameRegexSource"] = pattern
+ params["nameRegexFlags"] = flag
+ default:
+ return errors.New("invalid type for name, expected string or *regexp.Regexp")
+ }
+ }
+ if options[0].Path != nil {
+ switch t := options[0].Path.(type) {
+ case string:
+ params["path"] = t
+ case *string:
+ params["path"] = t
+ case *regexp.Regexp:
+ pattern, flag := convertRegexp(t)
+ params["pathRegexSource"] = pattern
+ params["pathRegexFlags"] = flag
+ default:
+ return errors.New("invalid type for path, expected string or *regexp.Regexp")
+ }
+ }
+ }
+ _, err := b.channel.Send("clearCookies", params)
+ return err
+}
+
+func (b *browserContextImpl) GrantPermissions(permissions []string, options ...BrowserContextGrantPermissionsOptions) error {
+ _, err := b.channel.Send("grantPermissions", map[string]interface{}{
+ "permissions": permissions,
+ }, options)
+ return err
+}
+
+func (b *browserContextImpl) ClearPermissions() error {
+ _, err := b.channel.Send("clearPermissions")
+ return err
+}
+
+func (b *browserContextImpl) SetGeolocation(geolocation *Geolocation) error {
+ _, err := b.channel.Send("setGeolocation", map[string]interface{}{
+ "geolocation": geolocation,
+ })
+ return err
+}
+
+func (b *browserContextImpl) ResetGeolocation() error {
+ _, err := b.channel.Send("setGeolocation", map[string]interface{}{})
+ return err
+}
+
+func (b *browserContextImpl) SetExtraHTTPHeaders(headers map[string]string) error {
+ _, err := b.channel.Send("setExtraHTTPHeaders", map[string]interface{}{
+ "headers": serializeMapToNameAndValue(headers),
+ })
+ return err
+}
+
+func (b *browserContextImpl) SetOffline(offline bool) error {
+ _, err := b.channel.Send("setOffline", map[string]interface{}{
+ "offline": offline,
+ })
+ return err
+}
+
+func (b *browserContextImpl) AddInitScript(script Script) error {
+ var source string
+ if script.Content != nil {
+ source = *script.Content
+ }
+ if script.Path != nil {
+ content, err := os.ReadFile(*script.Path)
+ if err != nil {
+ return err
+ }
+ source = string(content)
+ }
+ _, err := b.channel.Send("addInitScript", map[string]interface{}{
+ "source": source,
+ })
+ return err
+}
+
+func (b *browserContextImpl) ExposeBinding(name string, binding BindingCallFunction, handle ...bool) error {
+ needsHandle := false
+ if len(handle) == 1 {
+ needsHandle = handle[0]
+ }
+ for _, page := range b.Pages() {
+ if _, ok := page.(*pageImpl).bindings.Load(name); ok {
+ return fmt.Errorf("Function '%s' has been already registered in one of the pages", name)
+ }
+ }
+ if _, ok := b.bindings.Load(name); ok {
+ return fmt.Errorf("Function '%s' has been already registered", name)
+ }
+ _, err := b.channel.Send("exposeBinding", map[string]interface{}{
+ "name": name,
+ "needsHandle": needsHandle,
+ })
+ if err != nil {
+ return err
+ }
+ b.bindings.Store(name, binding)
+ return err
+}
+
+func (b *browserContextImpl) ExposeFunction(name string, binding ExposedFunction) error {
+ return b.ExposeBinding(name, func(source *BindingSource, args ...interface{}) interface{} {
+ return binding(args...)
+ })
+}
+
+func (b *browserContextImpl) Route(url interface{}, handler routeHandler, times ...int) error {
+ b.Lock()
+ defer b.Unlock()
+ b.routes = slices.Insert(b.routes, 0, newRouteHandlerEntry(newURLMatcher(url, b.options.BaseURL), handler, times...))
+ return b.updateInterceptionPatterns()
+}
+
+func (b *browserContextImpl) Unroute(url interface{}, handlers ...routeHandler) error {
+ removed, remaining, err := unroute(b.routes, url, handlers...)
+ if err != nil {
+ return err
+ }
+ return b.unrouteInternal(removed, remaining, UnrouteBehaviorDefault)
+}
+
+func (b *browserContextImpl) unrouteInternal(removed []*routeHandlerEntry, remaining []*routeHandlerEntry, behavior *UnrouteBehavior) error {
+ b.Lock()
+ defer b.Unlock()
+ b.routes = remaining
+ if err := b.updateInterceptionPatterns(); err != nil {
+ return err
+ }
+ if behavior == nil || behavior == UnrouteBehaviorDefault {
+ return nil
+ }
+ wg := &sync.WaitGroup{}
+ for _, entry := range removed {
+ wg.Add(1)
+ go func(entry *routeHandlerEntry) {
+ defer wg.Done()
+ entry.Stop(string(*behavior))
+ }(entry)
+ }
+ wg.Wait()
+ return nil
+}
+
+func (b *browserContextImpl) UnrouteAll(options ...BrowserContextUnrouteAllOptions) error {
+ var behavior *UnrouteBehavior
+ if len(options) == 1 {
+ behavior = options[0].Behavior
+ }
+ defer b.disposeHarRouters()
+ return b.unrouteInternal(b.routes, []*routeHandlerEntry{}, behavior)
+}
+
+func (b *browserContextImpl) disposeHarRouters() {
+ for _, router := range b.harRouters {
+ router.dispose()
+ }
+ b.harRouters = make([]*harRouter, 0)
+}
+
+func (b *browserContextImpl) Request() APIRequestContext {
+ return b.request
+}
+
+func (b *browserContextImpl) RouteFromHAR(har string, options ...BrowserContextRouteFromHAROptions) error {
+ opt := BrowserContextRouteFromHAROptions{}
+ if len(options) == 1 {
+ opt = options[0]
+ }
+ if opt.Update != nil && *opt.Update {
+ var updateContent *HarContentPolicy
+ switch opt.UpdateContent {
+ case RouteFromHarUpdateContentPolicyAttach:
+ updateContent = HarContentPolicyAttach
+ case RouteFromHarUpdateContentPolicyEmbed:
+ updateContent = HarContentPolicyEmbed
+ }
+ return b.recordIntoHar(har, browserContextRecordIntoHarOptions{
+ URL: opt.URL,
+ UpdateContent: updateContent,
+ UpdateMode: opt.UpdateMode,
+ })
+ }
+ notFound := opt.NotFound
+ if notFound == nil {
+ notFound = HarNotFoundAbort
+ }
+ router := newHarRouter(b.connection.localUtils, har, *notFound, opt.URL)
+ b.harRouters = append(b.harRouters, router)
+ return router.addContextRoute(b)
+}
+
+func (b *browserContextImpl) WaitForEvent(event string, options ...BrowserContextWaitForEventOptions) (interface{}, error) {
+ return b.waiterForEvent(event, options...).Wait()
+}
+
+func (b *browserContextImpl) waiterForEvent(event string, options ...BrowserContextWaitForEventOptions) *waiter {
+ timeout := b.timeoutSettings.Timeout()
+ var predicate interface{} = nil
+ if len(options) == 1 {
+ if options[0].Timeout != nil {
+ timeout = *options[0].Timeout
+ }
+ predicate = options[0].Predicate
+ }
+ waiter := newWaiter().WithTimeout(timeout)
+ waiter.RejectOnEvent(b, "close", ErrTargetClosed)
+ return waiter.WaitForEvent(b, event, predicate)
+}
+
+func (b *browserContextImpl) ExpectConsoleMessage(cb func() error, options ...BrowserContextExpectConsoleMessageOptions) (ConsoleMessage, error) {
+ var w *waiter
+ if len(options) == 1 {
+ w = b.waiterForEvent("console", BrowserContextWaitForEventOptions{
+ Predicate: options[0].Predicate,
+ Timeout: options[0].Timeout,
+ })
+ } else {
+ w = b.waiterForEvent("console")
+ }
+ ret, err := w.RunAndWait(cb)
+ if err != nil {
+ return nil, err
+ }
+ return ret.(ConsoleMessage), nil
+}
+
+func (b *browserContextImpl) ExpectEvent(event string, cb func() error, options ...BrowserContextExpectEventOptions) (interface{}, error) {
+ if len(options) == 1 {
+ return b.waiterForEvent(event, BrowserContextWaitForEventOptions(options[0])).RunAndWait(cb)
+ }
+ return b.waiterForEvent(event).RunAndWait(cb)
+}
+
+func (b *browserContextImpl) ExpectPage(cb func() error, options ...BrowserContextExpectPageOptions) (Page, error) {
+ var w *waiter
+ if len(options) == 1 {
+ w = b.waiterForEvent("page", BrowserContextWaitForEventOptions{
+ Predicate: options[0].Predicate,
+ Timeout: options[0].Timeout,
+ })
+ } else {
+ w = b.waiterForEvent("page")
+ }
+ ret, err := w.RunAndWait(cb)
+ if err != nil {
+ return nil, err
+ }
+ return ret.(Page), nil
+}
+
+func (b *browserContextImpl) Close(options ...BrowserContextCloseOptions) error {
+ if b.closeWasCalled {
+ return nil
+ }
+ if len(options) == 1 {
+ b.closeReason = options[0].Reason
+ }
+ b.closeWasCalled = true
+
+ _, err := b.channel.connection.WrapAPICall(func() (interface{}, error) {
+ return nil, b.request.Dispose(APIRequestContextDisposeOptions{
+ Reason: b.closeReason,
+ })
+ }, true)
+ if err != nil {
+ return err
+ }
+
+ innerClose := func() (interface{}, error) {
+ for harId, harMetaData := range b.harRecorders {
+ overrides := map[string]interface{}{}
+ if harId != "" {
+ overrides["harId"] = harId
+ }
+ response, err := b.channel.Send("harExport", overrides)
+ if err != nil {
+ return nil, err
+ }
+ artifact := fromChannel(response).(*artifactImpl)
+ // Server side will compress artifact if content is attach or if file is .zip.
+ needCompressed := strings.HasSuffix(strings.ToLower(harMetaData.Path), ".zip")
+ if !needCompressed && harMetaData.Content == HarContentPolicyAttach {
+ tmpPath := harMetaData.Path + ".tmp"
+ if err := artifact.SaveAs(tmpPath); err != nil {
+ return nil, err
+ }
+ err = b.connection.localUtils.HarUnzip(tmpPath, harMetaData.Path)
+ if err != nil {
+ return nil, err
+ }
+ } else {
+ if err := artifact.SaveAs(harMetaData.Path); err != nil {
+ return nil, err
+ }
+ }
+ if err := artifact.Delete(); err != nil {
+ return nil, err
+ }
+ }
+ return nil, nil
+ }
+
+ _, err = b.channel.connection.WrapAPICall(innerClose, true)
+ if err != nil {
+ return err
+ }
+
+ _, err = b.channel.Send("close", map[string]interface{}{
+ "reason": b.closeReason,
+ })
+ if err != nil {
+ return err
+ }
+ <-b.closed
+ return err
+}
+
+type browserContextRecordIntoHarOptions struct {
+ Page Page
+ URL interface{}
+ UpdateContent *HarContentPolicy
+ UpdateMode *HarMode
+}
+
+func (b *browserContextImpl) recordIntoHar(har string, options ...browserContextRecordIntoHarOptions) error {
+ overrides := map[string]interface{}{}
+ harOptions := recordHarInputOptions{
+ Path: har,
+ Content: HarContentPolicyAttach,
+ Mode: HarModeMinimal,
+ }
+ if len(options) == 1 {
+ if options[0].UpdateContent != nil {
+ harOptions.Content = options[0].UpdateContent
+ }
+ if options[0].UpdateMode != nil {
+ harOptions.Mode = options[0].UpdateMode
+ }
+ harOptions.URL = options[0].URL
+ overrides["options"] = prepareRecordHarOptions(harOptions)
+ if options[0].Page != nil {
+ overrides["page"] = options[0].Page.(*pageImpl).channel
+ }
+ }
+ harId, err := b.channel.Send("harStart", overrides)
+ if err != nil {
+ return err
+ }
+ b.harRecorders[harId.(string)] = harRecordingMetadata{
+ Path: har,
+ Content: harOptions.Content,
+ }
+ return nil
+}
+
+func (b *browserContextImpl) StorageState(paths ...string) (*StorageState, error) {
+ result, err := b.channel.SendReturnAsDict("storageState")
+ if err != nil {
+ return nil, err
+ }
+ if len(paths) == 1 {
+ file, err := os.Create(paths[0])
+ if err != nil {
+ return nil, err
+ }
+ if err := json.NewEncoder(file).Encode(result); err != nil {
+ return nil, err
+ }
+ if err := file.Close(); err != nil {
+ return nil, err
+ }
+ }
+ var storageState StorageState
+ remapMapToStruct(result, &storageState)
+ return &storageState, nil
+}
+
+func (b *browserContextImpl) onBinding(binding *bindingCallImpl) {
+ function, ok := b.bindings.Load(binding.initializer["name"].(string))
+ if !ok || function == nil {
+ return
+ }
+ go binding.Call(function)
+}
+
+func (b *browserContextImpl) onClose() {
+ if b.browser != nil {
+ contexts := make([]BrowserContext, 0)
+ b.browser.Lock()
+ for _, context := range b.browser.contexts {
+ if context != b {
+ contexts = append(contexts, context)
+ }
+ }
+ b.browser.contexts = contexts
+ b.browser.Unlock()
+ }
+ b.disposeHarRouters()
+ b.Emit("close", b)
+}
+
+func (b *browserContextImpl) onPage(page Page) {
+ b.Lock()
+ b.pages = append(b.pages, page)
+ b.Unlock()
+ b.Emit("page", page)
+ opener, _ := page.Opener()
+ if opener != nil && !opener.IsClosed() {
+ opener.Emit("popup", page)
+ }
+}
+
+func (b *browserContextImpl) onRoute(route *routeImpl) {
+ b.Lock()
+ route.context = b
+ page := route.Request().(*requestImpl).safePage()
+ routes := make([]*routeHandlerEntry, len(b.routes))
+ copy(routes, b.routes)
+ b.Unlock()
+
+ checkInterceptionIfNeeded := func() {
+ b.Lock()
+ defer b.Unlock()
+ if len(b.routes) == 0 {
+ _, err := b.connection.WrapAPICall(func() (interface{}, error) {
+ err := b.updateInterceptionPatterns()
+ return nil, err
+ }, true)
+ if err != nil {
+ logger.Error("could not update interception patterns", "error", err)
+ }
+ }
+ }
+
+ url := route.Request().URL()
+ for _, handlerEntry := range routes {
+ // If the page or the context was closed we stall all requests right away.
+ if (page != nil && page.closeWasCalled) || b.closeWasCalled {
+ return
+ }
+ if !handlerEntry.Matches(url) {
+ continue
+ }
+ if !slices.ContainsFunc(b.routes, func(entry *routeHandlerEntry) bool {
+ return entry == handlerEntry
+ }) {
+ continue
+ }
+ if handlerEntry.WillExceed() {
+ b.routes = slices.DeleteFunc(b.routes, func(rhe *routeHandlerEntry) bool {
+ return rhe == handlerEntry
+ })
+ }
+ handled := handlerEntry.Handle(route)
+ checkInterceptionIfNeeded()
+ yes := <-handled
+ if yes {
+ return
+ }
+ }
+ // If the page is closed or unrouteAll() was called without waiting and interception disabled,
+ // the method will throw an error - silence it.
+ _ = route.internalContinue(true)
+}
+
+func (b *browserContextImpl) updateInterceptionPatterns() error {
+ patterns := prepareInterceptionPatterns(b.routes)
+ _, err := b.channel.Send("setNetworkInterceptionPatterns", map[string]interface{}{
+ "patterns": patterns,
+ })
+ return err
+}
+
+func (b *browserContextImpl) pause() <-chan error {
+ ret := make(chan error, 1)
+ go func() {
+ _, err := b.channel.Send("pause")
+ ret <- err
+ }()
+ return ret
+}
+
+func (b *browserContextImpl) onBackgroundPage(ev map[string]interface{}) {
+ b.Lock()
+ p := fromChannel(ev["page"]).(*pageImpl)
+ p.browserContext = b
+ b.backgroundPages = append(b.backgroundPages, p)
+ b.Unlock()
+ b.Emit("backgroundpage", p)
+}
+
+func (b *browserContextImpl) onServiceWorker(worker *workerImpl) {
+ worker.context = b
+ b.serviceWorkers = append(b.serviceWorkers, worker)
+ b.Emit("serviceworker", worker)
+}
+
+func (b *browserContextImpl) setOptions(options *BrowserNewContextOptions, tracesDir *string) {
+ if options == nil {
+ options = &BrowserNewContextOptions{}
+ }
+ b.options = options
+ if b.options != nil && b.options.RecordHarPath != nil {
+ b.harRecorders[""] = harRecordingMetadata{
+ Path: *b.options.RecordHarPath,
+ Content: b.options.RecordHarContent,
+ }
+ }
+ if tracesDir != nil {
+ b.tracing.tracesDir = *tracesDir
+ }
+}
+
+func (b *browserContextImpl) BackgroundPages() []Page {
+ b.Lock()
+ defer b.Unlock()
+ return b.backgroundPages
+}
+
+func (b *browserContextImpl) ServiceWorkers() []Worker {
+ b.Lock()
+ defer b.Unlock()
+ return b.serviceWorkers
+}
+
+func (b *browserContextImpl) OnBackgroundPage(fn func(Page)) {
+ b.On("backgroundpage", fn)
+}
+
+func (b *browserContextImpl) OnClose(fn func(BrowserContext)) {
+ b.On("close", fn)
+}
+
+func (b *browserContextImpl) OnConsole(fn func(ConsoleMessage)) {
+ b.On("console", fn)
+}
+
+func (b *browserContextImpl) OnDialog(fn func(Dialog)) {
+ b.On("dialog", fn)
+}
+
+func (b *browserContextImpl) OnPage(fn func(Page)) {
+ b.On("page", fn)
+}
+
+func (b *browserContextImpl) OnRequest(fn func(Request)) {
+ b.On("request", fn)
+}
+
+func (b *browserContextImpl) OnRequestFailed(fn func(Request)) {
+ b.On("requestfailed", fn)
+}
+
+func (b *browserContextImpl) OnRequestFinished(fn func(Request)) {
+ b.On("requestfinished", fn)
+}
+
+func (b *browserContextImpl) OnResponse(fn func(Response)) {
+ b.On("response", fn)
+}
+
+func (b *browserContextImpl) OnWebError(fn func(WebError)) {
+ b.On("weberror", fn)
+}
+
+func (b *browserContextImpl) RouteWebSocket(url interface{}, handler func(WebSocketRoute)) error {
+ b.Lock()
+ defer b.Unlock()
+ b.webSocketRoutes = slices.Insert(b.webSocketRoutes, 0, newWebSocketRouteHandler(newURLMatcher(url, b.options.BaseURL), handler))
+
+ return b.updateWebSocketInterceptionPatterns()
+}
+
+func (b *browserContextImpl) onWebSocketRoute(wr WebSocketRoute) {
+ b.Lock()
+ index := slices.IndexFunc(b.webSocketRoutes, func(r *webSocketRouteHandler) bool {
+ return r.Matches(wr.URL())
+ })
+ if index == -1 {
+ b.Unlock()
+ _, err := wr.ConnectToServer()
+ if err != nil {
+ logger.Error("could not connect to WebSocket server", "error", err)
+ }
+ return
+ }
+ handler := b.webSocketRoutes[index]
+ b.Unlock()
+ handler.Handle(wr)
+}
+
+func (b *browserContextImpl) updateWebSocketInterceptionPatterns() error {
+ patterns := prepareWebSocketRouteHandlerInterceptionPatterns(b.webSocketRoutes)
+ _, err := b.channel.Send("setWebSocketInterceptionPatterns", map[string]interface{}{
+ "patterns": patterns,
+ })
+ return err
+}
+
+func (b *browserContextImpl) effectiveCloseReason() *string {
+ b.Lock()
+ defer b.Unlock()
+ if b.closeReason != nil {
+ return b.closeReason
+ }
+ if b.browser != nil {
+ return b.browser.closeReason
+ }
+ return nil
+}
+
+func newBrowserContext(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *browserContextImpl {
+ bt := &browserContextImpl{
+ timeoutSettings: newTimeoutSettings(nil),
+ pages: make([]Page, 0),
+ backgroundPages: make([]Page, 0),
+ routes: make([]*routeHandlerEntry, 0),
+ bindings: safe.NewSyncMap[string, BindingCallFunction](),
+ harRecorders: make(map[string]harRecordingMetadata),
+ closed: make(chan struct{}, 1),
+ harRouters: make([]*harRouter, 0),
+ }
+ bt.createChannelOwner(bt, parent, objectType, guid, initializer)
+ if parent.objectType == "Browser" {
+ bt.browser = fromChannel(parent.channel).(*browserImpl)
+ bt.browser.contexts = append(bt.browser.contexts, bt)
+ }
+ bt.tracing = fromChannel(initializer["tracing"]).(*tracingImpl)
+ bt.request = fromChannel(initializer["requestContext"]).(*apiRequestContextImpl)
+ bt.clock = newClock(bt)
+ bt.channel.On("bindingCall", func(params map[string]interface{}) {
+ bt.onBinding(fromChannel(params["binding"]).(*bindingCallImpl))
+ })
+
+ bt.channel.On("close", bt.onClose)
+ bt.channel.On("page", func(payload map[string]interface{}) {
+ bt.onPage(fromChannel(payload["page"]).(*pageImpl))
+ })
+ bt.channel.On("route", func(params map[string]interface{}) {
+ bt.channel.CreateTask(func() {
+ bt.onRoute(fromChannel(params["route"]).(*routeImpl))
+ })
+ })
+ bt.channel.On("webSocketRoute", func(params map[string]interface{}) {
+ bt.channel.CreateTask(func() {
+ bt.onWebSocketRoute(fromChannel(params["webSocketRoute"]).(*webSocketRouteImpl))
+ })
+ })
+ bt.channel.On("backgroundPage", bt.onBackgroundPage)
+ bt.channel.On("serviceWorker", func(params map[string]interface{}) {
+ bt.onServiceWorker(fromChannel(params["worker"]).(*workerImpl))
+ })
+ bt.channel.On("console", func(ev map[string]interface{}) {
+ message := newConsoleMessage(ev)
+ bt.Emit("console", message)
+ if message.page != nil {
+ message.page.Emit("console", message)
+ }
+ })
+ bt.channel.On("dialog", func(params map[string]interface{}) {
+ dialog := fromChannel(params["dialog"]).(*dialogImpl)
+ go func() {
+ hasListeners := bt.Emit("dialog", dialog)
+ page := dialog.page
+ if page != nil {
+ if page.Emit("dialog", dialog) {
+ hasListeners = true
+ }
+ }
+ if !hasListeners {
+ // Although we do similar handling on the server side, we still need this logic
+ // on the client side due to a possible race condition between two async calls:
+ // a) removing "dialog" listener subscription (client->server)
+ // b) actual "dialog" event (server->client)
+ if dialog.Type() == "beforeunload" {
+ _ = dialog.Accept()
+ } else {
+ _ = dialog.Dismiss()
+ }
+ }
+ }()
+ })
+ bt.channel.On(
+ "pageError", func(ev map[string]interface{}) {
+ pwErr := &Error{}
+ remapMapToStruct(ev["error"].(map[string]interface{})["error"], pwErr)
+ err := parseError(*pwErr)
+ page := fromNullableChannel(ev["page"])
+ if page != nil {
+ bt.Emit("weberror", newWebError(page.(*pageImpl), err))
+ page.(*pageImpl).Emit("pageerror", err)
+ } else {
+ bt.Emit("weberror", newWebError(nil, err))
+ }
+ },
+ )
+ bt.channel.On("request", func(ev map[string]interface{}) {
+ request := fromChannel(ev["request"]).(*requestImpl)
+ page := fromNullableChannel(ev["page"])
+ bt.Emit("request", request)
+ if page != nil {
+ page.(*pageImpl).Emit("request", request)
+ }
+ })
+ bt.channel.On("requestFailed", func(ev map[string]interface{}) {
+ request := fromChannel(ev["request"]).(*requestImpl)
+ failureText := ev["failureText"]
+ if failureText != nil {
+ request.failureText = failureText.(string)
+ }
+ page := fromNullableChannel(ev["page"])
+ request.setResponseEndTiming(ev["responseEndTiming"].(float64))
+ bt.Emit("requestfailed", request)
+ if page != nil {
+ page.(*pageImpl).Emit("requestfailed", request)
+ }
+ })
+
+ bt.channel.On("requestFinished", func(ev map[string]interface{}) {
+ request := fromChannel(ev["request"]).(*requestImpl)
+ response := fromNullableChannel(ev["response"])
+ page := fromNullableChannel(ev["page"])
+ request.setResponseEndTiming(ev["responseEndTiming"].(float64))
+ bt.Emit("requestfinished", request)
+ if page != nil {
+ page.(*pageImpl).Emit("requestfinished", request)
+ }
+ if response != nil {
+ close(response.(*responseImpl).finished)
+ }
+ })
+ bt.channel.On("response", func(ev map[string]interface{}) {
+ response := fromChannel(ev["response"]).(*responseImpl)
+ page := fromNullableChannel(ev["page"])
+ bt.Emit("response", response)
+ if page != nil {
+ page.(*pageImpl).Emit("response", response)
+ }
+ })
+ bt.Once("close", func() {
+ bt.closed <- struct{}{}
+ })
+ bt.setEventSubscriptionMapping(map[string]string{
+ "console": "console",
+ "dialog": "dialog",
+ "request": "request",
+ "response": "response",
+ "requestfinished": "requestFinished",
+ "responsefailed": "responseFailed",
+ })
+ return bt
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/browser_type.go b/vendor/github.com/playwright-community/playwright-go/browser_type.go
new file mode 100644
index 0000000..41a8b18
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/browser_type.go
@@ -0,0 +1,181 @@
+package playwright
+
+import (
+ "fmt"
+)
+
+type browserTypeImpl struct {
+ channelOwner
+ playwright *Playwright
+}
+
+func (b *browserTypeImpl) Name() string {
+ return b.initializer["name"].(string)
+}
+
+func (b *browserTypeImpl) ExecutablePath() string {
+ return b.initializer["executablePath"].(string)
+}
+
+func (b *browserTypeImpl) Launch(options ...BrowserTypeLaunchOptions) (Browser, error) {
+ overrides := map[string]interface{}{}
+ if len(options) == 1 && options[0].Env != nil {
+ overrides["env"] = serializeMapToNameAndValue(options[0].Env)
+ options[0].Env = nil
+ }
+ channel, err := b.channel.Send("launch", options, overrides)
+ if err != nil {
+ return nil, err
+ }
+ browser := fromChannel(channel).(*browserImpl)
+ b.didLaunchBrowser(browser)
+ return browser, nil
+}
+
+func (b *browserTypeImpl) LaunchPersistentContext(userDataDir string, options ...BrowserTypeLaunchPersistentContextOptions) (BrowserContext, error) {
+ overrides := map[string]interface{}{
+ "userDataDir": userDataDir,
+ }
+ option := &BrowserNewContextOptions{}
+ var tracesDir *string = nil
+ if len(options) == 1 {
+ tracesDir = options[0].TracesDir
+ err := assignStructFields(option, options[0], true)
+ if err != nil {
+ return nil, fmt.Errorf("can not convert options: %w", err)
+ }
+ if options[0].AcceptDownloads != nil {
+ if *options[0].AcceptDownloads {
+ overrides["acceptDownloads"] = "accept"
+ } else {
+ overrides["acceptDownloads"] = "deny"
+ }
+ options[0].AcceptDownloads = nil
+ }
+ if options[0].ClientCertificates != nil {
+ certs, err := transformClientCertificate(options[0].ClientCertificates)
+ if err != nil {
+ return nil, err
+ }
+ overrides["clientCertificates"] = certs
+ options[0].ClientCertificates = nil
+ }
+ if options[0].ExtraHttpHeaders != nil {
+ overrides["extraHTTPHeaders"] = serializeMapToNameAndValue(options[0].ExtraHttpHeaders)
+ options[0].ExtraHttpHeaders = nil
+ }
+ if options[0].Env != nil {
+ overrides["env"] = serializeMapToNameAndValue(options[0].Env)
+ options[0].Env = nil
+ }
+ if options[0].NoViewport != nil && *options[0].NoViewport {
+ overrides["noDefaultViewport"] = true
+ options[0].NoViewport = nil
+ }
+ if options[0].RecordHarPath != nil {
+ overrides["recordHar"] = prepareRecordHarOptions(recordHarInputOptions{
+ Path: *options[0].RecordHarPath,
+ URL: options[0].RecordHarURLFilter,
+ Mode: options[0].RecordHarMode,
+ Content: options[0].RecordHarContent,
+ OmitContent: options[0].RecordHarOmitContent,
+ })
+ options[0].RecordHarPath = nil
+ options[0].RecordHarURLFilter = nil
+ options[0].RecordHarMode = nil
+ options[0].RecordHarContent = nil
+ options[0].RecordHarOmitContent = nil
+ }
+ }
+ channel, err := b.channel.Send("launchPersistentContext", options, overrides)
+ if err != nil {
+ return nil, err
+ }
+ context := fromChannel(channel).(*browserContextImpl)
+ b.didCreateContext(context, option, tracesDir)
+ return context, nil
+}
+
+func (b *browserTypeImpl) Connect(wsEndpoint string, options ...BrowserTypeConnectOptions) (Browser, error) {
+ overrides := map[string]interface{}{
+ "wsEndpoint": wsEndpoint,
+ "headers": map[string]string{
+ "x-playwright-browser": b.Name(),
+ },
+ }
+ if len(options) == 1 {
+ if options[0].Headers != nil {
+ for k, v := range options[0].Headers {
+ overrides["headers"].(map[string]string)[k] = v
+ }
+ options[0].Headers = nil
+ }
+ }
+ localUtils := b.connection.LocalUtils()
+ pipe, err := localUtils.channel.SendReturnAsDict("connect", options, overrides)
+ if err != nil {
+ return nil, err
+ }
+ jsonPipe := fromChannel(pipe["pipe"]).(*jsonPipe)
+ connection := newConnection(jsonPipe, localUtils)
+
+ playwright, err := connection.Start()
+ if err != nil {
+ return nil, err
+ }
+ playwright.setSelectors(b.playwright.Selectors)
+ browser := fromChannel(playwright.initializer["preLaunchedBrowser"]).(*browserImpl)
+ browser.shouldCloseConnectionOnClose = true
+ pipeClosed := func() {
+ for _, context := range browser.Contexts() {
+ pages := context.Pages()
+ for _, page := range pages {
+ page.(*pageImpl).onClose()
+ }
+ context.(*browserContextImpl).onClose()
+ }
+ browser.onClose()
+ connection.cleanup()
+ }
+ jsonPipe.On("closed", pipeClosed)
+
+ b.didLaunchBrowser(browser)
+ return browser, nil
+}
+
+func (b *browserTypeImpl) ConnectOverCDP(endpointURL string, options ...BrowserTypeConnectOverCDPOptions) (Browser, error) {
+ overrides := map[string]interface{}{
+ "endpointURL": endpointURL,
+ }
+ if len(options) == 1 {
+ if options[0].Headers != nil {
+ overrides["headers"] = serializeMapToNameAndValue(options[0].Headers)
+ options[0].Headers = nil
+ }
+ }
+ response, err := b.channel.SendReturnAsDict("connectOverCDP", options, overrides)
+ if err != nil {
+ return nil, err
+ }
+ browser := fromChannel(response["browser"]).(*browserImpl)
+ b.didLaunchBrowser(browser)
+ if defaultContext, ok := response["defaultContext"]; ok {
+ context := fromChannel(defaultContext).(*browserContextImpl)
+ b.didCreateContext(context, nil, nil)
+ }
+ return browser, nil
+}
+
+func (b *browserTypeImpl) didCreateContext(context *browserContextImpl, contextOptions *BrowserNewContextOptions, tracesDir *string) {
+ context.setOptions(contextOptions, tracesDir)
+}
+
+func (b *browserTypeImpl) didLaunchBrowser(browser *browserImpl) {
+ browser.browserType = b
+}
+
+func newBrowserType(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *browserTypeImpl {
+ bt := &browserTypeImpl{}
+ bt.createChannelOwner(bt, parent, objectType, guid, initializer)
+ return bt
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/cdp_session.go b/vendor/github.com/playwright-community/playwright-go/cdp_session.go
new file mode 100644
index 0000000..e9bba82
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/cdp_session.go
@@ -0,0 +1,38 @@
+package playwright
+
+type cdpSessionImpl struct {
+ channelOwner
+}
+
+func (c *cdpSessionImpl) Detach() error {
+ _, err := c.channel.Send("detach")
+ return err
+}
+
+func (c *cdpSessionImpl) Send(method string, params map[string]interface{}) (interface{}, error) {
+ result, err := c.channel.Send("send", map[string]interface{}{
+ "method": method,
+ "params": params,
+ })
+ if err != nil {
+ return nil, err
+ }
+
+ return result, err
+}
+
+func (c *cdpSessionImpl) onEvent(params map[string]interface{}) {
+ c.Emit(params["method"].(string), params["params"])
+}
+
+func newCDPSession(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *cdpSessionImpl {
+ bt := &cdpSessionImpl{}
+
+ bt.createChannelOwner(bt, parent, objectType, guid, initializer)
+
+ bt.channel.On("event", func(params map[string]interface{}) {
+ bt.onEvent(params)
+ })
+
+ return bt
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/channel.go b/vendor/github.com/playwright-community/playwright-go/channel.go
new file mode 100644
index 0000000..b0bded4
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/channel.go
@@ -0,0 +1,92 @@
+package playwright
+
+import (
+ "encoding/json"
+ "fmt"
+)
+
+type channel struct {
+ eventEmitter
+ guid string
+ connection *connection
+ owner *channelOwner // to avoid type conversion
+ object interface{} // retain type info (for fromChannel needed)
+}
+
+func (c *channel) MarshalJSON() ([]byte, error) {
+ return json.Marshal(map[string]string{
+ "guid": c.guid,
+ })
+}
+
+// for catch errors of route handlers etc.
+func (c *channel) CreateTask(fn func()) {
+ go func() {
+ defer func() {
+ if e := recover(); e != nil {
+ err, ok := e.(error)
+ if ok {
+ c.connection.err.Set(err)
+ } else {
+ c.connection.err.Set(fmt.Errorf("%v", e))
+ }
+ }
+ }()
+ fn()
+ }()
+}
+
+func (c *channel) Send(method string, options ...interface{}) (interface{}, error) {
+ return c.connection.WrapAPICall(func() (interface{}, error) {
+ return c.innerSend(method, options...).GetResultValue()
+ }, c.owner.isInternalType)
+}
+
+func (c *channel) SendReturnAsDict(method string, options ...interface{}) (map[string]interface{}, error) {
+ ret, err := c.connection.WrapAPICall(func() (interface{}, error) {
+ return c.innerSend(method, options...).GetResult()
+ }, c.owner.isInternalType)
+ return ret.(map[string]interface{}), err
+}
+
+func (c *channel) innerSend(method string, options ...interface{}) *protocolCallback {
+ if err := c.connection.err.Get(); err != nil {
+ c.connection.err.Set(nil)
+ pc := newProtocolCallback(false, c.connection.abort)
+ pc.SetError(err)
+ return pc
+ }
+ params := transformOptions(options...)
+ return c.connection.sendMessageToServer(c.owner, method, params, false)
+}
+
+// SendNoReply ignores return value and errors
+// almost equivalent to `send(...).catch(() => {})`
+func (c *channel) SendNoReply(method string, options ...interface{}) {
+ c.innerSendNoReply(method, c.owner.isInternalType, options...)
+}
+
+func (c *channel) SendNoReplyInternal(method string, options ...interface{}) {
+ c.innerSendNoReply(method, true, options...)
+}
+
+func (c *channel) innerSendNoReply(method string, isInternal bool, options ...interface{}) {
+ params := transformOptions(options...)
+ _, err := c.connection.WrapAPICall(func() (interface{}, error) {
+ return c.connection.sendMessageToServer(c.owner, method, params, true).GetResult()
+ }, isInternal)
+ if err != nil {
+ // ignore error actively, log only for debug
+ logger.Error("SendNoReply failed", "error", err)
+ }
+}
+
+func newChannel(owner *channelOwner, object interface{}) *channel {
+ channel := &channel{
+ connection: owner.connection,
+ guid: owner.guid,
+ owner: owner,
+ object: object,
+ }
+ return channel
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/channel_owner.go b/vendor/github.com/playwright-community/playwright-go/channel_owner.go
new file mode 100644
index 0000000..5159eb2
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/channel_owner.go
@@ -0,0 +1,122 @@
+package playwright
+
+import (
+ "sync"
+)
+
+type channelOwner struct {
+ sync.RWMutex
+ eventEmitter
+ objectType string
+ guid string
+ channel *channel
+ objects map[string]*channelOwner
+ eventToSubscriptionMapping map[string]string
+ connection *connection
+ initializer map[string]interface{}
+ parent *channelOwner
+ wasCollected bool
+ isInternalType bool
+}
+
+func (c *channelOwner) dispose(reason ...string) {
+ // Clean up from parent and connection.
+ if c.parent != nil {
+ delete(c.parent.objects, c.guid)
+ }
+ c.connection.objects.Delete(c.guid)
+ if len(reason) > 0 {
+ c.wasCollected = reason[0] == "gc"
+ }
+
+ // Dispose all children.
+ for _, object := range c.objects {
+ object.dispose(reason...)
+ }
+ c.objects = make(map[string]*channelOwner)
+}
+
+func (c *channelOwner) adopt(child *channelOwner) {
+ delete(child.parent.objects, child.guid)
+ c.objects[child.guid] = child
+ child.parent = c
+}
+
+func (c *channelOwner) setEventSubscriptionMapping(mapping map[string]string) {
+ c.eventToSubscriptionMapping = mapping
+}
+
+func (c *channelOwner) updateSubscription(event string, enabled bool) {
+ protocolEvent, ok := c.eventToSubscriptionMapping[event]
+ if ok {
+ c.channel.SendNoReplyInternal("updateSubscription", map[string]interface{}{
+ "event": protocolEvent,
+ "enabled": enabled,
+ })
+ }
+}
+
+func (c *channelOwner) Once(name string, handler interface{}) {
+ c.addEvent(name, handler, true)
+}
+
+func (c *channelOwner) On(name string, handler interface{}) {
+ c.addEvent(name, handler, false)
+}
+
+func (c *channelOwner) addEvent(name string, handler interface{}, once bool) {
+ if c.ListenerCount(name) == 0 {
+ c.updateSubscription(name, true)
+ }
+ c.eventEmitter.addEvent(name, handler, once)
+}
+
+func (c *channelOwner) RemoveListener(name string, handler interface{}) {
+ c.eventEmitter.RemoveListener(name, handler)
+ if c.ListenerCount(name) == 0 {
+ c.updateSubscription(name, false)
+ }
+}
+
+func (c *channelOwner) createChannelOwner(self interface{}, parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) {
+ c.objectType = objectType
+ c.guid = guid
+ c.wasCollected = false
+ c.parent = parent
+ c.objects = make(map[string]*channelOwner)
+ c.initializer = initializer
+ if c.parent != nil {
+ c.connection = parent.connection
+ c.parent.objects[guid] = c
+ }
+ if c.connection != nil {
+ c.connection.objects.Store(guid, c)
+ }
+ c.channel = newChannel(c, self)
+ c.eventToSubscriptionMapping = map[string]string{}
+}
+
+func (c *channelOwner) markAsInternalType() {
+ c.isInternalType = true
+}
+
+type rootChannelOwner struct {
+ channelOwner
+}
+
+func (r *rootChannelOwner) initialize() (*Playwright, error) {
+ ret, err := r.channel.SendReturnAsDict("initialize", map[string]interface{}{
+ "sdkLanguage": "javascript",
+ })
+ if err != nil {
+ return nil, err
+ }
+ return fromChannel(ret["playwright"]).(*Playwright), nil
+}
+
+func newRootChannelOwner(connection *connection) *rootChannelOwner {
+ c := &rootChannelOwner{}
+ c.connection = connection
+ c.createChannelOwner(c, nil, "Root", "", make(map[string]interface{}))
+ return c
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/clock.go b/vendor/github.com/playwright-community/playwright-go/clock.go
new file mode 100644
index 0000000..8bab037
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/clock.go
@@ -0,0 +1,111 @@
+package playwright
+
+import (
+ "errors"
+ "time"
+)
+
+type clockImpl struct {
+ browserCtx *browserContextImpl
+}
+
+func newClock(bCtx *browserContextImpl) Clock {
+ return &clockImpl{
+ browserCtx: bCtx,
+ }
+}
+
+func (c *clockImpl) FastForward(ticks interface{}) error {
+ params, err := parseTicks(ticks)
+ if err != nil {
+ return err
+ }
+
+ _, err = c.browserCtx.channel.Send("clockFastForward", params)
+ return err
+}
+
+func (c *clockImpl) Install(options ...ClockInstallOptions) (err error) {
+ params := map[string]any{}
+ if len(options) == 1 {
+ if options[0].Time != nil {
+ params, err = parseTime(options[0].Time)
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ _, err = c.browserCtx.channel.Send("clockInstall", params)
+
+ return err
+}
+
+func (c *clockImpl) PauseAt(time interface{}) error {
+ params, err := parseTime(time)
+ if err != nil {
+ return err
+ }
+
+ _, err = c.browserCtx.channel.Send("clockPauseAt", params)
+ return err
+}
+
+func (c *clockImpl) Resume() error {
+ _, err := c.browserCtx.channel.Send("clockResume")
+ return err
+}
+
+func (c *clockImpl) RunFor(ticks interface{}) error {
+ params, err := parseTicks(ticks)
+ if err != nil {
+ return err
+ }
+
+ _, err = c.browserCtx.channel.Send("clockRunFor", params)
+ return err
+}
+
+func (c *clockImpl) SetFixedTime(time interface{}) error {
+ params, err := parseTime(time)
+ if err != nil {
+ return err
+ }
+
+ _, err = c.browserCtx.channel.Send("clockSetFixedTime", params)
+ return err
+}
+
+func (c *clockImpl) SetSystemTime(time interface{}) error {
+ params, err := parseTime(time)
+ if err != nil {
+ return err
+ }
+
+ _, err = c.browserCtx.channel.Send("clockSetSystemTime", params)
+ return err
+}
+
+func parseTime(t interface{}) (map[string]any, error) {
+ switch v := t.(type) {
+ case int, int64:
+ return map[string]any{"timeNumber": v}, nil
+ case string:
+ return map[string]any{"timeString": v}, nil
+ case time.Time:
+ return map[string]any{"timeNumber": v.UnixMilli()}, nil
+ default:
+ return nil, errors.New("time should be one of: int, int64, string, time.Time")
+ }
+}
+
+func parseTicks(ticks interface{}) (map[string]any, error) {
+ switch v := ticks.(type) {
+ case int, int64:
+ return map[string]any{"ticksNumber": v}, nil
+ case string:
+ return map[string]any{"ticksString": v}, nil
+ default:
+ return nil, errors.New("ticks should be one of: int, int64, string")
+ }
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/connection.go b/vendor/github.com/playwright-community/playwright-go/connection.go
new file mode 100644
index 0000000..ba1e365
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/connection.go
@@ -0,0 +1,401 @@
+package playwright
+
+import (
+ "errors"
+ "fmt"
+ "reflect"
+ "regexp"
+ "strconv"
+ "strings"
+ "sync"
+ "sync/atomic"
+ "time"
+
+ "github.com/go-stack/stack"
+ "github.com/playwright-community/playwright-go/internal/safe"
+)
+
+var (
+ pkgSourcePathPattern = regexp.MustCompile(`.+[\\/]playwright-go[\\/][^\\/]+\.go`)
+ apiNameTransform = regexp.MustCompile(`(?U)\(\*(.+)(Impl)?\)`)
+)
+
+type connection struct {
+ transport transport
+ apiZone sync.Map
+ objects *safe.SyncMap[string, *channelOwner]
+ lastID atomic.Uint32
+ rootObject *rootChannelOwner
+ callbacks *safe.SyncMap[uint32, *protocolCallback]
+ afterClose func()
+ onClose func() error
+ isRemote bool
+ localUtils *localUtilsImpl
+ tracingCount atomic.Int32
+ abort chan struct{}
+ abortOnce sync.Once
+ err *safeValue[error] // for event listener error
+ closedError *safeValue[error]
+}
+
+func (c *connection) Start() (*Playwright, error) {
+ go func() {
+ for {
+ msg, err := c.transport.Poll()
+ if err != nil {
+ _ = c.transport.Close()
+ c.cleanup(err)
+ return
+ }
+ c.Dispatch(msg)
+ }
+ }()
+
+ c.onClose = func() error {
+ if err := c.transport.Close(); err != nil {
+ return err
+ }
+ return nil
+ }
+
+ return c.rootObject.initialize()
+}
+
+func (c *connection) Stop() error {
+ if err := c.onClose(); err != nil {
+ return err
+ }
+ c.cleanup()
+ return nil
+}
+
+func (c *connection) cleanup(cause ...error) {
+ if len(cause) > 0 {
+ c.closedError.Set(fmt.Errorf("%w: %w", ErrTargetClosed, cause[0]))
+ } else {
+ c.closedError.Set(ErrTargetClosed)
+ }
+ if c.afterClose != nil {
+ c.afterClose()
+ }
+ c.abortOnce.Do(func() {
+ select {
+ case <-c.abort:
+ default:
+ close(c.abort)
+ }
+ })
+}
+
+func (c *connection) Dispatch(msg *message) {
+ if c.closedError.Get() != nil {
+ return
+ }
+ method := msg.Method
+ if msg.ID != 0 {
+ cb, _ := c.callbacks.LoadAndDelete(uint32(msg.ID))
+ if cb.noReply {
+ return
+ }
+ if msg.Error != nil {
+ cb.SetError(parseError(msg.Error.Error))
+ } else {
+ cb.SetResult(c.replaceGuidsWithChannels(msg.Result).(map[string]interface{}))
+ }
+ return
+ }
+ object, _ := c.objects.Load(msg.GUID)
+ if method == "__create__" {
+ c.createRemoteObject(
+ object, msg.Params["type"].(string), msg.Params["guid"].(string), msg.Params["initializer"],
+ )
+ return
+ }
+ if object == nil {
+ return
+ }
+ if method == "__adopt__" {
+ child, ok := c.objects.Load(msg.Params["guid"].(string))
+ if !ok {
+ return
+ }
+ object.adopt(child)
+ return
+ }
+ if method == "__dispose__" {
+ reason, ok := msg.Params["reason"]
+ if ok {
+ object.dispose(reason.(string))
+ } else {
+ object.dispose()
+ }
+ return
+ }
+ if object.objectType == "JsonPipe" {
+ object.channel.Emit(method, msg.Params)
+ } else {
+ object.channel.Emit(method, c.replaceGuidsWithChannels(msg.Params))
+ }
+}
+
+func (c *connection) LocalUtils() *localUtilsImpl {
+ return c.localUtils
+}
+
+func (c *connection) createRemoteObject(parent *channelOwner, objectType string, guid string, initializer interface{}) interface{} {
+ initializer = c.replaceGuidsWithChannels(initializer)
+ result := createObjectFactory(parent, objectType, guid, initializer.(map[string]interface{}))
+ return result
+}
+
+func (c *connection) WrapAPICall(cb func() (interface{}, error), isInternal bool) (interface{}, error) {
+ if _, ok := c.apiZone.Load("apiZone"); ok {
+ return cb()
+ }
+ c.apiZone.Store("apiZone", serializeCallStack(isInternal))
+ return cb()
+}
+
+func (c *connection) replaceGuidsWithChannels(payload interface{}) interface{} {
+ if payload == nil {
+ return nil
+ }
+ v := reflect.ValueOf(payload)
+ if v.Kind() == reflect.Slice {
+ listV := payload.([]interface{})
+ for i := 0; i < len(listV); i++ {
+ listV[i] = c.replaceGuidsWithChannels(listV[i])
+ }
+ return listV
+ }
+ if v.Kind() == reflect.Map {
+ mapV := payload.(map[string]interface{})
+ if guid, hasGUID := mapV["guid"]; hasGUID {
+ if channelOwner, ok := c.objects.Load(guid.(string)); ok {
+ return channelOwner.channel
+ }
+ }
+ for key := range mapV {
+ mapV[key] = c.replaceGuidsWithChannels(mapV[key])
+ }
+ return mapV
+ }
+ return payload
+}
+
+func (c *connection) sendMessageToServer(object *channelOwner, method string, params interface{}, noReply bool) (cb *protocolCallback) {
+ cb = newProtocolCallback(noReply, c.abort)
+
+ if err := c.closedError.Get(); err != nil {
+ cb.SetError(err)
+ return
+ }
+ if object.wasCollected {
+ cb.SetError(errors.New("The object has been collected to prevent unbounded heap growth."))
+ return
+ }
+
+ id := c.lastID.Add(1)
+ c.callbacks.Store(id, cb)
+ var (
+ metadata = make(map[string]interface{}, 0)
+ stack = make([]map[string]interface{}, 0)
+ )
+ apiZone, ok := c.apiZone.LoadAndDelete("apiZone")
+ if ok {
+ for k, v := range apiZone.(parsedStackTrace).metadata {
+ metadata[k] = v
+ }
+ stack = append(stack, apiZone.(parsedStackTrace).frames...)
+ }
+ metadata["wallTime"] = time.Now().UnixMilli()
+ message := map[string]interface{}{
+ "id": id,
+ "guid": object.guid,
+ "method": method,
+ "params": params, // channel.MarshalJSON will replace channel with guid
+ "metadata": metadata,
+ }
+ if c.tracingCount.Load() > 0 && len(stack) > 0 && object.guid != "localUtils" {
+ c.LocalUtils().AddStackToTracingNoReply(id, stack)
+ }
+
+ if err := c.transport.Send(message); err != nil {
+ cb.SetError(fmt.Errorf("could not send message: %w", err))
+ return
+ }
+
+ return
+}
+
+func (c *connection) setInTracing(isTracing bool) {
+ if isTracing {
+ c.tracingCount.Add(1)
+ } else {
+ c.tracingCount.Add(-1)
+ }
+}
+
+type parsedStackTrace struct {
+ frames []map[string]interface{}
+ metadata map[string]interface{}
+}
+
+func serializeCallStack(isInternal bool) parsedStackTrace {
+ st := stack.Trace().TrimRuntime()
+ if len(st) == 0 { // https://github.com/go-stack/stack/issues/27
+ st = stack.Trace()
+ }
+
+ lastInternalIndex := 0
+ for i, s := range st {
+ if pkgSourcePathPattern.MatchString(s.Frame().File) {
+ lastInternalIndex = i
+ }
+ }
+ apiName := ""
+ if !isInternal {
+ apiName = fmt.Sprintf("%n", st[lastInternalIndex])
+ }
+ st = st.TrimBelow(st[lastInternalIndex])
+
+ callStack := make([]map[string]interface{}, 0)
+ for i, s := range st {
+ if i == 0 {
+ continue
+ }
+ callStack = append(callStack, map[string]interface{}{
+ "file": s.Frame().File,
+ "line": s.Frame().Line,
+ "column": 0,
+ "function": s.Frame().Function,
+ })
+ }
+ metadata := make(map[string]interface{})
+ if len(st) > 1 {
+ metadata["location"] = serializeCallLocation(st[1])
+ }
+ apiName = apiNameTransform.ReplaceAllString(apiName, "$1")
+ if len(apiName) > 1 {
+ apiName = strings.ToUpper(apiName[:1]) + apiName[1:]
+ }
+ metadata["apiName"] = apiName
+ metadata["isInternal"] = isInternal
+ return parsedStackTrace{
+ metadata: metadata,
+ frames: callStack,
+ }
+}
+
+func serializeCallLocation(caller stack.Call) map[string]interface{} {
+ line, _ := strconv.Atoi(fmt.Sprintf("%d", caller))
+ return map[string]interface{}{
+ "file": fmt.Sprintf("%s", caller),
+ "line": line,
+ }
+}
+
+func newConnection(transport transport, localUtils ...*localUtilsImpl) *connection {
+ connection := &connection{
+ abort: make(chan struct{}, 1),
+ callbacks: safe.NewSyncMap[uint32, *protocolCallback](),
+ objects: safe.NewSyncMap[string, *channelOwner](),
+ transport: transport,
+ isRemote: false,
+ err: &safeValue[error]{},
+ closedError: &safeValue[error]{},
+ }
+ if len(localUtils) > 0 {
+ connection.localUtils = localUtils[0]
+ connection.isRemote = true
+ }
+ connection.rootObject = newRootChannelOwner(connection)
+ return connection
+}
+
+func fromChannel(v interface{}) interface{} {
+ return v.(*channel).object
+}
+
+func fromNullableChannel(v interface{}) interface{} {
+ if v == nil {
+ return nil
+ }
+ return fromChannel(v)
+}
+
+type protocolCallback struct {
+ done chan struct{}
+ noReply bool
+ abort <-chan struct{}
+ once sync.Once
+ value map[string]interface{}
+ err error
+}
+
+func (pc *protocolCallback) setResultOnce(result map[string]interface{}, err error) {
+ pc.once.Do(func() {
+ pc.value = result
+ pc.err = err
+ close(pc.done)
+ })
+}
+
+func (pc *protocolCallback) waitResult() {
+ if pc.noReply {
+ return
+ }
+ select {
+ case <-pc.done: // wait for result
+ return
+ case <-pc.abort:
+ select {
+ case <-pc.done:
+ return
+ default:
+ pc.err = errors.New("Connection closed")
+ return
+ }
+ }
+}
+
+func (pc *protocolCallback) SetError(err error) {
+ pc.setResultOnce(nil, err)
+}
+
+func (pc *protocolCallback) SetResult(result map[string]interface{}) {
+ pc.setResultOnce(result, nil)
+}
+
+func (pc *protocolCallback) GetResult() (map[string]interface{}, error) {
+ pc.waitResult()
+ return pc.value, pc.err
+}
+
+// GetResultValue returns value if the map has only one element
+func (pc *protocolCallback) GetResultValue() (interface{}, error) {
+ pc.waitResult()
+ if len(pc.value) == 0 { // empty map treated as nil
+ return nil, pc.err
+ }
+ if len(pc.value) == 1 {
+ for key := range pc.value {
+ return pc.value[key], pc.err
+ }
+ }
+
+ return pc.value, pc.err
+}
+
+func newProtocolCallback(noReply bool, abort <-chan struct{}) *protocolCallback {
+ if noReply {
+ return &protocolCallback{
+ noReply: true,
+ abort: abort,
+ }
+ }
+ return &protocolCallback{
+ done: make(chan struct{}, 1),
+ abort: abort,
+ }
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/console_message.go b/vendor/github.com/playwright-community/playwright-go/console_message.go
new file mode 100644
index 0000000..4baf3f1
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/console_message.go
@@ -0,0 +1,47 @@
+package playwright
+
+type consoleMessageImpl struct {
+ event map[string]interface{}
+ page Page
+}
+
+func (c *consoleMessageImpl) Type() string {
+ return c.event["type"].(string)
+}
+
+func (c *consoleMessageImpl) Text() string {
+ return c.event["text"].(string)
+}
+
+func (c *consoleMessageImpl) String() string {
+ return c.Text()
+}
+
+func (c *consoleMessageImpl) Args() []JSHandle {
+ args := c.event["args"].([]interface{})
+ out := []JSHandle{}
+ for idx := range args {
+ out = append(out, fromChannel(args[idx]).(*jsHandleImpl))
+ }
+ return out
+}
+
+func (c *consoleMessageImpl) Location() *ConsoleMessageLocation {
+ location := &ConsoleMessageLocation{}
+ remapMapToStruct(c.event["location"], location)
+ return location
+}
+
+func (c *consoleMessageImpl) Page() Page {
+ return c.page
+}
+
+func newConsoleMessage(event map[string]interface{}) *consoleMessageImpl {
+ bt := &consoleMessageImpl{}
+ bt.event = event
+ page := fromNullableChannel(event["page"])
+ if page != nil {
+ bt.page = page.(*pageImpl)
+ }
+ return bt
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/dialog.go b/vendor/github.com/playwright-community/playwright-go/dialog.go
new file mode 100644
index 0000000..8d13234
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/dialog.go
@@ -0,0 +1,48 @@
+package playwright
+
+type dialogImpl struct {
+ channelOwner
+ page Page
+}
+
+func (d *dialogImpl) Type() string {
+ return d.initializer["type"].(string)
+}
+
+func (d *dialogImpl) Message() string {
+ return d.initializer["message"].(string)
+}
+
+func (d *dialogImpl) DefaultValue() string {
+ return d.initializer["defaultValue"].(string)
+}
+
+func (d *dialogImpl) Accept(promptTextInput ...string) error {
+ var promptText *string
+ if len(promptTextInput) == 1 {
+ promptText = &promptTextInput[0]
+ }
+ _, err := d.channel.Send("accept", map[string]interface{}{
+ "promptText": promptText,
+ })
+ return err
+}
+
+func (d *dialogImpl) Dismiss() error {
+ _, err := d.channel.Send("dismiss")
+ return err
+}
+
+func (d *dialogImpl) Page() Page {
+ return d.page
+}
+
+func newDialog(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *dialogImpl {
+ bt := &dialogImpl{}
+ bt.createChannelOwner(bt, parent, objectType, guid, initializer)
+ page := fromNullableChannel(initializer["page"])
+ if page != nil {
+ bt.page = page.(*pageImpl)
+ }
+ return bt
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/download.go b/vendor/github.com/playwright-community/playwright-go/download.go
new file mode 100644
index 0000000..b9d2024
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/download.go
@@ -0,0 +1,56 @@
+package playwright
+
+type downloadImpl struct {
+ page *pageImpl
+ url string
+ suggestedFilename string
+ artifact *artifactImpl
+}
+
+func (d *downloadImpl) String() string {
+ return d.SuggestedFilename()
+}
+
+func (d *downloadImpl) Page() Page {
+ return d.page
+}
+
+func (d *downloadImpl) URL() string {
+ return d.url
+}
+
+func (d *downloadImpl) SuggestedFilename() string {
+ return d.suggestedFilename
+}
+
+func (d *downloadImpl) Delete() error {
+ err := d.artifact.Delete()
+ return err
+}
+
+func (d *downloadImpl) Failure() error {
+ return d.artifact.Failure()
+}
+
+func (d *downloadImpl) Path() (string, error) {
+ path, err := d.artifact.PathAfterFinished()
+ return path, err
+}
+
+func (d *downloadImpl) SaveAs(path string) error {
+ err := d.artifact.SaveAs(path)
+ return err
+}
+
+func (d *downloadImpl) Cancel() error {
+ return d.artifact.Cancel()
+}
+
+func newDownload(page *pageImpl, url string, suggestedFilename string, artifact *artifactImpl) *downloadImpl {
+ return &downloadImpl{
+ page: page,
+ url: url,
+ suggestedFilename: suggestedFilename,
+ artifact: artifact,
+ }
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/element_handle.go b/vendor/github.com/playwright-community/playwright-go/element_handle.go
new file mode 100644
index 0000000..62c41ba
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/element_handle.go
@@ -0,0 +1,403 @@
+package playwright
+
+import (
+ "encoding/base64"
+ "errors"
+ "fmt"
+ "os"
+)
+
+type elementHandleImpl struct {
+ jsHandleImpl
+}
+
+func (e *elementHandleImpl) AsElement() ElementHandle {
+ return e
+}
+
+func (e *elementHandleImpl) OwnerFrame() (Frame, error) {
+ channel, err := e.channel.Send("ownerFrame")
+ if err != nil {
+ return nil, err
+ }
+ channelOwner := fromNullableChannel(channel)
+ if channelOwner == nil {
+ return nil, nil
+ }
+ return channelOwner.(*frameImpl), nil
+}
+
+func (e *elementHandleImpl) ContentFrame() (Frame, error) {
+ channel, err := e.channel.Send("contentFrame")
+ if err != nil {
+ return nil, err
+ }
+ channelOwner := fromNullableChannel(channel)
+ if channelOwner == nil {
+ return nil, nil
+ }
+ return channelOwner.(*frameImpl), nil
+}
+
+func (e *elementHandleImpl) GetAttribute(name string) (string, error) {
+ attribute, err := e.channel.Send("getAttribute", map[string]interface{}{
+ "name": name,
+ })
+ if attribute == nil {
+ return "", err
+ }
+ return attribute.(string), err
+}
+
+func (e *elementHandleImpl) TextContent() (string, error) {
+ textContent, err := e.channel.Send("textContent")
+ if textContent == nil {
+ return "", err
+ }
+ return textContent.(string), err
+}
+
+func (e *elementHandleImpl) InnerText() (string, error) {
+ innerText, err := e.channel.Send("innerText")
+ if innerText == nil {
+ return "", err
+ }
+ return innerText.(string), err
+}
+
+func (e *elementHandleImpl) InnerHTML() (string, error) {
+ innerHTML, err := e.channel.Send("innerHTML")
+ if innerHTML == nil {
+ return "", err
+ }
+ return innerHTML.(string), err
+}
+
+func (e *elementHandleImpl) DispatchEvent(typ string, initObjects ...interface{}) error {
+ var initObject interface{}
+ if len(initObjects) == 1 {
+ initObject = initObjects[0]
+ }
+ _, err := e.channel.Send("dispatchEvent", map[string]interface{}{
+ "type": typ,
+ "eventInit": serializeArgument(initObject),
+ })
+ return err
+}
+
+func (e *elementHandleImpl) Hover(options ...ElementHandleHoverOptions) error {
+ _, err := e.channel.Send("hover", options)
+ return err
+}
+
+func (e *elementHandleImpl) Click(options ...ElementHandleClickOptions) error {
+ _, err := e.channel.Send("click", options)
+ return err
+}
+
+func (e *elementHandleImpl) Dblclick(options ...ElementHandleDblclickOptions) error {
+ _, err := e.channel.Send("dblclick", options)
+ return err
+}
+
+func (e *elementHandleImpl) QuerySelector(selector string) (ElementHandle, error) {
+ channel, err := e.channel.Send("querySelector", map[string]interface{}{
+ "selector": selector,
+ })
+ if err != nil {
+ return nil, err
+ }
+ if channel == nil {
+ return nil, nil
+ }
+ return fromChannel(channel).(*elementHandleImpl), nil
+}
+
+func (e *elementHandleImpl) QuerySelectorAll(selector string) ([]ElementHandle, error) {
+ channels, err := e.channel.Send("querySelectorAll", map[string]interface{}{
+ "selector": selector,
+ })
+ if err != nil {
+ return nil, err
+ }
+ elements := make([]ElementHandle, 0)
+ for _, channel := range channels.([]interface{}) {
+ elements = append(elements, fromChannel(channel).(*elementHandleImpl))
+ }
+ return elements, nil
+}
+
+func (e *elementHandleImpl) EvalOnSelector(selector string, expression string, options ...interface{}) (interface{}, error) {
+ var arg interface{}
+ if len(options) == 1 {
+ arg = options[0]
+ }
+ result, err := e.channel.Send("evalOnSelector", map[string]interface{}{
+ "selector": selector,
+ "expression": expression,
+ "arg": serializeArgument(arg),
+ })
+ if err != nil {
+ return nil, err
+ }
+ return parseResult(result), nil
+}
+
+func (e *elementHandleImpl) EvalOnSelectorAll(selector string, expression string, options ...interface{}) (interface{}, error) {
+ var arg interface{}
+ if len(options) == 1 {
+ arg = options[0]
+ }
+ result, err := e.channel.Send("evalOnSelectorAll", map[string]interface{}{
+ "selector": selector,
+ "expression": expression,
+ "arg": serializeArgument(arg),
+ })
+ if err != nil {
+ return nil, err
+ }
+ return parseResult(result), nil
+}
+
+func (e *elementHandleImpl) ScrollIntoViewIfNeeded(options ...ElementHandleScrollIntoViewIfNeededOptions) error {
+ _, err := e.channel.Send("scrollIntoViewIfNeeded", options)
+ if err != nil {
+ return err
+ }
+ return err
+}
+
+func (e *elementHandleImpl) SetInputFiles(files interface{}, options ...ElementHandleSetInputFilesOptions) error {
+ frame, err := e.OwnerFrame()
+ if err != nil {
+ return err
+ }
+ if frame == nil {
+ return errors.New("Cannot set input files to detached element")
+ }
+
+ params, err := convertInputFiles(files, frame.(*frameImpl).page.browserContext)
+ if err != nil {
+ return err
+ }
+ _, err = e.channel.Send("setInputFiles", params, options)
+ return err
+}
+
+func (e *elementHandleImpl) BoundingBox() (*Rect, error) {
+ boundingBox, err := e.channel.Send("boundingBox")
+ if err != nil {
+ return nil, err
+ }
+
+ if boundingBox == nil {
+ return nil, nil
+ }
+
+ out := &Rect{}
+ remapMapToStruct(boundingBox, out)
+ return out, nil
+}
+
+func (e *elementHandleImpl) Check(options ...ElementHandleCheckOptions) error {
+ _, err := e.channel.Send("check", options)
+ return err
+}
+
+func (e *elementHandleImpl) Uncheck(options ...ElementHandleUncheckOptions) error {
+ _, err := e.channel.Send("uncheck", options)
+ return err
+}
+
+func (e *elementHandleImpl) Press(key string, options ...ElementHandlePressOptions) error {
+ _, err := e.channel.Send("press", map[string]interface{}{
+ "key": key,
+ }, options)
+ return err
+}
+
+func (e *elementHandleImpl) Fill(value string, options ...ElementHandleFillOptions) error {
+ _, err := e.channel.Send("fill", map[string]interface{}{
+ "value": value,
+ }, options)
+ return err
+}
+
+func (e *elementHandleImpl) Type(value string, options ...ElementHandleTypeOptions) error {
+ _, err := e.channel.Send("type", map[string]interface{}{
+ "text": value,
+ }, options)
+ return err
+}
+
+func (e *elementHandleImpl) Focus() error {
+ _, err := e.channel.Send("focus")
+ return err
+}
+
+func (e *elementHandleImpl) SelectText(options ...ElementHandleSelectTextOptions) error {
+ _, err := e.channel.Send("selectText", options)
+ return err
+}
+
+func (e *elementHandleImpl) Screenshot(options ...ElementHandleScreenshotOptions) ([]byte, error) {
+ var path *string
+ overrides := map[string]interface{}{}
+ if len(options) == 1 {
+ path = options[0].Path
+ options[0].Path = nil
+ if options[0].Mask != nil {
+ masks := make([]map[string]interface{}, 0)
+ for _, m := range options[0].Mask {
+ if m.Err() != nil { // ErrLocatorNotSameFrame
+ return nil, m.Err()
+ }
+ l, ok := m.(*locatorImpl)
+ if ok {
+ masks = append(masks, map[string]interface{}{
+ "selector": l.selector,
+ "frame": l.frame.channel,
+ })
+ }
+ }
+ overrides["mask"] = masks
+ options[0].Mask = nil
+ }
+ }
+ data, err := e.channel.Send("screenshot", options, overrides)
+ if err != nil {
+ return nil, err
+ }
+ image, err := base64.StdEncoding.DecodeString(data.(string))
+ if err != nil {
+ return nil, fmt.Errorf("could not decode base64 :%w", err)
+ }
+ if path != nil {
+ if err := os.WriteFile(*path, image, 0o644); err != nil {
+ return nil, err
+ }
+ }
+ return image, nil
+}
+
+func (e *elementHandleImpl) Tap(options ...ElementHandleTapOptions) error {
+ _, err := e.channel.Send("tap", options)
+ return err
+}
+
+func (e *elementHandleImpl) SelectOption(values SelectOptionValues, options ...ElementHandleSelectOptionOptions) ([]string, error) {
+ opts := convertSelectOptionSet(values)
+ selected, err := e.channel.Send("selectOption", opts, options)
+ if err != nil {
+ return nil, err
+ }
+
+ return transformToStringList(selected), nil
+}
+
+func (e *elementHandleImpl) IsChecked() (bool, error) {
+ checked, err := e.channel.Send("isChecked")
+ if err != nil {
+ return false, err
+ }
+ return checked.(bool), nil
+}
+
+func (e *elementHandleImpl) IsDisabled() (bool, error) {
+ disabled, err := e.channel.Send("isDisabled")
+ if err != nil {
+ return false, err
+ }
+ return disabled.(bool), nil
+}
+
+func (e *elementHandleImpl) IsEditable() (bool, error) {
+ editable, err := e.channel.Send("isEditable")
+ if err != nil {
+ return false, err
+ }
+ return editable.(bool), nil
+}
+
+func (e *elementHandleImpl) IsEnabled() (bool, error) {
+ enabled, err := e.channel.Send("isEnabled")
+ if err != nil {
+ return false, err
+ }
+ return enabled.(bool), nil
+}
+
+func (e *elementHandleImpl) IsHidden() (bool, error) {
+ hidden, err := e.channel.Send("isHidden")
+ if err != nil {
+ return false, err
+ }
+ return hidden.(bool), nil
+}
+
+func (e *elementHandleImpl) IsVisible() (bool, error) {
+ visible, err := e.channel.Send("isVisible")
+ if err != nil {
+ return false, err
+ }
+ return visible.(bool), nil
+}
+
+func (e *elementHandleImpl) WaitForElementState(state ElementState, options ...ElementHandleWaitForElementStateOptions) error {
+ _, err := e.channel.Send("waitForElementState", map[string]interface{}{
+ "state": state,
+ }, options)
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+func (e *elementHandleImpl) WaitForSelector(selector string, options ...ElementHandleWaitForSelectorOptions) (ElementHandle, error) {
+ ch, err := e.channel.Send("waitForSelector", map[string]interface{}{
+ "selector": selector,
+ }, options)
+ if err != nil {
+ return nil, err
+ }
+
+ channelOwner := fromNullableChannel(ch)
+ if channelOwner == nil {
+ return nil, nil
+ }
+ return channelOwner.(*elementHandleImpl), nil
+}
+
+func (e *elementHandleImpl) InputValue(options ...ElementHandleInputValueOptions) (string, error) {
+ result, err := e.channel.Send("inputValue", options)
+ if result == nil {
+ return "", err
+ }
+ return result.(string), err
+}
+
+func (e *elementHandleImpl) SetChecked(checked bool, options ...ElementHandleSetCheckedOptions) error {
+ if checked {
+ _, err := e.channel.Send("check", options)
+ return err
+ } else {
+ _, err := e.channel.Send("uncheck", options)
+ return err
+ }
+}
+
+func newElementHandle(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *elementHandleImpl {
+ bt := &elementHandleImpl{}
+ bt.createChannelOwner(bt, parent, objectType, guid, initializer)
+ return bt
+}
+
+func transformToStringList(in interface{}) []string {
+ s := in.([]interface{})
+
+ var out []string
+ for _, v := range s {
+ out = append(out, v.(string))
+ }
+ return out
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/errors.go b/vendor/github.com/playwright-community/playwright-go/errors.go
new file mode 100644
index 0000000..36f7396
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/errors.go
@@ -0,0 +1,58 @@
+package playwright
+
+import (
+ "errors"
+ "fmt"
+)
+
+var (
+ // ErrPlaywright wraps all Playwright errors.
+ // - Use errors.Is to check if the error is a Playwright error.
+ // - Use errors.As to cast an error to [Error] if you want to access "Stack".
+ ErrPlaywright = errors.New("playwright")
+ // ErrTargetClosed usually wraps a reason.
+ ErrTargetClosed = errors.New("target closed")
+ // ErrTimeout wraps timeout errors. It can be either Playwright TimeoutError or client timeout.
+ ErrTimeout = errors.New("timeout")
+)
+
+// Error represents a Playwright error
+type Error struct {
+ Name string `json:"name"`
+ Message string `json:"message"`
+ Stack string `json:"stack"`
+}
+
+func (e *Error) Error() string {
+ return e.Message
+}
+
+func (e *Error) Is(target error) bool {
+ err, ok := target.(*Error)
+ if !ok {
+ return false
+ }
+ if err.Name != e.Name {
+ return false
+ }
+ if e.Name != "Error" {
+ return true // same name and not normal error
+ }
+ return e.Message == err.Message
+}
+
+func parseError(err Error) error {
+ if err.Name == "TimeoutError" {
+ return fmt.Errorf("%w: %w: %w", ErrPlaywright, ErrTimeout, &err)
+ } else if err.Name == "TargetClosedError" {
+ return fmt.Errorf("%w: %w: %w", ErrPlaywright, ErrTargetClosed, &err)
+ }
+ return fmt.Errorf("%w: %w", ErrPlaywright, &err)
+}
+
+func targetClosedError(reason *string) error {
+ if reason == nil {
+ return ErrTargetClosed
+ }
+ return fmt.Errorf("%w: %s", ErrTargetClosed, *reason)
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/event_emitter.go b/vendor/github.com/playwright-community/playwright-go/event_emitter.go
new file mode 100644
index 0000000..d4d62ef
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/event_emitter.go
@@ -0,0 +1,163 @@
+package playwright
+
+import (
+ "math"
+ "reflect"
+ "slices"
+ "sync"
+)
+
+type EventEmitter interface {
+ Emit(name string, payload ...interface{}) bool
+ ListenerCount(name string) int
+ On(name string, handler interface{})
+ Once(name string, handler interface{})
+ RemoveListener(name string, handler interface{})
+ RemoveListeners(name string)
+}
+
+type (
+ eventEmitter struct {
+ eventsMutex sync.Mutex
+ events map[string]*eventRegister
+ hasInit bool
+ }
+ eventRegister struct {
+ sync.Mutex
+ listeners []listener
+ }
+ listener struct {
+ handler interface{}
+ once bool
+ }
+)
+
+func NewEventEmitter() EventEmitter {
+ return &eventEmitter{}
+}
+
+func (e *eventEmitter) Emit(name string, payload ...interface{}) (hasListener bool) {
+ e.eventsMutex.Lock()
+ e.init()
+
+ evt, ok := e.events[name]
+ if !ok {
+ e.eventsMutex.Unlock()
+ return
+ }
+ e.eventsMutex.Unlock()
+ return evt.callHandlers(payload...) > 0
+}
+
+func (e *eventEmitter) Once(name string, handler interface{}) {
+ e.addEvent(name, handler, true)
+}
+
+func (e *eventEmitter) On(name string, handler interface{}) {
+ e.addEvent(name, handler, false)
+}
+
+func (e *eventEmitter) RemoveListener(name string, handler interface{}) {
+ e.eventsMutex.Lock()
+ defer e.eventsMutex.Unlock()
+ e.init()
+
+ if evt, ok := e.events[name]; ok {
+ evt.Lock()
+ defer evt.Unlock()
+ evt.removeHandler(handler)
+ }
+}
+
+func (e *eventEmitter) RemoveListeners(name string) {
+ e.eventsMutex.Lock()
+ defer e.eventsMutex.Unlock()
+ e.init()
+ delete(e.events, name)
+}
+
+// ListenerCount count the listeners by name, count all if name is empty
+func (e *eventEmitter) ListenerCount(name string) int {
+ e.eventsMutex.Lock()
+ defer e.eventsMutex.Unlock()
+ e.init()
+
+ if name != "" {
+ evt, ok := e.events[name]
+ if !ok {
+ return 0
+ }
+ return evt.count()
+ }
+
+ count := 0
+ for key := range e.events {
+ count += e.events[key].count()
+ }
+
+ return count
+}
+
+func (e *eventEmitter) addEvent(name string, handler interface{}, once bool) {
+ e.eventsMutex.Lock()
+ defer e.eventsMutex.Unlock()
+ e.init()
+
+ if _, ok := e.events[name]; !ok {
+ e.events[name] = &eventRegister{
+ listeners: make([]listener, 0),
+ }
+ }
+ e.events[name].addHandler(handler, once)
+}
+
+func (e *eventEmitter) init() {
+ if !e.hasInit {
+ e.events = make(map[string]*eventRegister, 0)
+ e.hasInit = true
+ }
+}
+
+func (er *eventRegister) addHandler(handler interface{}, once bool) {
+ er.Lock()
+ defer er.Unlock()
+ er.listeners = append(er.listeners, listener{handler: handler, once: once})
+}
+
+func (er *eventRegister) count() int {
+ er.Lock()
+ defer er.Unlock()
+ return len(er.listeners)
+}
+
+func (er *eventRegister) removeHandler(handler interface{}) {
+ handlerPtr := reflect.ValueOf(handler).Pointer()
+
+ er.listeners = slices.DeleteFunc(er.listeners, func(l listener) bool {
+ return reflect.ValueOf(l.handler).Pointer() == handlerPtr
+ })
+}
+
+func (er *eventRegister) callHandlers(payloads ...interface{}) int {
+ payloadV := make([]reflect.Value, 0)
+
+ for _, p := range payloads {
+ payloadV = append(payloadV, reflect.ValueOf(p))
+ }
+
+ handle := func(l listener) {
+ handlerV := reflect.ValueOf(l.handler)
+ handlerV.Call(payloadV[:int(math.Min(float64(handlerV.Type().NumIn()), float64(len(payloadV))))])
+ }
+
+ er.Lock()
+ defer er.Unlock()
+ count := len(er.listeners)
+ for _, l := range er.listeners {
+ if l.once {
+ defer er.removeHandler(l.handler)
+ }
+ handle(l)
+ }
+ return count
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/fetch.go b/vendor/github.com/playwright-community/playwright-go/fetch.go
new file mode 100644
index 0000000..fc7f79f
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/fetch.go
@@ -0,0 +1,451 @@
+package playwright
+
+import (
+ "encoding/base64"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "os"
+ "strings"
+)
+
+type apiRequestImpl struct {
+ *Playwright
+}
+
+func (r *apiRequestImpl) NewContext(options ...APIRequestNewContextOptions) (APIRequestContext, error) {
+ overrides := map[string]interface{}{}
+ if len(options) == 1 {
+ if options[0].ClientCertificates != nil {
+ certs, err := transformClientCertificate(options[0].ClientCertificates)
+ if err != nil {
+ return nil, err
+ }
+ overrides["clientCertificates"] = certs
+ options[0].ClientCertificates = nil
+ }
+ if options[0].ExtraHttpHeaders != nil {
+ overrides["extraHTTPHeaders"] = serializeMapToNameAndValue(options[0].ExtraHttpHeaders)
+ options[0].ExtraHttpHeaders = nil
+ }
+ if options[0].StorageStatePath != nil {
+ var storageState *StorageState
+ storageString, err := os.ReadFile(*options[0].StorageStatePath)
+ if err != nil {
+ return nil, fmt.Errorf("could not read storage state file: %w", err)
+ }
+ err = json.Unmarshal(storageString, &storageState)
+ if err != nil {
+ return nil, fmt.Errorf("could not parse storage state file: %w", err)
+ }
+ options[0].StorageState = storageState
+ options[0].StorageStatePath = nil
+ }
+ }
+
+ channel, err := r.channel.Send("newRequest", options, overrides)
+ if err != nil {
+ return nil, err
+ }
+ return fromChannel(channel).(*apiRequestContextImpl), nil
+}
+
+func newApiRequestImpl(pw *Playwright) *apiRequestImpl {
+ return &apiRequestImpl{pw}
+}
+
+type apiRequestContextImpl struct {
+ channelOwner
+ tracing *tracingImpl
+ closeReason *string
+}
+
+func (r *apiRequestContextImpl) Dispose(options ...APIRequestContextDisposeOptions) error {
+ if len(options) == 1 {
+ r.closeReason = options[0].Reason
+ }
+ _, err := r.channel.Send("dispose", map[string]interface{}{
+ "reason": r.closeReason,
+ })
+ if errors.Is(err, ErrTargetClosed) {
+ return nil
+ }
+ return err
+}
+
+func (r *apiRequestContextImpl) Delete(url string, options ...APIRequestContextDeleteOptions) (APIResponse, error) {
+ opts := APIRequestContextFetchOptions{
+ Method: String("DELETE"),
+ }
+ if len(options) == 1 {
+ err := assignStructFields(&opts, options[0], false)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ return r.Fetch(url, opts)
+}
+
+func (r *apiRequestContextImpl) Fetch(urlOrRequest interface{}, options ...APIRequestContextFetchOptions) (APIResponse, error) {
+ switch v := urlOrRequest.(type) {
+ case string:
+ return r.innerFetch(v, nil, options...)
+ case Request:
+ return r.innerFetch("", v, options...)
+ default:
+ return nil, fmt.Errorf("urlOrRequest has unsupported type: %T", urlOrRequest)
+ }
+}
+
+func (r *apiRequestContextImpl) innerFetch(url string, request Request, options ...APIRequestContextFetchOptions) (APIResponse, error) {
+ if r.closeReason != nil {
+ return nil, fmt.Errorf("%w: %s", ErrTargetClosed, *r.closeReason)
+ }
+ overrides := map[string]interface{}{}
+ if url != "" {
+ overrides["url"] = url
+ } else if request != nil {
+ overrides["url"] = request.URL()
+ }
+
+ if len(options) == 1 {
+ if options[0].MaxRedirects != nil && *options[0].MaxRedirects < 0 {
+ return nil, errors.New("maxRedirects must be non-negative")
+ }
+ if options[0].MaxRetries != nil && *options[0].MaxRetries < 0 {
+ return nil, errors.New("maxRetries must be non-negative")
+ }
+ // only one of them can be specified
+ if countNonNil(options[0].Data, options[0].Form, options[0].Multipart) > 1 {
+ return nil, errors.New("only one of 'data', 'form' or 'multipart' can be specified")
+ }
+ if options[0].Method == nil {
+ if request != nil {
+ options[0].Method = String(request.Method())
+ } else {
+ options[0].Method = String("GET")
+ }
+ }
+ if options[0].Headers == nil {
+ if request != nil {
+ overrides["headers"] = serializeMapToNameAndValue(request.Headers())
+ }
+ } else {
+ overrides["headers"] = serializeMapToNameAndValue(options[0].Headers)
+ options[0].Headers = nil
+ }
+ if options[0].Data != nil {
+ switch v := options[0].Data.(type) {
+ case string:
+ headersArray, ok := overrides["headers"].([]map[string]string)
+ if ok && isJsonContentType(headersArray) {
+ if json.Valid([]byte(v)) {
+ overrides["jsonData"] = v
+ } else {
+ data, err := json.Marshal(v)
+ if err != nil {
+ return nil, fmt.Errorf("could not marshal data: %w", err)
+ }
+ overrides["jsonData"] = string(data)
+ }
+ } else {
+ overrides["postData"] = base64.StdEncoding.EncodeToString([]byte(v))
+ }
+ case []byte:
+ overrides["postData"] = base64.StdEncoding.EncodeToString(v)
+ case interface{}:
+ data, err := json.Marshal(v)
+ if err != nil {
+ return nil, fmt.Errorf("could not marshal data: %w", err)
+ }
+ overrides["jsonData"] = string(data)
+ default:
+ return nil, errors.New("data must be a string, []byte, or interface{} that can marshal to json")
+ }
+ options[0].Data = nil
+ } else if options[0].Form != nil {
+ form, ok := options[0].Form.(map[string]interface{})
+ if !ok {
+ return nil, errors.New("form must be a map")
+ }
+ overrides["formData"] = serializeMapToNameValue(form)
+ options[0].Form = nil
+ } else if options[0].Multipart != nil {
+ _, ok := options[0].Multipart.(map[string]interface{})
+ if !ok {
+ return nil, errors.New("multipart must be a map")
+ }
+ multipartData := []map[string]interface{}{}
+ for name, value := range options[0].Multipart.(map[string]interface{}) {
+ switch v := value.(type) {
+ case InputFile:
+ multipartData = append(multipartData, map[string]interface{}{
+ "name": name,
+ "file": map[string]string{
+ "name": v.Name,
+ "mimeType": v.MimeType,
+ "buffer": base64.StdEncoding.EncodeToString(v.Buffer),
+ },
+ })
+ default:
+ multipartData = append(multipartData, map[string]interface{}{
+ "name": name,
+ "value": String(fmt.Sprintf("%v", v)),
+ })
+ }
+ }
+ overrides["multipartData"] = multipartData
+ options[0].Multipart = nil
+ } else if request != nil {
+ postDataBuf, err := request.PostDataBuffer()
+ if err == nil {
+ overrides["postData"] = base64.StdEncoding.EncodeToString(postDataBuf)
+ }
+ }
+ if options[0].Params != nil {
+ overrides["params"] = serializeMapToNameValue(options[0].Params)
+ options[0].Params = nil
+ }
+ }
+
+ response, err := r.channel.Send("fetch", options, overrides)
+ if err != nil {
+ return nil, err
+ }
+
+ return newAPIResponse(r, response.(map[string]interface{})), nil
+}
+
+func (r *apiRequestContextImpl) Get(url string, options ...APIRequestContextGetOptions) (APIResponse, error) {
+ opts := APIRequestContextFetchOptions{
+ Method: String("GET"),
+ }
+ if len(options) == 1 {
+ err := assignStructFields(&opts, options[0], false)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ return r.Fetch(url, opts)
+}
+
+func (r *apiRequestContextImpl) Head(url string, options ...APIRequestContextHeadOptions) (APIResponse, error) {
+ opts := APIRequestContextFetchOptions{
+ Method: String("HEAD"),
+ }
+ if len(options) == 1 {
+ err := assignStructFields(&opts, options[0], false)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ return r.Fetch(url, opts)
+}
+
+func (r *apiRequestContextImpl) Patch(url string, options ...APIRequestContextPatchOptions) (APIResponse, error) {
+ opts := APIRequestContextFetchOptions{
+ Method: String("PATCH"),
+ }
+ if len(options) == 1 {
+ err := assignStructFields(&opts, options[0], false)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ return r.Fetch(url, opts)
+}
+
+func (r *apiRequestContextImpl) Put(url string, options ...APIRequestContextPutOptions) (APIResponse, error) {
+ opts := APIRequestContextFetchOptions{
+ Method: String("PUT"),
+ }
+ if len(options) == 1 {
+ err := assignStructFields(&opts, options[0], false)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ return r.Fetch(url, opts)
+}
+
+func (r *apiRequestContextImpl) Post(url string, options ...APIRequestContextPostOptions) (APIResponse, error) {
+ opts := APIRequestContextFetchOptions{
+ Method: String("POST"),
+ }
+ if len(options) == 1 {
+ err := assignStructFields(&opts, options[0], false)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ return r.Fetch(url, opts)
+}
+
+func (r *apiRequestContextImpl) StorageState(path ...string) (*StorageState, error) {
+ result, err := r.channel.SendReturnAsDict("storageState")
+ if err != nil {
+ return nil, err
+ }
+ if len(path) == 1 {
+ file, err := os.Create(path[0])
+ if err != nil {
+ return nil, err
+ }
+ if err := json.NewEncoder(file).Encode(result); err != nil {
+ return nil, err
+ }
+ if err := file.Close(); err != nil {
+ return nil, err
+ }
+ }
+ var storageState StorageState
+ remapMapToStruct(result, &storageState)
+ return &storageState, nil
+}
+
+func newAPIRequestContext(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *apiRequestContextImpl {
+ rc := &apiRequestContextImpl{}
+ rc.createChannelOwner(rc, parent, objectType, guid, initializer)
+ rc.tracing = fromChannel(initializer["tracing"]).(*tracingImpl)
+ return rc
+}
+
+type apiResponseImpl struct {
+ request *apiRequestContextImpl
+ initializer map[string]interface{}
+ headers *rawHeaders
+}
+
+func (r *apiResponseImpl) Body() ([]byte, error) {
+ result, err := r.request.channel.SendReturnAsDict("fetchResponseBody", []map[string]interface{}{
+ {
+ "fetchUid": r.fetchUid(),
+ },
+ })
+ if err != nil {
+ if errors.Is(err, ErrTargetClosed) {
+ return nil, errors.New("response has been disposed")
+ }
+ return nil, err
+ }
+ body := result["binary"]
+ if body == nil {
+ return nil, errors.New("response has been disposed")
+ }
+ return base64.StdEncoding.DecodeString(body.(string))
+}
+
+func (r *apiResponseImpl) Dispose() error {
+ _, err := r.request.channel.Send("disposeAPIResponse", []map[string]interface{}{
+ {
+ "fetchUid": r.fetchUid(),
+ },
+ })
+ return err
+}
+
+func (r *apiResponseImpl) Headers() map[string]string {
+ return r.headers.Headers()
+}
+
+func (r *apiResponseImpl) HeadersArray() []NameValue {
+ return r.headers.HeadersArray()
+}
+
+func (r *apiResponseImpl) JSON(v interface{}) error {
+ body, err := r.Body()
+ if err != nil {
+ return err
+ }
+ return json.Unmarshal(body, &v)
+}
+
+func (r *apiResponseImpl) Ok() bool {
+ return r.Status() == 0 || (r.Status() >= 200 && r.Status() <= 299)
+}
+
+func (r *apiResponseImpl) Status() int {
+ return int(r.initializer["status"].(float64))
+}
+
+func (r *apiResponseImpl) StatusText() string {
+ return r.initializer["statusText"].(string)
+}
+
+func (r *apiResponseImpl) Text() (string, error) {
+ body, err := r.Body()
+ if err != nil {
+ return "", err
+ }
+ return string(body), nil
+}
+
+func (r *apiResponseImpl) URL() string {
+ return r.initializer["url"].(string)
+}
+
+func (r *apiResponseImpl) fetchUid() string {
+ return r.initializer["fetchUid"].(string)
+}
+
+func (r *apiResponseImpl) fetchLog() ([]string, error) {
+ ret, err := r.request.channel.Send("fetchLog", map[string]interface{}{
+ "fetchUid": r.fetchUid(),
+ })
+ if err != nil {
+ return nil, err
+ }
+ result := make([]string, len(ret.([]interface{})))
+ for i, v := range ret.([]interface{}) {
+ result[i] = v.(string)
+ }
+ return result, nil
+}
+
+func newAPIResponse(context *apiRequestContextImpl, initializer map[string]interface{}) *apiResponseImpl {
+ return &apiResponseImpl{
+ request: context,
+ initializer: initializer,
+ headers: newRawHeaders(initializer["headers"]),
+ }
+}
+
+func countNonNil(args ...interface{}) int {
+ count := 0
+ for _, v := range args {
+ if v != nil {
+ count++
+ }
+ }
+ return count
+}
+
+func isJsonContentType(headers []map[string]string) bool {
+ if len(headers) > 0 {
+ for _, v := range headers {
+ if strings.ToLower(v["name"]) == "content-type" {
+ if v["value"] == "application/json" {
+ return true
+ }
+ }
+ }
+ }
+ return false
+}
+
+func serializeMapToNameValue(data map[string]interface{}) []map[string]string {
+ serialized := make([]map[string]string, 0, len(data))
+ for k, v := range data {
+ serialized = append(serialized, map[string]string{
+ "name": k,
+ "value": fmt.Sprintf("%v", v),
+ })
+ }
+ return serialized
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/file_chooser.go b/vendor/github.com/playwright-community/playwright-go/file_chooser.go
new file mode 100644
index 0000000..119e885
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/file_chooser.go
@@ -0,0 +1,44 @@
+package playwright
+
+type fileChooserImpl struct {
+ page Page
+ elementHandle ElementHandle
+ isMultiple bool
+}
+
+func (f *fileChooserImpl) Page() Page {
+ return f.page
+}
+
+func (f *fileChooserImpl) Element() ElementHandle {
+ return f.elementHandle
+}
+
+func (f *fileChooserImpl) IsMultiple() bool {
+ return f.isMultiple
+}
+
+// InputFile represents the input file for:
+// - FileChooser.SetFiles()
+// - ElementHandle.SetInputFiles()
+// - Page.SetInputFiles()
+type InputFile struct {
+ Name string `json:"name"`
+ MimeType string `json:"mimeType,omitempty"`
+ Buffer []byte `json:"buffer"`
+}
+
+func (f *fileChooserImpl) SetFiles(files interface{}, options ...FileChooserSetFilesOptions) error {
+ if len(options) == 1 {
+ return f.elementHandle.SetInputFiles(files, ElementHandleSetInputFilesOptions(options[0]))
+ }
+ return f.elementHandle.SetInputFiles(files)
+}
+
+func newFileChooser(page Page, elementHandle ElementHandle, isMultiple bool) *fileChooserImpl {
+ return &fileChooserImpl{
+ page: page,
+ elementHandle: elementHandle,
+ isMultiple: isMultiple,
+ }
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/frame.go b/vendor/github.com/playwright-community/playwright-go/frame.go
new file mode 100644
index 0000000..b571c8e
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/frame.go
@@ -0,0 +1,792 @@
+package playwright
+
+import (
+ "errors"
+ "fmt"
+ "os"
+ "time"
+
+ mapset "github.com/deckarep/golang-set/v2"
+)
+
+type frameImpl struct {
+ channelOwner
+ detached bool
+ page *pageImpl
+ name string
+ url string
+ parentFrame Frame
+ childFrames []Frame
+ loadStates mapset.Set[string]
+}
+
+func newFrame(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *frameImpl {
+ var loadStates mapset.Set[string]
+
+ if ls, ok := initializer["loadStates"].([]string); ok {
+ loadStates = mapset.NewSet[string](ls...)
+ } else {
+ loadStates = mapset.NewSet[string]()
+ }
+ f := &frameImpl{
+ name: initializer["name"].(string),
+ url: initializer["url"].(string),
+ loadStates: loadStates,
+ childFrames: make([]Frame, 0),
+ }
+ f.createChannelOwner(f, parent, objectType, guid, initializer)
+
+ channelOwner := fromNullableChannel(initializer["parentFrame"])
+ if channelOwner != nil {
+ f.parentFrame = channelOwner.(*frameImpl)
+ f.parentFrame.(*frameImpl).childFrames = append(f.parentFrame.(*frameImpl).childFrames, f)
+ }
+
+ f.channel.On("navigated", f.onFrameNavigated)
+ f.channel.On("loadstate", f.onLoadState)
+ return f
+}
+
+func (f *frameImpl) URL() string {
+ f.RLock()
+ defer f.RUnlock()
+ return f.url
+}
+
+func (f *frameImpl) Name() string {
+ f.RLock()
+ defer f.RUnlock()
+ return f.name
+}
+
+func (f *frameImpl) SetContent(content string, options ...FrameSetContentOptions) error {
+ _, err := f.channel.Send("setContent", map[string]interface{}{
+ "html": content,
+ }, options)
+ return err
+}
+
+func (f *frameImpl) Content() (string, error) {
+ content, err := f.channel.Send("content")
+ if content == nil {
+ return "", err
+ }
+ return content.(string), err
+}
+
+func (f *frameImpl) Goto(url string, options ...FrameGotoOptions) (Response, error) {
+ channel, err := f.channel.Send("goto", map[string]interface{}{
+ "url": url,
+ }, options)
+ if err != nil {
+ return nil, fmt.Errorf("Frame.Goto %s: %w", url, err)
+ }
+ channelOwner := fromNullableChannel(channel)
+ if channelOwner == nil {
+ // navigation to about:blank or navigation to the same URL with a different hash
+ return nil, nil
+ }
+ return channelOwner.(*responseImpl), nil
+}
+
+func (f *frameImpl) AddScriptTag(options FrameAddScriptTagOptions) (ElementHandle, error) {
+ if options.Path != nil {
+ file, err := os.ReadFile(*options.Path)
+ if err != nil {
+ return nil, err
+ }
+ options.Content = String(string(file))
+ options.Path = nil
+ }
+ channel, err := f.channel.Send("addScriptTag", options)
+ if err != nil {
+ return nil, err
+ }
+ return fromChannel(channel).(*elementHandleImpl), nil
+}
+
+func (f *frameImpl) AddStyleTag(options FrameAddStyleTagOptions) (ElementHandle, error) {
+ if options.Path != nil {
+ file, err := os.ReadFile(*options.Path)
+ if err != nil {
+ return nil, err
+ }
+ options.Content = String(string(file))
+ options.Path = nil
+ }
+ channel, err := f.channel.Send("addStyleTag", options)
+ if err != nil {
+ return nil, err
+ }
+ return fromChannel(channel).(*elementHandleImpl), nil
+}
+
+func (f *frameImpl) Page() Page {
+ return f.page
+}
+
+func (f *frameImpl) WaitForLoadState(options ...FrameWaitForLoadStateOptions) error {
+ option := FrameWaitForLoadStateOptions{}
+ if len(options) == 1 {
+ option = options[0]
+ }
+ if option.State == nil {
+ option.State = LoadStateLoad
+ }
+ return f.waitForLoadStateImpl(string(*option.State), option.Timeout, nil)
+}
+
+func (f *frameImpl) waitForLoadStateImpl(state string, timeout *float64, cb func() error) error {
+ if f.loadStates.ContainsOne(state) {
+ return nil
+ }
+ waiter, err := f.setNavigationWaiter(timeout)
+ if err != nil {
+ return err
+ }
+ waiter.WaitForEvent(f, "loadstate", func(payload interface{}) bool {
+ gotState := payload.(string)
+ return gotState == state
+ })
+ if cb == nil {
+ _, err := waiter.Wait()
+ return err
+ } else {
+ _, err := waiter.RunAndWait(cb)
+ return err
+ }
+}
+
+func (f *frameImpl) WaitForURL(url interface{}, options ...FrameWaitForURLOptions) error {
+ if f.page == nil {
+ return errors.New("frame is detached")
+ }
+ matcher := newURLMatcher(url, f.page.browserContext.options.BaseURL)
+ if matcher.Matches(f.URL()) {
+ state := "load"
+ timeout := Float(f.page.timeoutSettings.NavigationTimeout())
+ if len(options) == 1 {
+ if options[0].WaitUntil != nil {
+ state = string(*options[0].WaitUntil)
+ }
+ if options[0].Timeout != nil {
+ timeout = options[0].Timeout
+ }
+ }
+ return f.waitForLoadStateImpl(state, timeout, nil)
+ }
+ navigationOptions := FrameExpectNavigationOptions{URL: url}
+ if len(options) > 0 {
+ navigationOptions.Timeout = options[0].Timeout
+ navigationOptions.WaitUntil = options[0].WaitUntil
+ }
+ if _, err := f.ExpectNavigation(nil, navigationOptions); err != nil {
+ return err
+ }
+ return nil
+}
+
+func (f *frameImpl) ExpectNavigation(cb func() error, options ...FrameExpectNavigationOptions) (Response, error) {
+ if f.page == nil {
+ return nil, errors.New("frame is detached")
+ }
+ option := FrameExpectNavigationOptions{}
+ if len(options) == 1 {
+ option = options[0]
+ }
+ if option.WaitUntil == nil {
+ option.WaitUntil = WaitUntilStateLoad
+ }
+ if option.Timeout == nil {
+ option.Timeout = Float(f.page.timeoutSettings.NavigationTimeout())
+ }
+ deadline := time.Now().Add(time.Duration(*option.Timeout) * time.Millisecond)
+ var matcher *urlMatcher
+ if option.URL != nil {
+ matcher = newURLMatcher(option.URL, f.page.browserContext.options.BaseURL)
+ }
+ predicate := func(events ...interface{}) bool {
+ ev := events[0].(map[string]interface{})
+ err, ok := ev["error"]
+ if ok {
+ // Any failed navigation results in a rejection.
+ logger.Error("navigation error", "url", ev["url"].(string), "error", err)
+ return true
+ }
+ return matcher == nil || matcher.Matches(ev["url"].(string))
+ }
+ waiter, err := f.setNavigationWaiter(option.Timeout)
+ if err != nil {
+ return nil, err
+ }
+
+ eventData, err := waiter.WaitForEvent(f, "navigated", predicate).RunAndWait(cb)
+ if err != nil || eventData == nil {
+ return nil, err
+ }
+
+ t := time.Until(deadline).Milliseconds()
+ if t > 0 {
+ err = f.waitForLoadStateImpl(string(*option.WaitUntil), Float(float64(t)), nil)
+ if err != nil {
+ return nil, err
+ }
+ }
+ event := eventData.(map[string]interface{})
+ if event["newDocument"] != nil && event["newDocument"].(map[string]interface{})["request"] != nil {
+ request := fromChannel(event["newDocument"].(map[string]interface{})["request"]).(*requestImpl)
+ return request.Response()
+ }
+ return nil, nil
+}
+
+func (f *frameImpl) setNavigationWaiter(timeout *float64) (*waiter, error) {
+ if f.page == nil {
+ return nil, errors.New("page does not exist")
+ }
+ waiter := newWaiter()
+ if timeout != nil {
+ waiter.WithTimeout(*timeout)
+ } else {
+ waiter.WithTimeout(f.page.timeoutSettings.NavigationTimeout())
+ }
+ waiter.RejectOnEvent(f.page, "close", f.page.closeErrorWithReason())
+ waiter.RejectOnEvent(f.page, "crash", fmt.Errorf("Navigation failed because page crashed!"))
+ waiter.RejectOnEvent(f.page, "framedetached", fmt.Errorf("Navigating frame was detached!"), func(payload interface{}) bool {
+ frame, ok := payload.(*frameImpl)
+ if ok && frame == f {
+ return true
+ }
+ return false
+ })
+ return waiter, nil
+}
+
+func (f *frameImpl) onFrameNavigated(ev map[string]interface{}) {
+ f.Lock()
+ f.url = ev["url"].(string)
+ f.name = ev["name"].(string)
+ f.Unlock()
+ f.Emit("navigated", ev)
+ _, ok := ev["error"]
+ if !ok && f.page != nil {
+ f.page.Emit("framenavigated", f)
+ }
+}
+
+func (f *frameImpl) onLoadState(ev map[string]interface{}) {
+ if ev["add"] != nil {
+ add := ev["add"].(string)
+ f.loadStates.Add(add)
+ f.Emit("loadstate", add)
+ if f.parentFrame == nil && f.page != nil {
+ if add == "load" || add == "domcontentloaded" {
+ f.Page().Emit(add, f.page)
+ }
+ }
+ } else if ev["remove"] != nil {
+ remove := ev["remove"].(string)
+ f.loadStates.Remove(remove)
+ }
+}
+
+func (f *frameImpl) QuerySelector(selector string, options ...FrameQuerySelectorOptions) (ElementHandle, error) {
+ params := map[string]interface{}{
+ "selector": selector,
+ }
+ if len(options) == 1 {
+ params["strict"] = options[0].Strict
+ }
+ channel, err := f.channel.Send("querySelector", params)
+ if err != nil {
+ return nil, err
+ }
+ if channel == nil {
+ return nil, nil
+ }
+ return fromChannel(channel).(*elementHandleImpl), nil
+}
+
+func (f *frameImpl) QuerySelectorAll(selector string) ([]ElementHandle, error) {
+ channels, err := f.channel.Send("querySelectorAll", map[string]interface{}{
+ "selector": selector,
+ })
+ if err != nil {
+ return nil, err
+ }
+ elements := make([]ElementHandle, 0)
+ for _, channel := range channels.([]interface{}) {
+ elements = append(elements, fromChannel(channel).(*elementHandleImpl))
+ }
+ return elements, nil
+}
+
+func (f *frameImpl) Evaluate(expression string, options ...interface{}) (interface{}, error) {
+ var arg interface{}
+ if len(options) == 1 {
+ arg = options[0]
+ }
+ result, err := f.channel.Send("evaluateExpression", map[string]interface{}{
+ "expression": expression,
+ "arg": serializeArgument(arg),
+ })
+ if err != nil {
+ return nil, err
+ }
+ return parseResult(result), nil
+}
+
+func (f *frameImpl) EvalOnSelector(selector string, expression string, arg interface{}, options ...FrameEvalOnSelectorOptions) (interface{}, error) {
+ params := map[string]interface{}{
+ "selector": selector,
+ "expression": expression,
+ "arg": serializeArgument(arg),
+ }
+ if len(options) == 1 && options[0].Strict != nil {
+ params["strict"] = *options[0].Strict
+ }
+
+ result, err := f.channel.Send("evalOnSelector", params)
+ if err != nil {
+ return nil, err
+ }
+ return parseResult(result), nil
+}
+
+func (f *frameImpl) EvalOnSelectorAll(selector string, expression string, options ...interface{}) (interface{}, error) {
+ var arg interface{}
+ if len(options) == 1 {
+ arg = options[0]
+ }
+ result, err := f.channel.Send("evalOnSelectorAll", map[string]interface{}{
+ "selector": selector,
+ "expression": expression,
+ "arg": serializeArgument(arg),
+ })
+ if err != nil {
+ return nil, err
+ }
+ return parseResult(result), nil
+}
+
+func (f *frameImpl) EvaluateHandle(expression string, options ...interface{}) (JSHandle, error) {
+ var arg interface{}
+ if len(options) == 1 {
+ arg = options[0]
+ }
+ result, err := f.channel.Send("evaluateExpressionHandle", map[string]interface{}{
+ "expression": expression,
+ "arg": serializeArgument(arg),
+ })
+ if err != nil {
+ return nil, err
+ }
+ channelOwner := fromChannel(result)
+ if channelOwner == nil {
+ return nil, nil
+ }
+ return channelOwner.(JSHandle), nil
+}
+
+func (f *frameImpl) Click(selector string, options ...FrameClickOptions) error {
+ _, err := f.channel.Send("click", map[string]interface{}{
+ "selector": selector,
+ }, options)
+ return err
+}
+
+func (f *frameImpl) WaitForSelector(selector string, options ...FrameWaitForSelectorOptions) (ElementHandle, error) {
+ channel, err := f.channel.Send("waitForSelector", map[string]interface{}{
+ "selector": selector,
+ }, options)
+ if err != nil {
+ return nil, err
+ }
+ channelOwner := fromNullableChannel(channel)
+ if channelOwner == nil {
+ return nil, nil
+ }
+ return channelOwner.(*elementHandleImpl), nil
+}
+
+func (f *frameImpl) DispatchEvent(selector, typ string, eventInit interface{}, options ...FrameDispatchEventOptions) error {
+ _, err := f.channel.Send("dispatchEvent", map[string]interface{}{
+ "selector": selector,
+ "type": typ,
+ "eventInit": serializeArgument(eventInit),
+ })
+ return err
+}
+
+func (f *frameImpl) InnerText(selector string, options ...FrameInnerTextOptions) (string, error) {
+ innerText, err := f.channel.Send("innerText", map[string]interface{}{
+ "selector": selector,
+ }, options)
+ if innerText == nil {
+ return "", err
+ }
+ return innerText.(string), err
+}
+
+func (f *frameImpl) InnerHTML(selector string, options ...FrameInnerHTMLOptions) (string, error) {
+ innerHTML, err := f.channel.Send("innerHTML", map[string]interface{}{
+ "selector": selector,
+ }, options)
+ if innerHTML == nil {
+ return "", err
+ }
+ return innerHTML.(string), err
+}
+
+func (f *frameImpl) GetAttribute(selector string, name string, options ...FrameGetAttributeOptions) (string, error) {
+ attribute, err := f.channel.Send("getAttribute", map[string]interface{}{
+ "selector": selector,
+ "name": name,
+ }, options)
+ if attribute == nil {
+ return "", err
+ }
+ return attribute.(string), err
+}
+
+func (f *frameImpl) Hover(selector string, options ...FrameHoverOptions) error {
+ _, err := f.channel.Send("hover", map[string]interface{}{
+ "selector": selector,
+ }, options)
+ return err
+}
+
+func (f *frameImpl) SetInputFiles(selector string, files interface{}, options ...FrameSetInputFilesOptions) error {
+ params, err := convertInputFiles(files, f.page.browserContext)
+ if err != nil {
+ return err
+ }
+ params.Selector = &selector
+ _, err = f.channel.Send("setInputFiles", params, options)
+ return err
+}
+
+func (f *frameImpl) Type(selector, text string, options ...FrameTypeOptions) error {
+ _, err := f.channel.Send("type", map[string]interface{}{
+ "selector": selector,
+ "text": text,
+ }, options)
+ return err
+}
+
+func (f *frameImpl) Press(selector, key string, options ...FramePressOptions) error {
+ _, err := f.channel.Send("press", map[string]interface{}{
+ "selector": selector,
+ "key": key,
+ }, options)
+ return err
+}
+
+func (f *frameImpl) Check(selector string, options ...FrameCheckOptions) error {
+ _, err := f.channel.Send("check", map[string]interface{}{
+ "selector": selector,
+ }, options)
+ return err
+}
+
+func (f *frameImpl) Uncheck(selector string, options ...FrameUncheckOptions) error {
+ _, err := f.channel.Send("uncheck", map[string]interface{}{
+ "selector": selector,
+ }, options)
+ return err
+}
+
+func (f *frameImpl) WaitForTimeout(timeout float64) {
+ time.Sleep(time.Duration(timeout) * time.Millisecond)
+}
+
+func (f *frameImpl) WaitForFunction(expression string, arg interface{}, options ...FrameWaitForFunctionOptions) (JSHandle, error) {
+ var option FrameWaitForFunctionOptions
+ if len(options) == 1 {
+ option = options[0]
+ }
+ result, err := f.channel.Send("waitForFunction", map[string]interface{}{
+ "expression": expression,
+ "arg": serializeArgument(arg),
+ "timeout": option.Timeout,
+ "polling": option.Polling,
+ })
+ if err != nil {
+ return nil, err
+ }
+ handle := fromChannel(result)
+ if handle == nil {
+ return nil, nil
+ }
+ return handle.(*jsHandleImpl), nil
+}
+
+func (f *frameImpl) Title() (string, error) {
+ title, err := f.channel.Send("title")
+ if title == nil {
+ return "", err
+ }
+ return title.(string), err
+}
+
+func (f *frameImpl) ChildFrames() []Frame {
+ return f.childFrames
+}
+
+func (f *frameImpl) Dblclick(selector string, options ...FrameDblclickOptions) error {
+ _, err := f.channel.Send("dblclick", map[string]interface{}{
+ "selector": selector,
+ }, options)
+ return err
+}
+
+func (f *frameImpl) Fill(selector string, value string, options ...FrameFillOptions) error {
+ _, err := f.channel.Send("fill", map[string]interface{}{
+ "selector": selector,
+ "value": value,
+ }, options)
+ return err
+}
+
+func (f *frameImpl) Focus(selector string, options ...FrameFocusOptions) error {
+ _, err := f.channel.Send("focus", map[string]interface{}{
+ "selector": selector,
+ }, options)
+ return err
+}
+
+func (f *frameImpl) FrameElement() (ElementHandle, error) {
+ channel, err := f.channel.Send("frameElement")
+ if err != nil {
+ return nil, err
+ }
+ return fromChannel(channel).(*elementHandleImpl), nil
+}
+
+func (f *frameImpl) IsDetached() bool {
+ return f.detached
+}
+
+func (f *frameImpl) ParentFrame() Frame {
+ return f.parentFrame
+}
+
+func (f *frameImpl) TextContent(selector string, options ...FrameTextContentOptions) (string, error) {
+ textContent, err := f.channel.Send("textContent", map[string]interface{}{
+ "selector": selector,
+ }, options)
+ if textContent == nil {
+ return "", err
+ }
+ return textContent.(string), err
+}
+
+func (f *frameImpl) Tap(selector string, options ...FrameTapOptions) error {
+ _, err := f.channel.Send("tap", map[string]interface{}{
+ "selector": selector,
+ }, options)
+ return err
+}
+
+func (f *frameImpl) SelectOption(selector string, values SelectOptionValues, options ...FrameSelectOptionOptions) ([]string, error) {
+ opts := convertSelectOptionSet(values)
+
+ m := make(map[string]interface{})
+ m["selector"] = selector
+ for k, v := range opts {
+ m[k] = v
+ }
+ selected, err := f.channel.Send("selectOption", m, options)
+ if err != nil {
+ return nil, err
+ }
+
+ return transformToStringList(selected), nil
+}
+
+func (f *frameImpl) IsChecked(selector string, options ...FrameIsCheckedOptions) (bool, error) {
+ checked, err := f.channel.Send("isChecked", map[string]interface{}{
+ "selector": selector,
+ }, options)
+ if err != nil {
+ return false, err
+ }
+ return checked.(bool), nil
+}
+
+func (f *frameImpl) IsDisabled(selector string, options ...FrameIsDisabledOptions) (bool, error) {
+ disabled, err := f.channel.Send("isDisabled", map[string]interface{}{
+ "selector": selector,
+ }, options)
+ if err != nil {
+ return false, err
+ }
+ return disabled.(bool), nil
+}
+
+func (f *frameImpl) IsEditable(selector string, options ...FrameIsEditableOptions) (bool, error) {
+ editable, err := f.channel.Send("isEditable", map[string]interface{}{
+ "selector": selector,
+ }, options)
+ if err != nil {
+ return false, err
+ }
+ return editable.(bool), nil
+}
+
+func (f *frameImpl) IsEnabled(selector string, options ...FrameIsEnabledOptions) (bool, error) {
+ enabled, err := f.channel.Send("isEnabled", map[string]interface{}{
+ "selector": selector,
+ }, options)
+ if err != nil {
+ return false, err
+ }
+ return enabled.(bool), nil
+}
+
+func (f *frameImpl) IsHidden(selector string, options ...FrameIsHiddenOptions) (bool, error) {
+ hidden, err := f.channel.Send("isHidden", map[string]interface{}{
+ "selector": selector,
+ }, options)
+ if err != nil {
+ return false, err
+ }
+ return hidden.(bool), nil
+}
+
+func (f *frameImpl) IsVisible(selector string, options ...FrameIsVisibleOptions) (bool, error) {
+ visible, err := f.channel.Send("isVisible", map[string]interface{}{
+ "selector": selector,
+ }, options)
+ if err != nil {
+ return false, err
+ }
+ return visible.(bool), nil
+}
+
+func (f *frameImpl) InputValue(selector string, options ...FrameInputValueOptions) (string, error) {
+ value, err := f.channel.Send("inputValue", map[string]interface{}{
+ "selector": selector,
+ }, options)
+ if value == nil {
+ return "", err
+ }
+ return value.(string), err
+}
+
+func (f *frameImpl) DragAndDrop(source, target string, options ...FrameDragAndDropOptions) error {
+ _, err := f.channel.Send("dragAndDrop", map[string]interface{}{
+ "source": source,
+ "target": target,
+ }, options)
+ return err
+}
+
+func (f *frameImpl) SetChecked(selector string, checked bool, options ...FrameSetCheckedOptions) error {
+ if checked {
+ _, err := f.channel.Send("check", map[string]interface{}{
+ "selector": selector,
+ }, options)
+ return err
+ } else {
+ _, err := f.channel.Send("uncheck", map[string]interface{}{
+ "selector": selector,
+ }, options)
+ return err
+ }
+}
+
+func (f *frameImpl) Locator(selector string, options ...FrameLocatorOptions) Locator {
+ var option LocatorOptions
+ if len(options) == 1 {
+ option = LocatorOptions{
+ Has: options[0].Has,
+ HasNot: options[0].HasNot,
+ HasText: options[0].HasText,
+ HasNotText: options[0].HasNotText,
+ }
+ }
+ return newLocator(f, selector, option)
+}
+
+func (f *frameImpl) GetByAltText(text interface{}, options ...FrameGetByAltTextOptions) Locator {
+ exact := false
+ if len(options) == 1 {
+ if *options[0].Exact {
+ exact = true
+ }
+ }
+ return f.Locator(getByAltTextSelector(text, exact))
+}
+
+func (f *frameImpl) GetByLabel(text interface{}, options ...FrameGetByLabelOptions) Locator {
+ exact := false
+ if len(options) == 1 {
+ if *options[0].Exact {
+ exact = true
+ }
+ }
+ return f.Locator(getByLabelSelector(text, exact))
+}
+
+func (f *frameImpl) GetByPlaceholder(text interface{}, options ...FrameGetByPlaceholderOptions) Locator {
+ exact := false
+ if len(options) == 1 {
+ if *options[0].Exact {
+ exact = true
+ }
+ }
+ return f.Locator(getByPlaceholderSelector(text, exact))
+}
+
+func (f *frameImpl) GetByRole(role AriaRole, options ...FrameGetByRoleOptions) Locator {
+ if len(options) == 1 {
+ return f.Locator(getByRoleSelector(role, LocatorGetByRoleOptions(options[0])))
+ }
+ return f.Locator(getByRoleSelector(role))
+}
+
+func (f *frameImpl) GetByTestId(testId interface{}) Locator {
+ return f.Locator(getByTestIdSelector(getTestIdAttributeName(), testId))
+}
+
+func (f *frameImpl) GetByText(text interface{}, options ...FrameGetByTextOptions) Locator {
+ exact := false
+ if len(options) == 1 {
+ if *options[0].Exact {
+ exact = true
+ }
+ }
+ return f.Locator(getByTextSelector(text, exact))
+}
+
+func (f *frameImpl) GetByTitle(text interface{}, options ...FrameGetByTitleOptions) Locator {
+ exact := false
+ if len(options) == 1 {
+ if *options[0].Exact {
+ exact = true
+ }
+ }
+ return f.Locator(getByTitleSelector(text, exact))
+}
+
+func (f *frameImpl) FrameLocator(selector string) FrameLocator {
+ return newFrameLocator(f, selector)
+}
+
+func (f *frameImpl) highlight(selector string) error {
+ _, err := f.channel.Send("highlight", map[string]interface{}{
+ "selector": selector,
+ })
+ return err
+}
+
+func (f *frameImpl) queryCount(selector string) (int, error) {
+ response, err := f.channel.Send("queryCount", map[string]interface{}{
+ "selector": selector,
+ })
+ if err != nil {
+ return 0, err
+ }
+ return int(response.(float64)), nil
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/frame_locator.go b/vendor/github.com/playwright-community/playwright-go/frame_locator.go
new file mode 100644
index 0000000..d4b8fd0
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/frame_locator.go
@@ -0,0 +1,130 @@
+package playwright
+
+import (
+ "errors"
+ "fmt"
+ "strconv"
+)
+
+type frameLocatorImpl struct {
+ frame *frameImpl
+ frameSelector string
+}
+
+func newFrameLocator(frame *frameImpl, frameSelector string) *frameLocatorImpl {
+ return &frameLocatorImpl{frame: frame, frameSelector: frameSelector}
+}
+
+func (fl *frameLocatorImpl) First() FrameLocator {
+ return newFrameLocator(fl.frame, fl.frameSelector+" >> nth=0")
+}
+
+func (fl *frameLocatorImpl) FrameLocator(selector string) FrameLocator {
+ return newFrameLocator(fl.frame, fl.frameSelector+" >> internal:control=enter-frame >> "+selector)
+}
+
+func (fl *frameLocatorImpl) GetByAltText(text interface{}, options ...FrameLocatorGetByAltTextOptions) Locator {
+ exact := false
+ if len(options) == 1 {
+ if *options[0].Exact {
+ exact = true
+ }
+ }
+ return fl.Locator(getByAltTextSelector(text, exact))
+}
+
+func (fl *frameLocatorImpl) GetByLabel(text interface{}, options ...FrameLocatorGetByLabelOptions) Locator {
+ exact := false
+ if len(options) == 1 {
+ if *options[0].Exact {
+ exact = true
+ }
+ }
+ return fl.Locator(getByLabelSelector(text, exact))
+}
+
+func (fl *frameLocatorImpl) GetByPlaceholder(text interface{}, options ...FrameLocatorGetByPlaceholderOptions) Locator {
+ exact := false
+ if len(options) == 1 {
+ if *options[0].Exact {
+ exact = true
+ }
+ }
+ return fl.Locator(getByPlaceholderSelector(text, exact))
+}
+
+func (fl *frameLocatorImpl) GetByRole(role AriaRole, options ...FrameLocatorGetByRoleOptions) Locator {
+ if len(options) == 1 {
+ return fl.Locator(getByRoleSelector(role, LocatorGetByRoleOptions(options[0])))
+ }
+ return fl.Locator(getByRoleSelector(role))
+}
+
+func (fl *frameLocatorImpl) GetByTestId(testId interface{}) Locator {
+ return fl.Locator(getByTestIdSelector(getTestIdAttributeName(), testId))
+}
+
+func (fl *frameLocatorImpl) GetByText(text interface{}, options ...FrameLocatorGetByTextOptions) Locator {
+ exact := false
+ if len(options) == 1 {
+ if *options[0].Exact {
+ exact = true
+ }
+ }
+ return fl.Locator(getByTextSelector(text, exact))
+}
+
+func (fl *frameLocatorImpl) GetByTitle(text interface{}, options ...FrameLocatorGetByTitleOptions) Locator {
+ exact := false
+ if len(options) == 1 {
+ if *options[0].Exact {
+ exact = true
+ }
+ }
+ return fl.Locator(getByTitleSelector(text, exact))
+}
+
+func (fl *frameLocatorImpl) Last() FrameLocator {
+ return newFrameLocator(fl.frame, fl.frameSelector+" >> nth=-1")
+}
+
+func (fl *frameLocatorImpl) Locator(selectorOrLocator interface{}, options ...FrameLocatorLocatorOptions) Locator {
+ var option LocatorOptions
+ if len(options) == 1 {
+ option = LocatorOptions{
+ Has: options[0].Has,
+ HasNot: options[0].HasNot,
+ HasText: options[0].HasText,
+ HasNotText: options[0].HasNotText,
+ }
+ }
+
+ selector, ok := selectorOrLocator.(string)
+ if ok {
+ return newLocator(fl.frame, fl.frameSelector+" >> internal:control=enter-frame >> "+selector, option)
+ }
+ locator, ok := selectorOrLocator.(*locatorImpl)
+ if ok {
+ if fl.frame != locator.frame {
+ locator.err = errors.Join(locator.err, ErrLocatorNotSameFrame)
+ return locator
+ }
+ return newLocator(locator.frame,
+ fmt.Sprintf("%s >> internal:control=enter-frame >> %s", fl.frameSelector, locator.selector),
+ option,
+ )
+ }
+ return &locatorImpl{
+ frame: fl.frame,
+ selector: fl.frameSelector,
+ err: fmt.Errorf("invalid locator parameter: %v", selectorOrLocator),
+ }
+}
+
+func (fl *frameLocatorImpl) Nth(index int) FrameLocator {
+ return newFrameLocator(fl.frame, fl.frameSelector+" >> nth="+strconv.Itoa(index))
+}
+
+func (fl *frameLocatorImpl) Owner() Locator {
+ return newLocator(fl.frame, fl.frameSelector)
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/generated-enums.go b/vendor/github.com/playwright-community/playwright-go/generated-enums.go
new file mode 100644
index 0000000..92c20c6
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/generated-enums.go
@@ -0,0 +1,404 @@
+package playwright
+
+func getMixedState(in string) *MixedState {
+ v := MixedState(in)
+ return &v
+}
+
+type MixedState string
+
+var (
+ MixedStateOn *MixedState = getMixedState("On")
+ MixedStateOff = getMixedState("Off")
+ MixedStateMixed = getMixedState("Mixed")
+)
+
+func getElementState(in string) *ElementState {
+ v := ElementState(in)
+ return &v
+}
+
+type ElementState string
+
+var (
+ ElementStateVisible *ElementState = getElementState("visible")
+ ElementStateHidden = getElementState("hidden")
+ ElementStateStable = getElementState("stable")
+ ElementStateEnabled = getElementState("enabled")
+ ElementStateDisabled = getElementState("disabled")
+ ElementStateEditable = getElementState("editable")
+)
+
+func getAriaRole(in string) *AriaRole {
+ v := AriaRole(in)
+ return &v
+}
+
+type AriaRole string
+
+var (
+ AriaRoleAlert *AriaRole = getAriaRole("alert")
+ AriaRoleAlertdialog = getAriaRole("alertdialog")
+ AriaRoleApplication = getAriaRole("application")
+ AriaRoleArticle = getAriaRole("article")
+ AriaRoleBanner = getAriaRole("banner")
+ AriaRoleBlockquote = getAriaRole("blockquote")
+ AriaRoleButton = getAriaRole("button")
+ AriaRoleCaption = getAriaRole("caption")
+ AriaRoleCell = getAriaRole("cell")
+ AriaRoleCheckbox = getAriaRole("checkbox")
+ AriaRoleCode = getAriaRole("code")
+ AriaRoleColumnheader = getAriaRole("columnheader")
+ AriaRoleCombobox = getAriaRole("combobox")
+ AriaRoleComplementary = getAriaRole("complementary")
+ AriaRoleContentinfo = getAriaRole("contentinfo")
+ AriaRoleDefinition = getAriaRole("definition")
+ AriaRoleDeletion = getAriaRole("deletion")
+ AriaRoleDialog = getAriaRole("dialog")
+ AriaRoleDirectory = getAriaRole("directory")
+ AriaRoleDocument = getAriaRole("document")
+ AriaRoleEmphasis = getAriaRole("emphasis")
+ AriaRoleFeed = getAriaRole("feed")
+ AriaRoleFigure = getAriaRole("figure")
+ AriaRoleForm = getAriaRole("form")
+ AriaRoleGeneric = getAriaRole("generic")
+ AriaRoleGrid = getAriaRole("grid")
+ AriaRoleGridcell = getAriaRole("gridcell")
+ AriaRoleGroup = getAriaRole("group")
+ AriaRoleHeading = getAriaRole("heading")
+ AriaRoleImg = getAriaRole("img")
+ AriaRoleInsertion = getAriaRole("insertion")
+ AriaRoleLink = getAriaRole("link")
+ AriaRoleList = getAriaRole("list")
+ AriaRoleListbox = getAriaRole("listbox")
+ AriaRoleListitem = getAriaRole("listitem")
+ AriaRoleLog = getAriaRole("log")
+ AriaRoleMain = getAriaRole("main")
+ AriaRoleMarquee = getAriaRole("marquee")
+ AriaRoleMath = getAriaRole("math")
+ AriaRoleMeter = getAriaRole("meter")
+ AriaRoleMenu = getAriaRole("menu")
+ AriaRoleMenubar = getAriaRole("menubar")
+ AriaRoleMenuitem = getAriaRole("menuitem")
+ AriaRoleMenuitemcheckbox = getAriaRole("menuitemcheckbox")
+ AriaRoleMenuitemradio = getAriaRole("menuitemradio")
+ AriaRoleNavigation = getAriaRole("navigation")
+ AriaRoleNone = getAriaRole("none")
+ AriaRoleNote = getAriaRole("note")
+ AriaRoleOption = getAriaRole("option")
+ AriaRoleParagraph = getAriaRole("paragraph")
+ AriaRolePresentation = getAriaRole("presentation")
+ AriaRoleProgressbar = getAriaRole("progressbar")
+ AriaRoleRadio = getAriaRole("radio")
+ AriaRoleRadiogroup = getAriaRole("radiogroup")
+ AriaRoleRegion = getAriaRole("region")
+ AriaRoleRow = getAriaRole("row")
+ AriaRoleRowgroup = getAriaRole("rowgroup")
+ AriaRoleRowheader = getAriaRole("rowheader")
+ AriaRoleScrollbar = getAriaRole("scrollbar")
+ AriaRoleSearch = getAriaRole("search")
+ AriaRoleSearchbox = getAriaRole("searchbox")
+ AriaRoleSeparator = getAriaRole("separator")
+ AriaRoleSlider = getAriaRole("slider")
+ AriaRoleSpinbutton = getAriaRole("spinbutton")
+ AriaRoleStatus = getAriaRole("status")
+ AriaRoleStrong = getAriaRole("strong")
+ AriaRoleSubscript = getAriaRole("subscript")
+ AriaRoleSuperscript = getAriaRole("superscript")
+ AriaRoleSwitch = getAriaRole("switch")
+ AriaRoleTab = getAriaRole("tab")
+ AriaRoleTable = getAriaRole("table")
+ AriaRoleTablist = getAriaRole("tablist")
+ AriaRoleTabpanel = getAriaRole("tabpanel")
+ AriaRoleTerm = getAriaRole("term")
+ AriaRoleTextbox = getAriaRole("textbox")
+ AriaRoleTime = getAriaRole("time")
+ AriaRoleTimer = getAriaRole("timer")
+ AriaRoleToolbar = getAriaRole("toolbar")
+ AriaRoleTooltip = getAriaRole("tooltip")
+ AriaRoleTree = getAriaRole("tree")
+ AriaRoleTreegrid = getAriaRole("treegrid")
+ AriaRoleTreeitem = getAriaRole("treeitem")
+)
+
+func getColorScheme(in string) *ColorScheme {
+ v := ColorScheme(in)
+ return &v
+}
+
+type ColorScheme string
+
+var (
+ ColorSchemeLight *ColorScheme = getColorScheme("light")
+ ColorSchemeDark = getColorScheme("dark")
+ ColorSchemeNoPreference = getColorScheme("no-preference")
+ ColorSchemeNoOverride = getColorScheme("no-override")
+)
+
+func getForcedColors(in string) *ForcedColors {
+ v := ForcedColors(in)
+ return &v
+}
+
+type ForcedColors string
+
+var (
+ ForcedColorsActive *ForcedColors = getForcedColors("active")
+ ForcedColorsNone = getForcedColors("none")
+ ForcedColorsNoOverride = getForcedColors("no-override")
+)
+
+func getHarContentPolicy(in string) *HarContentPolicy {
+ v := HarContentPolicy(in)
+ return &v
+}
+
+type HarContentPolicy string
+
+var (
+ HarContentPolicyOmit *HarContentPolicy = getHarContentPolicy("omit")
+ HarContentPolicyEmbed = getHarContentPolicy("embed")
+ HarContentPolicyAttach = getHarContentPolicy("attach")
+)
+
+func getHarMode(in string) *HarMode {
+ v := HarMode(in)
+ return &v
+}
+
+type HarMode string
+
+var (
+ HarModeFull *HarMode = getHarMode("full")
+ HarModeMinimal = getHarMode("minimal")
+)
+
+func getReducedMotion(in string) *ReducedMotion {
+ v := ReducedMotion(in)
+ return &v
+}
+
+type ReducedMotion string
+
+var (
+ ReducedMotionReduce *ReducedMotion = getReducedMotion("reduce")
+ ReducedMotionNoPreference = getReducedMotion("no-preference")
+ ReducedMotionNoOverride = getReducedMotion("no-override")
+)
+
+func getServiceWorkerPolicy(in string) *ServiceWorkerPolicy {
+ v := ServiceWorkerPolicy(in)
+ return &v
+}
+
+type ServiceWorkerPolicy string
+
+var (
+ ServiceWorkerPolicyAllow *ServiceWorkerPolicy = getServiceWorkerPolicy("allow")
+ ServiceWorkerPolicyBlock = getServiceWorkerPolicy("block")
+)
+
+func getSameSiteAttribute(in string) *SameSiteAttribute {
+ v := SameSiteAttribute(in)
+ return &v
+}
+
+type SameSiteAttribute string
+
+var (
+ SameSiteAttributeStrict *SameSiteAttribute = getSameSiteAttribute("Strict")
+ SameSiteAttributeLax = getSameSiteAttribute("Lax")
+ SameSiteAttributeNone = getSameSiteAttribute("None")
+)
+
+func getHarNotFound(in string) *HarNotFound {
+ v := HarNotFound(in)
+ return &v
+}
+
+type HarNotFound string
+
+var (
+ HarNotFoundAbort *HarNotFound = getHarNotFound("abort")
+ HarNotFoundFallback = getHarNotFound("fallback")
+)
+
+func getRouteFromHarUpdateContentPolicy(in string) *RouteFromHarUpdateContentPolicy {
+ v := RouteFromHarUpdateContentPolicy(in)
+ return &v
+}
+
+type RouteFromHarUpdateContentPolicy string
+
+var (
+ RouteFromHarUpdateContentPolicyEmbed *RouteFromHarUpdateContentPolicy = getRouteFromHarUpdateContentPolicy("embed")
+ RouteFromHarUpdateContentPolicyAttach = getRouteFromHarUpdateContentPolicy("attach")
+)
+
+func getUnrouteBehavior(in string) *UnrouteBehavior {
+ v := UnrouteBehavior(in)
+ return &v
+}
+
+type UnrouteBehavior string
+
+var (
+ UnrouteBehaviorWait *UnrouteBehavior = getUnrouteBehavior("wait")
+ UnrouteBehaviorIgnoreErrors = getUnrouteBehavior("ignoreErrors")
+ UnrouteBehaviorDefault = getUnrouteBehavior("default")
+)
+
+func getMouseButton(in string) *MouseButton {
+ v := MouseButton(in)
+ return &v
+}
+
+type MouseButton string
+
+var (
+ MouseButtonLeft *MouseButton = getMouseButton("left")
+ MouseButtonRight = getMouseButton("right")
+ MouseButtonMiddle = getMouseButton("middle")
+)
+
+func getKeyboardModifier(in string) *KeyboardModifier {
+ v := KeyboardModifier(in)
+ return &v
+}
+
+type KeyboardModifier string
+
+var (
+ KeyboardModifierAlt *KeyboardModifier = getKeyboardModifier("Alt")
+ KeyboardModifierControl = getKeyboardModifier("Control")
+ KeyboardModifierControlOrMeta = getKeyboardModifier("ControlOrMeta")
+ KeyboardModifierMeta = getKeyboardModifier("Meta")
+ KeyboardModifierShift = getKeyboardModifier("Shift")
+)
+
+func getScreenshotAnimations(in string) *ScreenshotAnimations {
+ v := ScreenshotAnimations(in)
+ return &v
+}
+
+type ScreenshotAnimations string
+
+var (
+ ScreenshotAnimationsDisabled *ScreenshotAnimations = getScreenshotAnimations("disabled")
+ ScreenshotAnimationsAllow = getScreenshotAnimations("allow")
+)
+
+func getScreenshotCaret(in string) *ScreenshotCaret {
+ v := ScreenshotCaret(in)
+ return &v
+}
+
+type ScreenshotCaret string
+
+var (
+ ScreenshotCaretHide *ScreenshotCaret = getScreenshotCaret("hide")
+ ScreenshotCaretInitial = getScreenshotCaret("initial")
+)
+
+func getScreenshotScale(in string) *ScreenshotScale {
+ v := ScreenshotScale(in)
+ return &v
+}
+
+type ScreenshotScale string
+
+var (
+ ScreenshotScaleCss *ScreenshotScale = getScreenshotScale("css")
+ ScreenshotScaleDevice = getScreenshotScale("device")
+)
+
+func getScreenshotType(in string) *ScreenshotType {
+ v := ScreenshotType(in)
+ return &v
+}
+
+type ScreenshotType string
+
+var (
+ ScreenshotTypePng *ScreenshotType = getScreenshotType("png")
+ ScreenshotTypeJpeg = getScreenshotType("jpeg")
+)
+
+func getWaitForSelectorState(in string) *WaitForSelectorState {
+ v := WaitForSelectorState(in)
+ return &v
+}
+
+type WaitForSelectorState string
+
+var (
+ WaitForSelectorStateAttached *WaitForSelectorState = getWaitForSelectorState("attached")
+ WaitForSelectorStateDetached = getWaitForSelectorState("detached")
+ WaitForSelectorStateVisible = getWaitForSelectorState("visible")
+ WaitForSelectorStateHidden = getWaitForSelectorState("hidden")
+)
+
+func getWaitUntilState(in string) *WaitUntilState {
+ v := WaitUntilState(in)
+ return &v
+}
+
+type WaitUntilState string
+
+var (
+ WaitUntilStateLoad *WaitUntilState = getWaitUntilState("load")
+ WaitUntilStateDomcontentloaded = getWaitUntilState("domcontentloaded")
+ WaitUntilStateNetworkidle = getWaitUntilState("networkidle")
+ WaitUntilStateCommit = getWaitUntilState("commit")
+)
+
+func getLoadState(in string) *LoadState {
+ v := LoadState(in)
+ return &v
+}
+
+type LoadState string
+
+var (
+ LoadStateLoad *LoadState = getLoadState("load")
+ LoadStateDomcontentloaded = getLoadState("domcontentloaded")
+ LoadStateNetworkidle = getLoadState("networkidle")
+)
+
+func getContrast(in string) *Contrast {
+ v := Contrast(in)
+ return &v
+}
+
+type Contrast string
+
+var (
+ ContrastNoPreference *Contrast = getContrast("no-preference")
+ ContrastMore = getContrast("more")
+ ContrastNoOverride = getContrast("no-override")
+)
+
+func getMedia(in string) *Media {
+ v := Media(in)
+ return &v
+}
+
+type Media string
+
+var (
+ MediaScreen *Media = getMedia("screen")
+ MediaPrint = getMedia("print")
+ MediaNoOverride = getMedia("no-override")
+)
+
+func getHttpCredentialsSend(in string) *HttpCredentialsSend {
+ v := HttpCredentialsSend(in)
+ return &v
+}
+
+type HttpCredentialsSend string
+
+var (
+ HttpCredentialsSendUnauthorized *HttpCredentialsSend = getHttpCredentialsSend("unauthorized")
+ HttpCredentialsSendAlways = getHttpCredentialsSend("always")
+)
diff --git a/vendor/github.com/playwright-community/playwright-go/generated-interfaces.go b/vendor/github.com/playwright-community/playwright-go/generated-interfaces.go
new file mode 100644
index 0000000..187dc91
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/generated-interfaces.go
@@ -0,0 +1,4658 @@
+package playwright
+
+// Exposes API that can be used for the Web API testing. This class is used for creating [APIRequestContext] instance
+// which in turn can be used for sending web requests. An instance of this class can be obtained via
+// [Playwright.Request]. For more information see [APIRequestContext].
+type APIRequest interface {
+ // Creates new instances of [APIRequestContext].
+ NewContext(options ...APIRequestNewContextOptions) (APIRequestContext, error)
+}
+
+// This API is used for the Web API testing. You can use it to trigger API endpoints, configure micro-services,
+// prepare environment or the service to your e2e test.
+// Each Playwright browser context has associated with it [APIRequestContext] instance which shares cookie storage
+// with the browser context and can be accessed via [BrowserContext.Request] or [Page.Request]. It is also possible to
+// create a new APIRequestContext instance manually by calling [APIRequest.NewContext].
+// **Cookie management**
+// [APIRequestContext] returned by [BrowserContext.Request] and [Page.Request] shares cookie storage with the
+// corresponding [BrowserContext]. Each API request will have `Cookie` header populated with the values from the
+// browser context. If the API response contains `Set-Cookie` header it will automatically update [BrowserContext]
+// cookies and requests made from the page will pick them up. This means that if you log in using this API, your e2e
+// test will be logged in and vice versa.
+// If you want API requests to not interfere with the browser cookies you should create a new [APIRequestContext] by
+// calling [APIRequest.NewContext]. Such `APIRequestContext` object will have its own isolated cookie storage.
+type APIRequestContext interface {
+ // Sends HTTP(S) [DELETE] request and returns its
+ // response. The method will populate request cookies from the context and update context cookies from the response.
+ // The method will automatically follow redirects.
+ //
+ // url: Target URL.
+ //
+ // [DELETE]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/DELETE
+ Delete(url string, options ...APIRequestContextDeleteOptions) (APIResponse, error)
+
+ // All responses returned by [APIRequestContext.Get] and similar methods are stored in the memory, so that you can
+ // later call [APIResponse.Body].This method discards all its resources, calling any method on disposed
+ // [APIRequestContext] will throw an exception.
+ Dispose(options ...APIRequestContextDisposeOptions) error
+
+ // Sends HTTP(S) request and returns its response. The method will populate request cookies from the context and
+ // update context cookies from the response. The method will automatically follow redirects.
+ //
+ // urlOrRequest: Target URL or Request to get all parameters from.
+ Fetch(urlOrRequest interface{}, options ...APIRequestContextFetchOptions) (APIResponse, error)
+
+ // Sends HTTP(S) [GET] request and returns its
+ // response. The method will populate request cookies from the context and update context cookies from the response.
+ // The method will automatically follow redirects.
+ //
+ // url: Target URL.
+ //
+ // [GET]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/GET
+ Get(url string, options ...APIRequestContextGetOptions) (APIResponse, error)
+
+ // Sends HTTP(S) [HEAD] request and returns its
+ // response. The method will populate request cookies from the context and update context cookies from the response.
+ // The method will automatically follow redirects.
+ //
+ // url: Target URL.
+ //
+ // [HEAD]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/HEAD
+ Head(url string, options ...APIRequestContextHeadOptions) (APIResponse, error)
+
+ // Sends HTTP(S) [PATCH] request and returns its
+ // response. The method will populate request cookies from the context and update context cookies from the response.
+ // The method will automatically follow redirects.
+ //
+ // url: Target URL.
+ //
+ // [PATCH]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PATCH
+ Patch(url string, options ...APIRequestContextPatchOptions) (APIResponse, error)
+
+ // Sends HTTP(S) [POST] request and returns its
+ // response. The method will populate request cookies from the context and update context cookies from the response.
+ // The method will automatically follow redirects.
+ //
+ // url: Target URL.
+ //
+ // [POST]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST
+ Post(url string, options ...APIRequestContextPostOptions) (APIResponse, error)
+
+ // Sends HTTP(S) [PUT] request and returns its
+ // response. The method will populate request cookies from the context and update context cookies from the response.
+ // The method will automatically follow redirects.
+ //
+ // url: Target URL.
+ //
+ // [PUT]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT
+ Put(url string, options ...APIRequestContextPutOptions) (APIResponse, error)
+
+ // Returns storage state for this request context, contains current cookies and local storage snapshot if it was
+ // passed to the constructor.
+ StorageState(path ...string) (*StorageState, error)
+}
+
+// [APIResponse] class represents responses returned by [APIRequestContext.Get] and similar methods.
+type APIResponse interface {
+ // Returns the buffer with response body.
+ Body() ([]byte, error)
+
+ // Disposes the body of this response. If not called then the body will stay in memory until the context closes.
+ Dispose() error
+
+ // An object with all the response HTTP headers associated with this response.
+ Headers() map[string]string
+
+ // An array with all the response HTTP headers associated with this response. Header names are not lower-cased.
+ // Headers with multiple entries, such as `Set-Cookie`, appear in the array multiple times.
+ HeadersArray() []NameValue
+
+ // Returns the JSON representation of response body.
+ // This method will throw if the response body is not parsable via `JSON.parse`.
+ JSON(v interface{}) error
+
+ // Contains a boolean stating whether the response was successful (status in the range 200-299) or not.
+ Ok() bool
+
+ // Contains the status code of the response (e.g., 200 for a success).
+ Status() int
+
+ // Contains the status text of the response (e.g. usually an "OK" for a success).
+ StatusText() string
+
+ // Returns the text representation of response body.
+ Text() (string, error)
+
+ // Contains the URL of the response.
+ URL() string
+}
+
+// The [APIResponseAssertions] class provides assertion methods that can be used to make assertions about the
+// [APIResponse] in the tests.
+type APIResponseAssertions interface {
+ // Makes the assertion check for the opposite condition. For example, this code tests that the response status is not
+ // successful:
+ Not() APIResponseAssertions
+
+ // Ensures the response status code is within `200..299` range.
+ ToBeOK() error
+}
+
+// A Browser is created via [BrowserType.Launch]. An example of using a [Browser] to create a [Page]:
+type Browser interface {
+ EventEmitter
+ // Emitted when Browser gets disconnected from the browser application. This might happen because of one of the
+ // following:
+ // - Browser application is closed or crashed.
+ // - The [Browser.Close] method was called.
+ OnDisconnected(fn func(Browser))
+
+ // Get the browser type (chromium, firefox or webkit) that the browser belongs to.
+ BrowserType() BrowserType
+
+ // In case this browser is obtained using [BrowserType.Launch], closes the browser and all of its pages (if any were
+ // opened).
+ // In case this browser is connected to, clears all created contexts belonging to this browser and disconnects from
+ // the browser server.
+ // **NOTE** This is similar to force-quitting the browser. To close pages gracefully and ensure you receive page close
+ // events, call [BrowserContext.Close] on any [BrowserContext] instances you explicitly created earlier using
+ // [Browser.NewContext] **before** calling [Browser.Close].
+ // The [Browser] object itself is considered to be disposed and cannot be used anymore.
+ Close(options ...BrowserCloseOptions) error
+
+ // Returns an array of all open browser contexts. In a newly created browser, this will return zero browser contexts.
+ Contexts() []BrowserContext
+
+ // Indicates that the browser is connected.
+ IsConnected() bool
+
+ // **NOTE** CDP Sessions are only supported on Chromium-based browsers.
+ // Returns the newly created browser session.
+ NewBrowserCDPSession() (CDPSession, error)
+
+ // Creates a new browser context. It won't share cookies/cache with other browser contexts.
+ // **NOTE** If directly using this method to create [BrowserContext]s, it is best practice to explicitly close the
+ // returned context via [BrowserContext.Close] when your code is done with the [BrowserContext], and before calling
+ // [Browser.Close]. This will ensure the `context` is closed gracefully and any artifacts—like HARs and videos—are
+ // fully flushed and saved.
+ NewContext(options ...BrowserNewContextOptions) (BrowserContext, error)
+
+ // Creates a new page in a new browser context. Closing this page will close the context as well.
+ // This is a convenience API that should only be used for the single-page scenarios and short snippets. Production
+ // code and testing frameworks should explicitly create [Browser.NewContext] followed by the [BrowserContext.NewPage]
+ // to control their exact life times.
+ NewPage(options ...BrowserNewPageOptions) (Page, error)
+
+ // **NOTE** This API controls
+ // [Chromium Tracing] which is a low-level
+ // chromium-specific debugging tool. API to control [Playwright Tracing] could be found
+ // [here].
+ // You can use [Browser.StartTracing] and [Browser.StopTracing] to create a trace file that can be opened in Chrome
+ // DevTools performance panel.
+ //
+ // [Chromium Tracing]: https://www.chromium.org/developers/how-tos/trace-event-profiling-tool
+ // [Playwright Tracing]: ../trace-viewer
+ // [here]: ./class-tracing
+ StartTracing(options ...BrowserStartTracingOptions) error
+
+ // **NOTE** This API controls
+ // [Chromium Tracing] which is a low-level
+ // chromium-specific debugging tool. API to control [Playwright Tracing] could be found
+ // [here].
+ // Returns the buffer with trace data.
+ //
+ // [Chromium Tracing]: https://www.chromium.org/developers/how-tos/trace-event-profiling-tool
+ // [Playwright Tracing]: ../trace-viewer
+ // [here]: ./class-tracing
+ StopTracing() ([]byte, error)
+
+ // Returns the browser version.
+ Version() string
+}
+
+// BrowserContexts provide a way to operate multiple independent browser sessions.
+// If a page opens another page, e.g. with a `window.open` call, the popup will belong to the parent page's browser
+// context.
+// Playwright allows creating isolated non-persistent browser contexts with [Browser.NewContext] method.
+// Non-persistent browser contexts don't write any browsing data to disk.
+type BrowserContext interface {
+ EventEmitter
+ // **NOTE** Only works with Chromium browser's persistent context.
+ // Emitted when new background page is created in the context.
+ OnBackgroundPage(fn func(Page))
+
+ // Playwright has ability to mock clock and passage of time.
+ Clock() Clock
+
+ // Emitted when Browser context gets closed. This might happen because of one of the following:
+ // - Browser context is closed.
+ // - Browser application is closed or crashed.
+ // - The [Browser.Close] method was called.
+ OnClose(fn func(BrowserContext))
+
+ // Emitted when JavaScript within the page calls one of console API methods, e.g. `console.log` or `console.dir`.
+ // The arguments passed into `console.log` and the page are available on the [ConsoleMessage] event handler argument.
+ OnConsole(fn func(ConsoleMessage))
+
+ // Emitted when a JavaScript dialog appears, such as `alert`, `prompt`, `confirm` or `beforeunload`. Listener **must**
+ // either [Dialog.Accept] or [Dialog.Dismiss] the dialog - otherwise the page will
+ // [freeze] waiting for the dialog,
+ // and actions like click will never finish.
+ //
+ // [freeze]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop#never_blocking
+ OnDialog(fn func(Dialog))
+
+ // The event is emitted when a new Page is created in the BrowserContext. The page may still be loading. The event
+ // will also fire for popup pages. See also [Page.OnPopup] to receive events about popups relevant to a specific page.
+ // The earliest moment that page is available is when it has navigated to the initial url. For example, when opening a
+ // popup with `window.open('http://example.com')`, this event will fire when the network request to
+ // "http://example.com" is done and its response has started loading in the popup. If you would like to route/listen
+ // to this network request, use [BrowserContext.Route] and [BrowserContext.OnRequest] respectively instead of similar
+ // methods on the [Page].
+ // **NOTE** Use [Page.WaitForLoadState] to wait until the page gets to a particular state (you should not need it in
+ // most cases).
+ OnPage(fn func(Page))
+
+ // Emitted when exception is unhandled in any of the pages in this context. To listen for errors from a particular
+ // page, use [Page.OnPageError] instead.
+ OnWebError(fn func(WebError))
+
+ // Emitted when a request is issued from any pages created through this context. The [request] object is read-only. To
+ // only listen for requests from a particular page, use [Page.OnRequest].
+ // In order to intercept and mutate requests, see [BrowserContext.Route] or [Page.Route].
+ OnRequest(fn func(Request))
+
+ // Emitted when a request fails, for example by timing out. To only listen for failed requests from a particular page,
+ // use [Page.OnRequestFailed].
+ // **NOTE** HTTP Error responses, such as 404 or 503, are still successful responses from HTTP standpoint, so request
+ // will complete with [BrowserContext.OnRequestFinished] event and not with [BrowserContext.OnRequestFailed].
+ OnRequestFailed(fn func(Request))
+
+ // Emitted when a request finishes successfully after downloading the response body. For a successful response, the
+ // sequence of events is `request`, `response` and `requestfinished`. To listen for successful requests from a
+ // particular page, use [Page.OnRequestFinished].
+ OnRequestFinished(fn func(Request))
+
+ // Emitted when [response] status and headers are received for a request. For a successful response, the sequence of
+ // events is `request`, `response` and `requestfinished`. To listen for response events from a particular page, use
+ // [Page.OnResponse].
+ OnResponse(fn func(Response))
+
+ // Adds cookies into this browser context. All pages within this context will have these cookies installed. Cookies
+ // can be obtained via [BrowserContext.Cookies].
+ AddCookies(cookies []OptionalCookie) error
+
+ // Adds a script which would be evaluated in one of the following scenarios:
+ // - Whenever a page is created in the browser context or is navigated.
+ // - Whenever a child frame is attached or navigated in any page in the browser context. In this case, the script is
+ // evaluated in the context of the newly attached frame.
+ // The script is evaluated after the document was created but before any of its scripts were run. This is useful to
+ // amend the JavaScript environment, e.g. to seed `Math.random`.
+ //
+ // script: Script to be evaluated in all pages in the browser context.
+ AddInitScript(script Script) error
+
+ // **NOTE** Background pages are only supported on Chromium-based browsers.
+ // All existing background pages in the context.
+ BackgroundPages() []Page
+
+ // Returns the browser instance of the context. If it was launched as a persistent context null gets returned.
+ Browser() Browser
+
+ // Removes cookies from context. Accepts optional filter.
+ ClearCookies(options ...BrowserContextClearCookiesOptions) error
+
+ // Clears all permission overrides for the browser context.
+ ClearPermissions() error
+
+ // Closes the browser context. All the pages that belong to the browser context will be closed.
+ // **NOTE** The default browser context cannot be closed.
+ Close(options ...BrowserContextCloseOptions) error
+
+ // If no URLs are specified, this method returns all cookies. If URLs are specified, only cookies that affect those
+ // URLs are returned.
+ Cookies(urls ...string) ([]Cookie, error)
+
+ // The method adds a function called “[object Object]” on the `window` object of every frame in every page in the
+ // context. When called, the function executes “[object Object]” and returns a [Promise] which resolves to the return
+ // value of “[object Object]”. If the “[object Object]” returns a [Promise], it will be awaited.
+ // The first argument of the “[object Object]” function contains information about the caller: `{ browserContext:
+ // BrowserContext, page: Page, frame: Frame }`.
+ // See [Page.ExposeBinding] for page-only version.
+ //
+ // 1. name: Name of the function on the window object.
+ // 2. binding: Callback function that will be called in the Playwright's context.
+ ExposeBinding(name string, binding BindingCallFunction, handle ...bool) error
+
+ // The method adds a function called “[object Object]” on the `window` object of every frame in every page in the
+ // context. When called, the function executes “[object Object]” and returns a [Promise] which resolves to the return
+ // value of “[object Object]”.
+ // If the “[object Object]” returns a [Promise], it will be awaited.
+ // See [Page.ExposeFunction] for page-only version.
+ //
+ // 1. name: Name of the function on the window object.
+ // 2. binding: Callback function that will be called in the Playwright's context.
+ ExposeFunction(name string, binding ExposedFunction) error
+
+ // Grants specified permissions to the browser context. Only grants corresponding permissions to the given origin if
+ // specified.
+ //
+ // permissions: A list of permissions to grant.
+ //
+ // **NOTE** Supported permissions differ between browsers, and even between different versions of the same browser.
+ // Any permission may stop working after an update.
+ //
+ // Here are some permissions that may be supported by some browsers:
+ // - `'accelerometer'`
+ // - `'ambient-light-sensor'`
+ // - `'background-sync'`
+ // - `'camera'`
+ // - `'clipboard-read'`
+ // - `'clipboard-write'`
+ // - `'geolocation'`
+ // - `'gyroscope'`
+ // - `'magnetometer'`
+ // - `'microphone'`
+ // - `'midi-sysex'` (system-exclusive midi)
+ // - `'midi'`
+ // - `'notifications'`
+ // - `'payment-handler'`
+ // - `'storage-access'`
+ GrantPermissions(permissions []string, options ...BrowserContextGrantPermissionsOptions) error
+
+ // **NOTE** CDP sessions are only supported on Chromium-based browsers.
+ // Returns the newly created session.
+ //
+ // page: Target to create new session for. For backwards-compatibility, this parameter is named `page`, but it can be a
+ // `Page` or `Frame` type.
+ NewCDPSession(page interface{}) (CDPSession, error)
+
+ // Creates a new page in the browser context.
+ NewPage() (Page, error)
+
+ // Returns all open pages in the context.
+ Pages() []Page
+
+ // API testing helper associated with this context. Requests made with this API will use context cookies.
+ Request() APIRequestContext
+
+ // Routing provides the capability to modify network requests that are made by any page in the browser context. Once
+ // route is enabled, every request matching the url pattern will stall unless it's continued, fulfilled or aborted.
+ // **NOTE** [BrowserContext.Route] will not intercept requests intercepted by Service Worker. See
+ // [this] issue. We recommend disabling Service Workers when
+ // using request interception by setting “[object Object]” to `block`.
+ //
+ // 1. url: A glob pattern, regex pattern, or predicate that receives a [URL] to match during routing. If “[object Object]” is
+ // set in the context options and the provided URL is a string that does not start with `*`, it is resolved using the
+ // [`new URL()`](https://developer.mozilla.org/en-US/docs/Web/API/URL/URL) constructor.
+ // 2. handler: handler function to route the request.
+ //
+ // [this]: https://github.com/microsoft/playwright/issues/1090
+ Route(url interface{}, handler routeHandler, times ...int) error
+
+ // If specified the network requests that are made in the context will be served from the HAR file. Read more about
+ // [Replaying from HAR].
+ // Playwright will not serve requests intercepted by Service Worker from the HAR file. See
+ // [this] issue. We recommend disabling Service Workers when
+ // using request interception by setting “[object Object]” to `block`.
+ //
+ // har: Path to a [HAR](http://www.softwareishard.com/blog/har-12-spec) file with prerecorded network data. If `path` is a
+ // relative path, then it is resolved relative to the current working directory.
+ //
+ // [Replaying from HAR]: https://playwright.dev/docs/mock#replaying-from-har
+ // [this]: https://github.com/microsoft/playwright/issues/1090
+ RouteFromHAR(har string, options ...BrowserContextRouteFromHAROptions) error
+
+ // This method allows to modify websocket connections that are made by any page in the browser context.
+ // Note that only `WebSocket`s created after this method was called will be routed. It is recommended to call this
+ // method before creating any pages.
+ //
+ // 1. url: Only WebSockets with the url matching this pattern will be routed. A string pattern can be relative to the
+ // “[object Object]” context option.
+ // 2. handler: Handler function to route the WebSocket.
+ RouteWebSocket(url interface{}, handler func(WebSocketRoute)) error
+
+ // **NOTE** Service workers are only supported on Chromium-based browsers.
+ // All existing service workers in the context.
+ ServiceWorkers() []Worker
+
+ // This setting will change the default maximum navigation time for the following methods and related shortcuts:
+ // - [Page.GoBack]
+ // - [Page.GoForward]
+ // - [Page.Goto]
+ // - [Page.Reload]
+ // - [Page.SetContent]
+ // - [Page.ExpectNavigation]
+ // **NOTE** [Page.SetDefaultNavigationTimeout] and [Page.SetDefaultTimeout] take priority over
+ // [BrowserContext.SetDefaultNavigationTimeout].
+ //
+ // timeout: Maximum navigation time in milliseconds
+ SetDefaultNavigationTimeout(timeout float64)
+
+ // This setting will change the default maximum time for all the methods accepting “[object Object]” option.
+ // **NOTE** [Page.SetDefaultNavigationTimeout], [Page.SetDefaultTimeout] and
+ // [BrowserContext.SetDefaultNavigationTimeout] take priority over [BrowserContext.SetDefaultTimeout].
+ //
+ // timeout: Maximum time in milliseconds. Pass `0` to disable timeout.
+ SetDefaultTimeout(timeout float64)
+
+ // The extra HTTP headers will be sent with every request initiated by any page in the context. These headers are
+ // merged with page-specific extra HTTP headers set with [Page.SetExtraHTTPHeaders]. If page overrides a particular
+ // header, page-specific header value will be used instead of the browser context header value.
+ // **NOTE** [BrowserContext.SetExtraHTTPHeaders] does not guarantee the order of headers in the outgoing requests.
+ //
+ // headers: An object containing additional HTTP headers to be sent with every request. All header values must be strings.
+ SetExtraHTTPHeaders(headers map[string]string) error
+
+ // Sets the context's geolocation. Passing `null` or `undefined` emulates position unavailable.
+ SetGeolocation(geolocation *Geolocation) error
+
+ //
+ // offline: Whether to emulate network being offline for the browser context.
+ SetOffline(offline bool) error
+
+ // Returns storage state for this browser context, contains current cookies, local storage snapshot and IndexedDB
+ // snapshot.
+ StorageState(path ...string) (*StorageState, error)
+
+ Tracing() Tracing
+
+ // Removes all routes created with [BrowserContext.Route] and [BrowserContext.RouteFromHAR].
+ UnrouteAll(options ...BrowserContextUnrouteAllOptions) error
+
+ // Removes a route created with [BrowserContext.Route]. When “[object Object]” is not specified, removes all routes
+ // for the “[object Object]”.
+ //
+ // 1. url: A glob pattern, regex pattern or predicate receiving [URL] used to register a routing with [BrowserContext.Route].
+ // 2. handler: Optional handler function used to register a routing with [BrowserContext.Route].
+ Unroute(url interface{}, handler ...routeHandler) error
+
+ // Performs action and waits for a [ConsoleMessage] to be logged by in the pages in the context. If predicate is
+ // provided, it passes [ConsoleMessage] value into the `predicate` function and waits for `predicate(message)` to
+ // return a truthy value. Will throw an error if the page is closed before the [BrowserContext.OnConsole] event is
+ // fired.
+ ExpectConsoleMessage(cb func() error, options ...BrowserContextExpectConsoleMessageOptions) (ConsoleMessage, error)
+
+ // Waits for event to fire and passes its value into the predicate function. Returns when the predicate returns truthy
+ // value. Will throw an error if the context closes before the event is fired. Returns the event data value.
+ //
+ // event: Event name, same one would pass into `browserContext.on(event)`.
+ ExpectEvent(event string, cb func() error, options ...BrowserContextExpectEventOptions) (interface{}, error)
+
+ // Performs action and waits for a new [Page] to be created in the context. If predicate is provided, it passes [Page]
+ // value into the `predicate` function and waits for `predicate(event)` to return a truthy value. Will throw an error
+ // if the context closes before new [Page] is created.
+ ExpectPage(cb func() error, options ...BrowserContextExpectPageOptions) (Page, error)
+
+ // **NOTE** In most cases, you should use [BrowserContext.ExpectEvent].
+ // Waits for given `event` to fire. If predicate is provided, it passes event's value into the `predicate` function
+ // and waits for `predicate(event)` to return a truthy value. Will throw an error if the browser context is closed
+ // before the `event` is fired.
+ //
+ // event: Event name, same one typically passed into `*.on(event)`.
+ WaitForEvent(event string, options ...BrowserContextWaitForEventOptions) (interface{}, error)
+}
+
+// BrowserType provides methods to launch a specific browser instance or connect to an existing one. The following is
+// a typical example of using Playwright to drive automation:
+type BrowserType interface {
+ // This method attaches Playwright to an existing browser instance created via `BrowserType.launchServer` in Node.js.
+ // **NOTE** The major and minor version of the Playwright instance that connects needs to match the version of
+ // Playwright that launches the browser (1.2.3 → is compatible with 1.2.x).
+ //
+ // wsEndpoint: A Playwright browser websocket endpoint to connect to. You obtain this endpoint via `BrowserServer.wsEndpoint`.
+ Connect(wsEndpoint string, options ...BrowserTypeConnectOptions) (Browser, error)
+
+ // This method attaches Playwright to an existing browser instance using the Chrome DevTools Protocol.
+ // The default browser context is accessible via [Browser.Contexts].
+ // **NOTE** Connecting over the Chrome DevTools Protocol is only supported for Chromium-based browsers.
+ // **NOTE** This connection is significantly lower fidelity than the Playwright protocol connection via
+ // [BrowserType.Connect]. If you are experiencing issues or attempting to use advanced functionality, you probably
+ // want to use [BrowserType.Connect].
+ //
+ // endpointURL: A CDP websocket endpoint or http url to connect to. For example `http://localhost:9222/` or
+ // `ws://127.0.0.1:9222/devtools/browser/387adf4c-243f-4051-a181-46798f4a46f4`.
+ ConnectOverCDP(endpointURL string, options ...BrowserTypeConnectOverCDPOptions) (Browser, error)
+
+ // A path where Playwright expects to find a bundled browser executable.
+ ExecutablePath() string
+
+ // Returns the browser instance.
+ //
+ // [Chrome Canary]: https://www.google.com/chrome/browser/canary.html
+ // [Dev Channel]: https://www.chromium.org/getting-involved/dev-channel
+ // [this article]: https://www.howtogeek.com/202825/what%E2%80%99s-the-difference-between-chromium-and-chrome/
+ // [This article]: https://chromium.googlesource.com/chromium/src/+/lkgr/docs/chromium_browser_vs_google_chrome.md
+ Launch(options ...BrowserTypeLaunchOptions) (Browser, error)
+
+ // Returns the persistent browser context instance.
+ // Launches browser that uses persistent storage located at “[object Object]” and returns the only context. Closing
+ // this context will automatically close the browser.
+ //
+ // userDataDir: Path to a User Data Directory, which stores browser session data like cookies and local storage. Pass an empty
+ // string to create a temporary directory.
+ //
+ // More details for
+ // [Chromium](https://chromium.googlesource.com/chromium/src/+/master/docs/user_data_dir.md#introduction) and
+ // [Firefox](https://wiki.mozilla.org/Firefox/CommandLineOptions#User_profile). Chromium's user data directory is the
+ // **parent** directory of the "Profile Path" seen at `chrome://version`.
+ //
+ // Note that browsers do not allow launching multiple instances with the same User Data Directory.
+ LaunchPersistentContext(userDataDir string, options ...BrowserTypeLaunchPersistentContextOptions) (BrowserContext, error)
+
+ // Returns browser name. For example: `chromium`, `webkit` or `firefox`.
+ Name() string
+}
+
+// The `CDPSession` instances are used to talk raw Chrome Devtools Protocol:
+// - protocol methods can be called with `session.send` method.
+// - protocol events can be subscribed to with `session.on` method.
+//
+// Useful links:
+// - Documentation on DevTools Protocol can be found here:
+// [DevTools Protocol Viewer].
+// - Getting Started with DevTools Protocol:
+// https://github.com/aslushnikov/getting-started-with-cdp/blob/master/README.md
+//
+// [DevTools Protocol Viewer]: https://chromedevtools.github.io/devtools-protocol/
+type CDPSession interface {
+ EventEmitter
+ // Detaches the CDPSession from the target. Once detached, the CDPSession object won't emit any events and can't be
+ // used to send messages.
+ Detach() error
+
+ //
+ // 1. method: Protocol method name.
+ // 2. params: Optional method parameters.
+ Send(method string, params map[string]interface{}) (interface{}, error)
+}
+
+// Accurately simulating time-dependent behavior is essential for verifying the correctness of applications. Learn
+// more about [clock emulation].
+// Note that clock is installed for the entire [BrowserContext], so the time in all the pages and iframes is
+// controlled by the same clock.
+//
+// [clock emulation]: https://playwright.dev/docs/clock
+type Clock interface {
+ // Advance the clock by jumping forward in time. Only fires due timers at most once. This is equivalent to user
+ // closing the laptop lid for a while and reopening it later, after given time.
+ //
+ // ticks: Time may be the number of milliseconds to advance the clock by or a human-readable string. Valid string formats are
+ // "08" for eight seconds, "01:00" for one minute and "02:34:10" for two hours, 34 minutes and ten seconds.
+ FastForward(ticks interface{}) error
+
+ // Install fake implementations for the following time-related functions:
+ // - `Date`
+ // - `setTimeout`
+ // - `clearTimeout`
+ // - `setInterval`
+ // - `clearInterval`
+ // - `requestAnimationFrame`
+ // - `cancelAnimationFrame`
+ // - `requestIdleCallback`
+ // - `cancelIdleCallback`
+ // - `performance`
+ // Fake timers are used to manually control the flow of time in tests. They allow you to advance time, fire timers,
+ // and control the behavior of time-dependent functions. See [Clock.RunFor] and [Clock.FastForward] for more
+ // information.
+ Install(options ...ClockInstallOptions) error
+
+ // Advance the clock, firing all the time-related callbacks.
+ //
+ // ticks: Time may be the number of milliseconds to advance the clock by or a human-readable string. Valid string formats are
+ // "08" for eight seconds, "01:00" for one minute and "02:34:10" for two hours, 34 minutes and ten seconds.
+ RunFor(ticks interface{}) error
+
+ // Advance the clock by jumping forward in time and pause the time. Once this method is called, no timers are fired
+ // unless [Clock.RunFor], [Clock.FastForward], [Clock.PauseAt] or [Clock.Resume] is called.
+ // Only fires due timers at most once. This is equivalent to user closing the laptop lid for a while and reopening it
+ // at the specified time and pausing.
+ //
+ // time: Time to pause at.
+ PauseAt(time interface{}) error
+
+ // Resumes timers. Once this method is called, time resumes flowing, timers are fired as usual.
+ Resume() error
+
+ // Makes `Date.now` and `new Date()` return fixed fake time at all times, keeps all the timers running.
+ // Use this method for simple scenarios where you only need to test with a predefined time. For more advanced
+ // scenarios, use [Clock.Install] instead. Read docs on [clock emulation] to learn more.
+ //
+ // time: Time to be set.
+ //
+ // [clock emulation]: https://playwright.dev/docs/clock
+ SetFixedTime(time interface{}) error
+
+ // Sets system time, but does not trigger any timers. Use this to test how the web page reacts to a time shift, for
+ // example switching from summer to winter time, or changing time zones.
+ //
+ // time: Time to be set.
+ SetSystemTime(time interface{}) error
+}
+
+// [ConsoleMessage] objects are dispatched by page via the [Page.OnConsole] event. For each console message logged in
+// the page there will be corresponding event in the Playwright context.
+type ConsoleMessage interface {
+ // List of arguments passed to a `console` function call. See also [Page.OnConsole].
+ Args() []JSHandle
+
+ Location() *ConsoleMessageLocation
+
+ // The page that produced this console message, if any.
+ Page() Page
+
+ // The text of the console message.
+ Text() string
+
+ // The text of the console message.
+ String() string
+
+ // One of the following values: `log`, `debug`, `info`, `error`, `warning`, `dir`, `dirxml`, `table`,
+ // `trace`, `clear`, `startGroup`, `startGroupCollapsed`, `endGroup`, `assert`, `profile`,
+ // `profileEnd`, `count`, `timeEnd`.
+ Type() string
+}
+
+// [Dialog] objects are dispatched by page via the [Page.OnDialog] event.
+// An example of using `Dialog` class:
+// **NOTE** Dialogs are dismissed automatically, unless there is a [Page.OnDialog] listener. When listener is present,
+// it **must** either [Dialog.Accept] or [Dialog.Dismiss] the dialog - otherwise the page will
+// [freeze] waiting for the dialog,
+// and actions like click will never finish.
+//
+// [freeze]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop#never_blocking
+type Dialog interface {
+ // Returns when the dialog has been accepted.
+ Accept(promptText ...string) error
+
+ // If dialog is prompt, returns default prompt value. Otherwise, returns empty string.
+ DefaultValue() string
+
+ // Returns when the dialog has been dismissed.
+ Dismiss() error
+
+ // A message displayed in the dialog.
+ Message() string
+
+ // The page that initiated this dialog, if available.
+ Page() Page
+
+ // Returns dialog's type, can be one of `alert`, `beforeunload`, `confirm` or `prompt`.
+ Type() string
+}
+
+// [Download] objects are dispatched by page via the [Page.OnDownload] event.
+// All the downloaded files belonging to the browser context are deleted when the browser context is closed.
+// Download event is emitted once the download starts. Download path becomes available once download completes.
+type Download interface {
+ // Cancels a download. Will not fail if the download is already finished or canceled. Upon successful cancellations,
+ // `download.failure()` would resolve to `canceled`.
+ Cancel() error
+
+ // Deletes the downloaded file. Will wait for the download to finish if necessary.
+ Delete() error
+
+ // Returns download error if any. Will wait for the download to finish if necessary.
+ Failure() error
+
+ // Get the page that the download belongs to.
+ Page() Page
+
+ // Returns path to the downloaded file for a successful download, or throws for a failed/canceled download. The method
+ // will wait for the download to finish if necessary. The method throws when connected remotely.
+ // Note that the download's file name is a random GUID, use [Download.SuggestedFilename] to get suggested file name.
+ Path() (string, error)
+
+ // Copy the download to a user-specified path. It is safe to call this method while the download is still in progress.
+ // Will wait for the download to finish if necessary.
+ //
+ // path: Path where the download should be copied.
+ SaveAs(path string) error
+
+ // Returns suggested filename for this download. It is typically computed by the browser from the
+ // [`Content-Disposition`] response
+ // header or the `download` attribute. See the spec on [whatwg].
+ // Different browsers can use different logic for computing it.
+ //
+ // [`Content-Disposition`]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition
+ // [whatwg]: https://html.spec.whatwg.org/#downloading-resources
+ SuggestedFilename() string
+
+ // Returns downloaded url.
+ URL() string
+
+ String() string
+}
+
+// ElementHandle represents an in-page DOM element. ElementHandles can be created with the [Page.QuerySelector]
+//
+// method.
+// **NOTE** The use of ElementHandle is discouraged, use [Locator] objects and web-first assertions instead.
+// ElementHandle prevents DOM element from garbage collection unless the handle is disposed with [JSHandle.Dispose].
+// ElementHandles are auto-disposed when their origin frame gets navigated.
+// ElementHandle instances can be used as an argument in [Page.EvalOnSelector] and [Page.Evaluate] methods.
+// The difference between the [Locator] and ElementHandle is that the ElementHandle points to a particular element,
+// while [Locator] captures the logic of how to retrieve an element.
+// In the example below, handle points to a particular DOM element on page. If that element changes text or is used by
+// React to render an entirely different component, handle is still pointing to that very DOM element. This can lead
+// to unexpected behaviors.
+// With the locator, every time the `element` is used, up-to-date DOM element is located in the page using the
+// selector. So in the snippet below, underlying DOM element is going to be located twice.
+type ElementHandle interface {
+ JSHandle
+ // This method returns the bounding box of the element, or `null` if the element is not visible. The bounding box is
+ // calculated relative to the main frame viewport - which is usually the same as the browser window.
+ // Scrolling affects the returned bounding box, similarly to
+ // [Element.GetBoundingClientRect].
+ // That means `x` and/or `y` may be negative.
+ // Elements from child frames return the bounding box relative to the main frame, unlike the
+ // [Element.GetBoundingClientRect].
+ // Assuming the page is static, it is safe to use bounding box coordinates to perform input. For example, the
+ // following snippet should click the center of the element.
+ //
+ // [Element.GetBoundingClientRect]: https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect
+ // [Element.GetBoundingClientRect]: https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect
+ BoundingBox() (*Rect, error)
+
+ // This method checks the element by performing the following steps:
+ // 1. Ensure that element is a checkbox or a radio input. If not, this method throws. If the element is already
+ // checked, this method returns immediately.
+ // 2. Wait for [actionability] checks on the element, unless “[object Object]” option is set.
+ // 3. Scroll the element into view if needed.
+ // 4. Use [Page.Mouse] to click in the center of the element.
+ // 5. Ensure that the element is now checked. If not, this method throws.
+ // If the element is detached from the DOM at any moment during the action, this method throws.
+ // When all steps combined have not finished during the specified “[object Object]”, this method throws a
+ // [TimeoutError]. Passing zero timeout disables this.
+ //
+ // Deprecated: Use locator-based [Locator.Check] instead. Read more about [locators].
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [locators]: https://playwright.dev/docs/locators
+ Check(options ...ElementHandleCheckOptions) error
+
+ // This method clicks the element by performing the following steps:
+ // 1. Wait for [actionability] checks on the element, unless “[object Object]” option is set.
+ // 2. Scroll the element into view if needed.
+ // 3. Use [Page.Mouse] to click in the center of the element, or the specified “[object Object]”.
+ // 4. Wait for initiated navigations to either succeed or fail, unless “[object Object]” option is set.
+ // If the element is detached from the DOM at any moment during the action, this method throws.
+ // When all steps combined have not finished during the specified “[object Object]”, this method throws a
+ // [TimeoutError]. Passing zero timeout disables this.
+ //
+ // Deprecated: Use locator-based [Locator.Click] instead. Read more about [locators].
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [locators]: https://playwright.dev/docs/locators
+ Click(options ...ElementHandleClickOptions) error
+
+ // Returns the content frame for element handles referencing iframe nodes, or `null` otherwise
+ ContentFrame() (Frame, error)
+
+ // This method double clicks the element by performing the following steps:
+ // 1. Wait for [actionability] checks on the element, unless “[object Object]” option is set.
+ // 2. Scroll the element into view if needed.
+ // 3. Use [Page.Mouse] to double click in the center of the element, or the specified “[object Object]”.
+ // If the element is detached from the DOM at any moment during the action, this method throws.
+ // When all steps combined have not finished during the specified “[object Object]”, this method throws a
+ // [TimeoutError]. Passing zero timeout disables this.
+ // **NOTE** `elementHandle.dblclick()` dispatches two `click` events and a single `dblclick` event.
+ //
+ // Deprecated: Use locator-based [Locator.Dblclick] instead. Read more about [locators].
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [locators]: https://playwright.dev/docs/locators
+ Dblclick(options ...ElementHandleDblclickOptions) error
+
+ // The snippet below dispatches the `click` event on the element. Regardless of the visibility state of the element,
+ // `click` is dispatched. This is equivalent to calling
+ // [element.Click()].
+ //
+ // Deprecated: Use locator-based [Locator.DispatchEvent] instead. Read more about [locators].
+ //
+ // 1. typ: DOM event type: `"click"`, `"dragstart"`, etc.
+ // 2. eventInit: Optional event-specific initialization properties.
+ //
+ // [element.Click()]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/click
+ // [DeviceMotionEvent]: https://developer.mozilla.org/en-US/docs/Web/API/DeviceMotionEvent/DeviceMotionEvent
+ // [DeviceOrientationEvent]: https://developer.mozilla.org/en-US/docs/Web/API/DeviceOrientationEvent/DeviceOrientationEvent
+ // [DragEvent]: https://developer.mozilla.org/en-US/docs/Web/API/DragEvent/DragEvent
+ // [Event]: https://developer.mozilla.org/en-US/docs/Web/API/Event/Event
+ // [FocusEvent]: https://developer.mozilla.org/en-US/docs/Web/API/FocusEvent/FocusEvent
+ // [KeyboardEvent]: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/KeyboardEvent
+ // [MouseEvent]: https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/MouseEvent
+ // [PointerEvent]: https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/PointerEvent
+ // [TouchEvent]: https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent/TouchEvent
+ // [WheelEvent]: https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent/WheelEvent
+ // [locators]: https://playwright.dev/docs/locators
+ DispatchEvent(typ string, eventInit ...interface{}) error
+
+ // Returns the return value of “[object Object]”.
+ // The method finds an element matching the specified selector in the `ElementHandle`s subtree and passes it as a
+ // first argument to “[object Object]”. If no elements match the selector, the method throws an error.
+ // If “[object Object]” returns a [Promise], then [ElementHandle.EvalOnSelector] would wait for the promise to resolve
+ // and return its value.
+ //
+ // Deprecated: This method does not wait for the element to pass actionability checks and therefore can lead to the flaky tests. Use [Locator.Evaluate], other [Locator] helper methods or web-first assertions instead.
+ //
+ // 1. selector: A selector to query for.
+ // 2. expression: JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the
+ // function is automatically invoked.
+ // 3. arg: Optional argument to pass to “[object Object]”.
+ EvalOnSelector(selector string, expression string, arg ...interface{}) (interface{}, error)
+
+ // Returns the return value of “[object Object]”.
+ // The method finds all elements matching the specified selector in the `ElementHandle`'s subtree and passes an array
+ // of matched elements as a first argument to “[object Object]”.
+ // If “[object Object]” returns a [Promise], then [ElementHandle.EvalOnSelectorAll] would wait for the promise to
+ // resolve and return its value.
+ //
+ // Deprecated: In most cases, [Locator.EvaluateAll], other [Locator] helper methods and web-first assertions do a better job.
+ //
+ // 1. selector: A selector to query for.
+ // 2. expression: JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the
+ // function is automatically invoked.
+ // 3. arg: Optional argument to pass to “[object Object]”.
+ EvalOnSelectorAll(selector string, expression string, arg ...interface{}) (interface{}, error)
+
+ // This method waits for [actionability] checks, focuses the element, fills it and triggers an
+ // `input` event after filling. Note that you can pass an empty string to clear the input field.
+ // If the target element is not an `<input>`, `<textarea>` or `[contenteditable]` element, this method throws an
+ // error. However, if the element is inside the `<label>` element that has an associated
+ // [control], the control will be filled
+ // instead.
+ // To send fine-grained keyboard events, use [Locator.PressSequentially].
+ //
+ // Deprecated: Use locator-based [Locator.Fill] instead. Read more about [locators].
+ //
+ // value: Value to set for the `<input>`, `<textarea>` or `[contenteditable]` element.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [control]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/control
+ // [locators]: https://playwright.dev/docs/locators
+ Fill(value string, options ...ElementHandleFillOptions) error
+
+ // Calls [focus] on the element.
+ //
+ // Deprecated: Use locator-based [Locator.Focus] instead. Read more about [locators].
+ //
+ // [focus]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus
+ // [locators]: https://playwright.dev/docs/locators
+ Focus() error
+
+ // Returns element attribute value.
+ //
+ // Deprecated: Use locator-based [Locator.GetAttribute] instead. Read more about [locators].
+ //
+ // name: Attribute name to get the value for.
+ //
+ // [locators]: https://playwright.dev/docs/locators
+ GetAttribute(name string) (string, error)
+
+ // This method hovers over the element by performing the following steps:
+ // 1. Wait for [actionability] checks on the element, unless “[object Object]” option is set.
+ // 2. Scroll the element into view if needed.
+ // 3. Use [Page.Mouse] to hover over the center of the element, or the specified “[object Object]”.
+ // If the element is detached from the DOM at any moment during the action, this method throws.
+ // When all steps combined have not finished during the specified “[object Object]”, this method throws a
+ // [TimeoutError]. Passing zero timeout disables this.
+ //
+ // Deprecated: Use locator-based [Locator.Hover] instead. Read more about [locators].
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [locators]: https://playwright.dev/docs/locators
+ Hover(options ...ElementHandleHoverOptions) error
+
+ // Returns the `element.innerHTML`.
+ //
+ // Deprecated: Use locator-based [Locator.InnerHTML] instead. Read more about [locators].
+ //
+ // [locators]: https://playwright.dev/docs/locators
+ InnerHTML() (string, error)
+
+ // Returns the `element.innerText`.
+ //
+ // Deprecated: Use locator-based [Locator.InnerText] instead. Read more about [locators].
+ //
+ // [locators]: https://playwright.dev/docs/locators
+ InnerText() (string, error)
+
+ // Returns `input.value` for the selected `<input>` or `<textarea>` or `<select>` element.
+ // Throws for non-input elements. However, if the element is inside the `<label>` element that has an associated
+ // [control], returns the value of the
+ // control.
+ //
+ // Deprecated: Use locator-based [Locator.InputValue] instead. Read more about [locators].
+ //
+ // [control]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/control
+ // [locators]: https://playwright.dev/docs/locators
+ InputValue(options ...ElementHandleInputValueOptions) (string, error)
+
+ // Returns whether the element is checked. Throws if the element is not a checkbox or radio input.
+ //
+ // Deprecated: Use locator-based [Locator.IsChecked] instead. Read more about [locators].
+ //
+ // [locators]: https://playwright.dev/docs/locators
+ IsChecked() (bool, error)
+
+ // Returns whether the element is disabled, the opposite of [enabled].
+ //
+ // Deprecated: Use locator-based [Locator.IsDisabled] instead. Read more about [locators].
+ //
+ // [enabled]: https://playwright.dev/docs/actionability#enabled
+ // [locators]: https://playwright.dev/docs/locators
+ IsDisabled() (bool, error)
+
+ // Returns whether the element is [editable].
+ //
+ // Deprecated: Use locator-based [Locator.IsEditable] instead. Read more about [locators].
+ //
+ // [editable]: https://playwright.dev/docs/actionability#editable
+ // [locators]: https://playwright.dev/docs/locators
+ IsEditable() (bool, error)
+
+ // Returns whether the element is [enabled].
+ //
+ // Deprecated: Use locator-based [Locator.IsEnabled] instead. Read more about [locators].
+ //
+ // [enabled]: https://playwright.dev/docs/actionability#enabled
+ // [locators]: https://playwright.dev/docs/locators
+ IsEnabled() (bool, error)
+
+ // Returns whether the element is hidden, the opposite of [visible].
+ //
+ // Deprecated: Use locator-based [Locator.IsHidden] instead. Read more about [locators].
+ //
+ // [visible]: https://playwright.dev/docs/actionability#visible
+ // [locators]: https://playwright.dev/docs/locators
+ IsHidden() (bool, error)
+
+ // Returns whether the element is [visible].
+ //
+ // Deprecated: Use locator-based [Locator.IsVisible] instead. Read more about [locators].
+ //
+ // [visible]: https://playwright.dev/docs/actionability#visible
+ // [locators]: https://playwright.dev/docs/locators
+ IsVisible() (bool, error)
+
+ // Returns the frame containing the given element.
+ OwnerFrame() (Frame, error)
+
+ // Focuses the element, and then uses [Keyboard.Down] and [Keyboard.Up].
+ // “[object Object]” can specify the intended
+ // [keyboardEvent.Key] value or a single character
+ // to generate the text for. A superset of the “[object Object]” values can be found
+ // [here]. Examples of the keys are:
+ // `F1` - `F12`, `Digit0`- `Digit9`, `KeyA`- `KeyZ`, `Backquote`, `Minus`, `Equal`, `Backslash`, `Backspace`, `Tab`,
+ // `Delete`, `Escape`, `ArrowDown`, `End`, `Enter`, `Home`, `Insert`, `PageDown`, `PageUp`, `ArrowRight`, `ArrowUp`,
+ // etc.
+ // Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`,
+ // `ControlOrMeta`.
+ // Holding down `Shift` will type the text that corresponds to the “[object Object]” in the upper case.
+ // If “[object Object]” is a single character, it is case-sensitive, so the values `a` and `A` will generate different
+ // respective texts.
+ // Shortcuts such as `key: "Control+o"`, `key: "Control++` or `key: "Control+Shift+T"` are supported as well. When
+ // specified with the modifier, modifier is pressed and being held while the subsequent key is being pressed.
+ //
+ // Deprecated: Use locator-based [Locator.Press] instead. Read more about [locators].
+ //
+ // key: Name of the key to press or a character to generate, such as `ArrowLeft` or `a`.
+ //
+ // [keyboardEvent.Key]: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key
+ // [here]: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values
+ // [locators]: https://playwright.dev/docs/locators
+ Press(key string, options ...ElementHandlePressOptions) error
+
+ // The method finds an element matching the specified selector in the `ElementHandle`'s subtree. If no elements match
+ // the selector, returns `null`.
+ //
+ // Deprecated: Use locator-based [Page.Locator] instead. Read more about [locators].
+ //
+ // selector: A selector to query for.
+ //
+ // [locators]: https://playwright.dev/docs/locators
+ QuerySelector(selector string) (ElementHandle, error)
+
+ // The method finds all elements matching the specified selector in the `ElementHandle`s subtree. If no elements match
+ // the selector, returns empty array.
+ //
+ // Deprecated: Use locator-based [Page.Locator] instead. Read more about [locators].
+ //
+ // selector: A selector to query for.
+ //
+ // [locators]: https://playwright.dev/docs/locators
+ QuerySelectorAll(selector string) ([]ElementHandle, error)
+
+ // This method captures a screenshot of the page, clipped to the size and position of this particular element. If the
+ // element is covered by other elements, it will not be actually visible on the screenshot. If the element is a
+ // scrollable container, only the currently scrolled content will be visible on the screenshot.
+ // This method waits for the [actionability] checks, then scrolls element into view before taking
+ // a screenshot. If the element is detached from DOM, the method throws an error.
+ // Returns the buffer with the captured screenshot.
+ //
+ // Deprecated: Use locator-based [Locator.Screenshot] instead. Read more about [locators].
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [locators]: https://playwright.dev/docs/locators
+ Screenshot(options ...ElementHandleScreenshotOptions) ([]byte, error)
+
+ // This method waits for [actionability] checks, then tries to scroll element into view, unless
+ // it is completely visible as defined by
+ // [IntersectionObserver]'s `ratio`.
+ // Throws when `elementHandle` does not point to an element
+ // [connected] to a Document or a ShadowRoot.
+ // See [scrolling] for alternative ways to scroll.
+ //
+ // Deprecated: Use locator-based [Locator.ScrollIntoViewIfNeeded] instead. Read more about [locators].
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [IntersectionObserver]: https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API
+ // [connected]: https://developer.mozilla.org/en-US/docs/Web/API/Node/isConnected
+ // [scrolling]: https://playwright.dev/docs/input#scrolling
+ // [locators]: https://playwright.dev/docs/locators
+ ScrollIntoViewIfNeeded(options ...ElementHandleScrollIntoViewIfNeededOptions) error
+
+ // This method waits for [actionability] checks, waits until all specified options are present in
+ // the `<select>` element and selects these options.
+ // If the target element is not a `<select>` element, this method throws an error. However, if the element is inside
+ // the `<label>` element that has an associated
+ // [control], the control will be used
+ // instead.
+ // Returns the array of option values that have been successfully selected.
+ // Triggers a `change` and `input` event once all the provided options have been selected.
+ //
+ // Deprecated: Use locator-based [Locator.SelectOption] instead. Read more about [locators].
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [control]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/control
+ // [locators]: https://playwright.dev/docs/locators
+ SelectOption(values SelectOptionValues, options ...ElementHandleSelectOptionOptions) ([]string, error)
+
+ // This method waits for [actionability] checks, then focuses the element and selects all its
+ // text content.
+ // If the element is inside the `<label>` element that has an associated
+ // [control], focuses and selects text in
+ // the control instead.
+ //
+ // Deprecated: Use locator-based [Locator.SelectText] instead. Read more about [locators].
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [control]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/control
+ // [locators]: https://playwright.dev/docs/locators
+ SelectText(options ...ElementHandleSelectTextOptions) error
+
+ // This method checks or unchecks an element by performing the following steps:
+ // 1. Ensure that element is a checkbox or a radio input. If not, this method throws.
+ // 2. If the element already has the right checked state, this method returns immediately.
+ // 3. Wait for [actionability] checks on the matched element, unless “[object Object]” option
+ // is set. If the element is detached during the checks, the whole action is retried.
+ // 4. Scroll the element into view if needed.
+ // 5. Use [Page.Mouse] to click in the center of the element.
+ // 6. Ensure that the element is now checked or unchecked. If not, this method throws.
+ // When all steps combined have not finished during the specified “[object Object]”, this method throws a
+ // [TimeoutError]. Passing zero timeout disables this.
+ //
+ // Deprecated: Use locator-based [Locator.SetChecked] instead. Read more about [locators].
+ //
+ // checked: Whether to check or uncheck the checkbox.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [locators]: https://playwright.dev/docs/locators
+ SetChecked(checked bool, options ...ElementHandleSetCheckedOptions) error
+
+ // Sets the value of the file input to these file paths or files. If some of the `filePaths` are relative paths, then
+ // they are resolved relative to the current working directory. For empty array, clears the selected files. For inputs
+ // with a `[webkitdirectory]` attribute, only a single directory path is supported.
+ // This method expects [ElementHandle] to point to an
+ // [input element]. However, if the element is inside
+ // the `<label>` element that has an associated
+ // [control], targets the control instead.
+ //
+ // Deprecated: Use locator-based [Locator.SetInputFiles] instead. Read more about [locators].
+ //
+ // [input element]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input
+ // [control]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/control
+ // [locators]: https://playwright.dev/docs/locators
+ SetInputFiles(files interface{}, options ...ElementHandleSetInputFilesOptions) error
+
+ // This method taps the element by performing the following steps:
+ // 1. Wait for [actionability] checks on the element, unless “[object Object]” option is set.
+ // 2. Scroll the element into view if needed.
+ // 3. Use [Page.Touchscreen] to tap the center of the element, or the specified “[object Object]”.
+ // If the element is detached from the DOM at any moment during the action, this method throws.
+ // When all steps combined have not finished during the specified “[object Object]”, this method throws a
+ // [TimeoutError]. Passing zero timeout disables this.
+ // **NOTE** `elementHandle.tap()` requires that the `hasTouch` option of the browser context be set to true.
+ //
+ // Deprecated: Use locator-based [Locator.Tap] instead. Read more about [locators].
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [locators]: https://playwright.dev/docs/locators
+ Tap(options ...ElementHandleTapOptions) error
+
+ // Returns the `node.textContent`.
+ //
+ // Deprecated: Use locator-based [Locator.TextContent] instead. Read more about [locators].
+ //
+ // [locators]: https://playwright.dev/docs/locators
+ TextContent() (string, error)
+
+ // Focuses the element, and then sends a `keydown`, `keypress`/`input`, and `keyup` event for each character in the
+ // text.
+ // To press a special key, like `Control` or `ArrowDown`, use [ElementHandle.Press].
+ //
+ // 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].
+ //
+ // text: A text to type into a focused element.
+ Type(text string, options ...ElementHandleTypeOptions) error
+
+ // This method checks the element by performing the following steps:
+ // 1. Ensure that element is a checkbox or a radio input. If not, this method throws. If the element is already
+ // unchecked, this method returns immediately.
+ // 2. Wait for [actionability] checks on the element, unless “[object Object]” option is set.
+ // 3. Scroll the element into view if needed.
+ // 4. Use [Page.Mouse] to click in the center of the element.
+ // 5. Ensure that the element is now unchecked. If not, this method throws.
+ // If the element is detached from the DOM at any moment during the action, this method throws.
+ // When all steps combined have not finished during the specified “[object Object]”, this method throws a
+ // [TimeoutError]. Passing zero timeout disables this.
+ //
+ // Deprecated: Use locator-based [Locator.Uncheck] instead. Read more about [locators].
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [locators]: https://playwright.dev/docs/locators
+ Uncheck(options ...ElementHandleUncheckOptions) error
+
+ // Returns when the element satisfies the “[object Object]”.
+ // Depending on the “[object Object]” parameter, this method waits for one of the [actionability]
+ // checks to pass. This method throws when the element is detached while waiting, unless waiting for the `"hidden"`
+ // state.
+ // - `"visible"` Wait until the element is [visible].
+ // - `"hidden"` Wait until the element is [not visible] or not attached. Note that
+ // waiting for hidden does not throw when the element detaches.
+ // - `"stable"` Wait until the element is both [visible] and
+ // [stable].
+ // - `"enabled"` Wait until the element is [enabled].
+ // - `"disabled"` Wait until the element is [not enabled].
+ // - `"editable"` Wait until the element is [editable].
+ // If the element does not satisfy the condition for the “[object Object]” milliseconds, this method will throw.
+ //
+ // state: A state to wait for, see below for more details.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [visible]: https://playwright.dev/docs/actionability#visible
+ // [not visible]: https://playwright.dev/docs/actionability#visible
+ // [visible]: https://playwright.dev/docs/actionability#visible
+ // [stable]: https://playwright.dev/docs/actionability#stable
+ // [enabled]: https://playwright.dev/docs/actionability#enabled
+ // [not enabled]: https://playwright.dev/docs/actionability#enabled
+ // [editable]: https://playwright.dev/docs/actionability#editable
+ WaitForElementState(state ElementState, options ...ElementHandleWaitForElementStateOptions) error
+
+ // Returns element specified by selector when it satisfies “[object Object]” option. Returns `null` if waiting for
+ // `hidden` or `detached`.
+ // Wait for the “[object Object]” relative to the element handle to satisfy “[object Object]” option (either
+ // appear/disappear from dom, or become visible/hidden). If at the moment of calling the method “[object Object]”
+ // already satisfies the condition, the method will return immediately. If the selector doesn't satisfy the condition
+ // for the “[object Object]” milliseconds, the function will throw.
+ //
+ // Deprecated: Use web assertions that assert visibility or a locator-based [Locator.WaitFor] instead.
+ //
+ // selector: A selector to query for.
+ WaitForSelector(selector string, options ...ElementHandleWaitForSelectorOptions) (ElementHandle, error)
+}
+
+// [FileChooser] objects are dispatched by the page in the [Page.OnFileChooser] event.
+type FileChooser interface {
+ // Returns input element associated with this file chooser.
+ Element() ElementHandle
+
+ // Returns whether this file chooser accepts multiple files.
+ IsMultiple() bool
+
+ // Returns page this file chooser belongs to.
+ Page() Page
+
+ // Sets the value of the file input this chooser is associated with. If some of the `filePaths` are relative paths,
+ // then they are resolved relative to the current working directory. For empty array, clears the selected files.
+ SetFiles(files interface{}, options ...FileChooserSetFilesOptions) error
+}
+
+// At every point of time, page exposes its current frame tree via the [Page.MainFrame] and [Frame.ChildFrames]
+// methods.
+// [Frame] object's lifecycle is controlled by three events, dispatched on the page object:
+// - [Page.OnFrameAttached] - fired when the frame gets attached to the page. A Frame can be attached to the page
+// only once.
+// - [Page.OnFrameNavigated] - fired when the frame commits navigation to a different URL.
+// - [Page.OnFrameDetached] - fired when the frame gets detached from the page. A Frame can be detached from the
+// page only once.
+//
+// An example of dumping frame tree:
+type Frame interface {
+ // Returns the added tag when the script's onload fires or when the script content was injected into frame.
+ // Adds a `<script>` tag into the page with the desired url or content.
+ AddScriptTag(options FrameAddScriptTagOptions) (ElementHandle, error)
+
+ // Returns the added tag when the stylesheet's onload fires or when the CSS content was injected into frame.
+ // Adds a `<link rel="stylesheet">` tag into the page with the desired url or a `<style type="text/css">` tag with the
+ // content.
+ AddStyleTag(options FrameAddStyleTagOptions) (ElementHandle, error)
+
+ // This method checks an element matching “[object Object]” by performing the following steps:
+ // 1. Find an element matching “[object Object]”. If there is none, wait until a matching element is attached to
+ // the DOM.
+ // 2. Ensure that matched element is a checkbox or a radio input. If not, this method throws. If the element is
+ // already checked, this method returns immediately.
+ // 3. Wait for [actionability] checks on the matched element, unless “[object Object]” option
+ // is set. If the element is detached during the checks, the whole action is retried.
+ // 4. Scroll the element into view if needed.
+ // 5. Use [Page.Mouse] to click in the center of the element.
+ // 6. Ensure that the element is now checked. If not, this method throws.
+ // When all steps combined have not finished during the specified “[object Object]”, this method throws a
+ // [TimeoutError]. Passing zero timeout disables this.
+ //
+ // Deprecated: Use locator-based [Locator.Check] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [locators]: https://playwright.dev/docs/locators
+ Check(selector string, options ...FrameCheckOptions) error
+
+ ChildFrames() []Frame
+
+ // This method clicks an element matching “[object Object]” by performing the following steps:
+ // 1. Find an element matching “[object Object]”. If there is none, wait until a matching element is attached to
+ // the DOM.
+ // 2. Wait for [actionability] checks on the matched element, unless “[object Object]” option
+ // is set. If the element is detached during the checks, the whole action is retried.
+ // 3. Scroll the element into view if needed.
+ // 4. Use [Page.Mouse] to click in the center of the element, or the specified “[object Object]”.
+ // 5. Wait for initiated navigations to either succeed or fail, unless “[object Object]” option is set.
+ // When all steps combined have not finished during the specified “[object Object]”, this method throws a
+ // [TimeoutError]. Passing zero timeout disables this.
+ //
+ // Deprecated: Use locator-based [Locator.Click] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [locators]: https://playwright.dev/docs/locators
+ Click(selector string, options ...FrameClickOptions) error
+
+ // Gets the full HTML contents of the frame, including the doctype.
+ Content() (string, error)
+
+ // This method double clicks an element matching “[object Object]” by performing the following steps:
+ // 1. Find an element matching “[object Object]”. If there is none, wait until a matching element is attached to
+ // the DOM.
+ // 2. Wait for [actionability] checks on the matched element, unless “[object Object]” option
+ // is set. If the element is detached during the checks, the whole action is retried.
+ // 3. Scroll the element into view if needed.
+ // 4. Use [Page.Mouse] to double click in the center of the element, or the specified “[object Object]”. if the
+ // first click of the `dblclick()` triggers a navigation event, this method will throw.
+ // When all steps combined have not finished during the specified “[object Object]”, this method throws a
+ // [TimeoutError]. Passing zero timeout disables this.
+ // **NOTE** `frame.dblclick()` dispatches two `click` events and a single `dblclick` event.
+ //
+ // Deprecated: Use locator-based [Locator.Dblclick] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [locators]: https://playwright.dev/docs/locators
+ Dblclick(selector string, options ...FrameDblclickOptions) error
+
+ // The snippet below dispatches the `click` event on the element. Regardless of the visibility state of the element,
+ // `click` is dispatched. This is equivalent to calling
+ // [element.Click()].
+ //
+ // Deprecated: Use locator-based [Locator.DispatchEvent] instead. Read more about [locators].
+ //
+ // 1. selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ // 2. typ: DOM event type: `"click"`, `"dragstart"`, etc.
+ // 3. eventInit: Optional event-specific initialization properties.
+ //
+ // [element.Click()]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/click
+ // [DeviceMotionEvent]: https://developer.mozilla.org/en-US/docs/Web/API/DeviceMotionEvent/DeviceMotionEvent
+ // [DeviceOrientationEvent]: https://developer.mozilla.org/en-US/docs/Web/API/DeviceOrientationEvent/DeviceOrientationEvent
+ // [DragEvent]: https://developer.mozilla.org/en-US/docs/Web/API/DragEvent/DragEvent
+ // [Event]: https://developer.mozilla.org/en-US/docs/Web/API/Event/Event
+ // [FocusEvent]: https://developer.mozilla.org/en-US/docs/Web/API/FocusEvent/FocusEvent
+ // [KeyboardEvent]: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/KeyboardEvent
+ // [MouseEvent]: https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/MouseEvent
+ // [PointerEvent]: https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/PointerEvent
+ // [TouchEvent]: https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent/TouchEvent
+ // [WheelEvent]: https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent/WheelEvent
+ // [locators]: https://playwright.dev/docs/locators
+ DispatchEvent(selector string, typ string, eventInit interface{}, options ...FrameDispatchEventOptions) error
+
+ //
+ // 1. source: A selector to search for an element to drag. If there are multiple elements satisfying the selector, the first will
+ // be used.
+ // 2. target: A selector to search for an element to drop onto. If there are multiple elements satisfying the selector, the first
+ // will be used.
+ DragAndDrop(source string, target string, options ...FrameDragAndDropOptions) error
+
+ // Returns the return value of “[object Object]”.
+ // The method finds an element matching the specified selector within the frame and passes it as a first argument to
+ // “[object Object]”. If no elements match the selector, the method throws an error.
+ // If “[object Object]” returns a [Promise], then [Frame.EvalOnSelector] would wait for the promise to resolve and
+ // return its value.
+ //
+ // Deprecated: This method does not wait for the element to pass the actionability checks and therefore can lead to the flaky tests. Use [Locator.Evaluate], other [Locator] helper methods or web-first assertions instead.
+ //
+ // 1. selector: A selector to query for.
+ // 2. expression: JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the
+ // function is automatically invoked.
+ // 3. arg: Optional argument to pass to “[object Object]”.
+ EvalOnSelector(selector string, expression string, arg interface{}, options ...FrameEvalOnSelectorOptions) (interface{}, error)
+
+ // Returns the return value of “[object Object]”.
+ // The method finds all elements matching the specified selector within the frame and passes an array of matched
+ // elements as a first argument to “[object Object]”.
+ // If “[object Object]” returns a [Promise], then [Frame.EvalOnSelectorAll] would wait for the promise to resolve and
+ // return its value.
+ //
+ // Deprecated: In most cases, [Locator.EvaluateAll], other [Locator] helper methods and web-first assertions do a better job.
+ //
+ // 1. selector: A selector to query for.
+ // 2. expression: JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the
+ // function is automatically invoked.
+ // 3. arg: Optional argument to pass to “[object Object]”.
+ EvalOnSelectorAll(selector string, expression string, arg ...interface{}) (interface{}, error)
+
+ // Returns the return value of “[object Object]”.
+ // If the function passed to the [Frame.Evaluate] returns a [Promise], then [Frame.Evaluate] would wait for the
+ // promise to resolve and return its value.
+ // If the function passed to the [Frame.Evaluate] returns a non-[Serializable] value, then [Frame.Evaluate] returns
+ // `undefined`. Playwright also supports transferring some additional values that are not serializable by `JSON`:
+ // `-0`, `NaN`, `Infinity`, `-Infinity`.
+ //
+ // 1. expression: JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the
+ // function is automatically invoked.
+ // 2. arg: Optional argument to pass to “[object Object]”.
+ Evaluate(expression string, arg ...interface{}) (interface{}, error)
+
+ // Returns the return value of “[object Object]” as a [JSHandle].
+ // The only difference between [Frame.Evaluate] and [Frame.EvaluateHandle] is that [Frame.EvaluateHandle] returns
+ // [JSHandle].
+ // If the function, passed to the [Frame.EvaluateHandle], returns a [Promise], then [Frame.EvaluateHandle] would wait
+ // for the promise to resolve and return its value.
+ //
+ // 1. expression: JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the
+ // function is automatically invoked.
+ // 2. arg: Optional argument to pass to “[object Object]”.
+ EvaluateHandle(expression string, arg ...interface{}) (JSHandle, error)
+
+ // This method waits for an element matching “[object Object]”, waits for [actionability] checks,
+ // focuses the element, fills it and triggers an `input` event after filling. Note that you can pass an empty string
+ // to clear the input field.
+ // If the target element is not an `<input>`, `<textarea>` or `[contenteditable]` element, this method throws an
+ // error. However, if the element is inside the `<label>` element that has an associated
+ // [control], the control will be filled
+ // instead.
+ // To send fine-grained keyboard events, use [Locator.PressSequentially].
+ //
+ // Deprecated: Use locator-based [Locator.Fill] instead. Read more about [locators].
+ //
+ // 1. selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ // 2. value: Value to fill for the `<input>`, `<textarea>` or `[contenteditable]` element.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [control]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/control
+ // [locators]: https://playwright.dev/docs/locators
+ Fill(selector string, value string, options ...FrameFillOptions) error
+
+ // This method fetches an element with “[object Object]” and focuses it. If there's no element matching
+ // “[object Object]”, the method waits until a matching element appears in the DOM.
+ //
+ // Deprecated: Use locator-based [Locator.Focus] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [locators]: https://playwright.dev/docs/locators
+ Focus(selector string, options ...FrameFocusOptions) error
+
+ // Returns the `frame` or `iframe` element handle which corresponds to this frame.
+ // This is an inverse of [ElementHandle.ContentFrame]. Note that returned handle actually belongs to the parent frame.
+ // This method throws an error if the frame has been detached before `frameElement()` returns.
+ FrameElement() (ElementHandle, error)
+
+ // When working with iframes, you can create a frame locator that will enter the iframe and allow selecting elements
+ // in that iframe.
+ //
+ // selector: A selector to use when resolving DOM element.
+ FrameLocator(selector string) FrameLocator
+
+ // Returns element attribute value.
+ //
+ // Deprecated: Use locator-based [Locator.GetAttribute] instead. Read more about [locators].
+ //
+ // 1. selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ // 2. name: Attribute name to get the value for.
+ //
+ // [locators]: https://playwright.dev/docs/locators
+ GetAttribute(selector string, name string, options ...FrameGetAttributeOptions) (string, error)
+
+ // Allows locating elements by their alt text.
+ //
+ // text: Text to locate the element for.
+ GetByAltText(text interface{}, options ...FrameGetByAltTextOptions) Locator
+
+ // Allows locating input elements by the text of the associated `<label>` or `aria-labelledby` element, or by the
+ // `aria-label` attribute.
+ //
+ // text: Text to locate the element for.
+ GetByLabel(text interface{}, options ...FrameGetByLabelOptions) Locator
+
+ // Allows locating input elements by the placeholder text.
+ //
+ // text: Text to locate the element for.
+ GetByPlaceholder(text interface{}, options ...FrameGetByPlaceholderOptions) Locator
+
+ // Allows locating elements by their [ARIA role],
+ // [ARIA attributes] and
+ // [accessible name].
+ //
+ // # Details
+ //
+ // Role selector **does not replace** accessibility audits and conformance tests, but rather gives early feedback
+ // about the ARIA guidelines.
+ // Many html elements have an implicitly [defined role]
+ // that is recognized by the role selector. You can find all the
+ // [supported roles here]. ARIA guidelines **do not recommend**
+ // duplicating implicit roles and attributes by setting `role` and/or `aria-*` attributes to default values.
+ //
+ // role: Required aria role.
+ //
+ // [ARIA role]: https://www.w3.org/TR/wai-aria-1.2/#roles
+ // [ARIA attributes]: https://www.w3.org/TR/wai-aria-1.2/#aria-attributes
+ // [accessible name]: https://w3c.github.io/accname/#dfn-accessible-name
+ // [defined role]: https://w3c.github.io/html-aam/#html-element-role-mappings
+ // [supported roles here]: https://www.w3.org/TR/wai-aria-1.2/#role_definitions
+ GetByRole(role AriaRole, options ...FrameGetByRoleOptions) Locator
+
+ // Locate element by the test id.
+ //
+ // # Details
+ //
+ // By default, the `data-testid` attribute is used as a test id. Use [Selectors.SetTestIdAttribute] to configure a
+ // different test id attribute if necessary.
+ //
+ // testId: Id to locate the element by.
+ GetByTestId(testId interface{}) Locator
+
+ // Allows locating elements that contain given text.
+ // See also [Locator.Filter] that allows to match by another criteria, like an accessible role, and then filter by the
+ // text content.
+ //
+ // # Details
+ //
+ // Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into
+ // one, turns line breaks into spaces and ignores leading and trailing whitespace.
+ // Input elements of the type `button` and `submit` are matched by their `value` instead of the text content. For
+ // example, locating by text `"Log in"` matches `<input type=button value="Log in">`.
+ //
+ // text: Text to locate the element for.
+ GetByText(text interface{}, options ...FrameGetByTextOptions) Locator
+
+ // Allows locating elements by their title attribute.
+ //
+ // text: Text to locate the element for.
+ GetByTitle(text interface{}, options ...FrameGetByTitleOptions) Locator
+
+ // Returns the main resource response. In case of multiple redirects, the navigation will resolve with the response of
+ // the last redirect.
+ // The method will throw an error if:
+ // - there's an SSL error (e.g. in case of self-signed certificates).
+ // - target URL is invalid.
+ // - the “[object Object]” is exceeded during navigation.
+ // - the remote server does not respond or is unreachable.
+ // - the main resource failed to load.
+ // The method will not throw an error when any valid HTTP status code is returned by the remote server, including 404
+ // "Not Found" and 500 "Internal Server Error". The status code for such responses can be retrieved by calling
+ // [Response.Status].
+ // **NOTE** The method either throws an error or returns a main resource response. The only exceptions are navigation
+ // to `about:blank` or navigation to the same URL with a different hash, which would succeed and return `null`.
+ // **NOTE** Headless mode doesn't support navigation to a PDF document. See the
+ // [upstream issue].
+ //
+ // url: URL to navigate frame to. The url should include scheme, e.g. `https://`.
+ //
+ // [upstream issue]: https://bugs.chromium.org/p/chromium/issues/detail?id=761295
+ Goto(url string, options ...FrameGotoOptions) (Response, error)
+
+ // This method hovers over an element matching “[object Object]” by performing the following steps:
+ // 1. Find an element matching “[object Object]”. If there is none, wait until a matching element is attached to
+ // the DOM.
+ // 2. Wait for [actionability] checks on the matched element, unless “[object Object]” option
+ // is set. If the element is detached during the checks, the whole action is retried.
+ // 3. Scroll the element into view if needed.
+ // 4. Use [Page.Mouse] to hover over the center of the element, or the specified “[object Object]”.
+ // When all steps combined have not finished during the specified “[object Object]”, this method throws a
+ // [TimeoutError]. Passing zero timeout disables this.
+ //
+ // Deprecated: Use locator-based [Locator.Hover] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [locators]: https://playwright.dev/docs/locators
+ Hover(selector string, options ...FrameHoverOptions) error
+
+ // Returns `element.innerHTML`.
+ //
+ // Deprecated: Use locator-based [Locator.InnerHTML] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [locators]: https://playwright.dev/docs/locators
+ InnerHTML(selector string, options ...FrameInnerHTMLOptions) (string, error)
+
+ // Returns `element.innerText`.
+ //
+ // Deprecated: Use locator-based [Locator.InnerText] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [locators]: https://playwright.dev/docs/locators
+ InnerText(selector string, options ...FrameInnerTextOptions) (string, error)
+
+ // Returns `input.value` for the selected `<input>` or `<textarea>` or `<select>` element.
+ // Throws for non-input elements. However, if the element is inside the `<label>` element that has an associated
+ // [control], returns the value of the
+ // control.
+ //
+ // Deprecated: Use locator-based [Locator.InputValue] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [control]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/control
+ // [locators]: https://playwright.dev/docs/locators
+ InputValue(selector string, options ...FrameInputValueOptions) (string, error)
+
+ // Returns whether the element is checked. Throws if the element is not a checkbox or radio input.
+ //
+ // Deprecated: Use locator-based [Locator.IsChecked] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [locators]: https://playwright.dev/docs/locators
+ IsChecked(selector string, options ...FrameIsCheckedOptions) (bool, error)
+
+ // Returns `true` if the frame has been detached, or `false` otherwise.
+ IsDetached() bool
+
+ // Returns whether the element is disabled, the opposite of [enabled].
+ //
+ // Deprecated: Use locator-based [Locator.IsDisabled] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [enabled]: https://playwright.dev/docs/actionability#enabled
+ // [locators]: https://playwright.dev/docs/locators
+ IsDisabled(selector string, options ...FrameIsDisabledOptions) (bool, error)
+
+ // Returns whether the element is [editable].
+ //
+ // Deprecated: Use locator-based [Locator.IsEditable] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [editable]: https://playwright.dev/docs/actionability#editable
+ // [locators]: https://playwright.dev/docs/locators
+ IsEditable(selector string, options ...FrameIsEditableOptions) (bool, error)
+
+ // Returns whether the element is [enabled].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [enabled]: https://playwright.dev/docs/actionability#enabled
+ IsEnabled(selector string, options ...FrameIsEnabledOptions) (bool, error)
+
+ // Returns whether the element is hidden, the opposite of [visible]. “[object Object]”
+ // that does not match any elements is considered hidden.
+ //
+ // Deprecated: Use locator-based [Locator.IsHidden] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [visible]: https://playwright.dev/docs/actionability#visible
+ // [locators]: https://playwright.dev/docs/locators
+ IsHidden(selector string, options ...FrameIsHiddenOptions) (bool, error)
+
+ // Returns whether the element is [visible]. “[object Object]” that does not match any
+ // elements is considered not visible.
+ //
+ // Deprecated: Use locator-based [Locator.IsVisible] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [visible]: https://playwright.dev/docs/actionability#visible
+ // [locators]: https://playwright.dev/docs/locators
+ IsVisible(selector string, options ...FrameIsVisibleOptions) (bool, error)
+
+ // The method returns an element locator that can be used to perform actions on this page / frame. Locator is resolved
+ // to the element immediately before performing an action, so a series of actions on the same locator can in fact be
+ // performed on different DOM elements. That would happen if the DOM structure between those actions has changed.
+ // [Learn more about locators].
+ // [Learn more about locators].
+ //
+ // selector: A selector to use when resolving DOM element.
+ //
+ // [Learn more about locators]: https://playwright.dev/docs/locators
+ // [Learn more about locators]: https://playwright.dev/docs/locators
+ Locator(selector string, options ...FrameLocatorOptions) Locator
+
+ // Returns frame's name attribute as specified in the tag.
+ // If the name is empty, returns the id attribute instead.
+ // **NOTE** This value is calculated once when the frame is created, and will not update if the attribute is changed
+ // later.
+ Name() string
+
+ // Returns the page containing this frame.
+ Page() Page
+
+ // Parent frame, if any. Detached frames and main frames return `null`.
+ ParentFrame() Frame
+
+ // “[object Object]” can specify the intended
+ // [keyboardEvent.Key] value or a single character
+ // to generate the text for. A superset of the “[object Object]” values can be found
+ // [here]. Examples of the keys are:
+ // `F1` - `F12`, `Digit0`- `Digit9`, `KeyA`- `KeyZ`, `Backquote`, `Minus`, `Equal`, `Backslash`, `Backspace`, `Tab`,
+ // `Delete`, `Escape`, `ArrowDown`, `End`, `Enter`, `Home`, `Insert`, `PageDown`, `PageUp`, `ArrowRight`, `ArrowUp`,
+ // etc.
+ // Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`,
+ // `ControlOrMeta`. `ControlOrMeta` resolves to `Control` on Windows and Linux and to `Meta` on macOS.
+ // Holding down `Shift` will type the text that corresponds to the “[object Object]” in the upper case.
+ // If “[object Object]” is a single character, it is case-sensitive, so the values `a` and `A` will generate different
+ // respective texts.
+ // Shortcuts such as `key: "Control+o"`, `key: "Control++` or `key: "Control+Shift+T"` are supported as well. When
+ // specified with the modifier, modifier is pressed and being held while the subsequent key is being pressed.
+ //
+ // Deprecated: Use locator-based [Locator.Press] instead. Read more about [locators].
+ //
+ // 1. selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ // 2. key: Name of the key to press or a character to generate, such as `ArrowLeft` or `a`.
+ //
+ // [keyboardEvent.Key]: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key
+ // [here]: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values
+ // [locators]: https://playwright.dev/docs/locators
+ Press(selector string, key string, options ...FramePressOptions) error
+
+ // Returns the ElementHandle pointing to the frame element.
+ // **NOTE** The use of [ElementHandle] is discouraged, use [Locator] objects and web-first assertions instead.
+ // The method finds an element matching the specified selector within the frame. If no elements match the selector,
+ // returns `null`.
+ //
+ // Deprecated: Use locator-based [Frame.Locator] instead. Read more about [locators].
+ //
+ // selector: A selector to query for.
+ //
+ // [locators]: https://playwright.dev/docs/locators
+ QuerySelector(selector string, options ...FrameQuerySelectorOptions) (ElementHandle, error)
+
+ // Returns the ElementHandles pointing to the frame elements.
+ // **NOTE** The use of [ElementHandle] is discouraged, use [Locator] objects instead.
+ // The method finds all elements matching the specified selector within the frame. If no elements match the selector,
+ // returns empty array.
+ //
+ // Deprecated: Use locator-based [Frame.Locator] instead. Read more about [locators].
+ //
+ // selector: A selector to query for.
+ //
+ // [locators]: https://playwright.dev/docs/locators
+ QuerySelectorAll(selector string) ([]ElementHandle, error)
+
+ // This method waits for an element matching “[object Object]”, waits for [actionability] checks,
+ // waits until all specified options are present in the `<select>` element and selects these options.
+ // If the target element is not a `<select>` element, this method throws an error. However, if the element is inside
+ // the `<label>` element that has an associated
+ // [control], the control will be used
+ // instead.
+ // Returns the array of option values that have been successfully selected.
+ // Triggers a `change` and `input` event once all the provided options have been selected.
+ //
+ // Deprecated: Use locator-based [Locator.SelectOption] instead. Read more about [locators].
+ //
+ // selector: A selector to query for.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [control]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/control
+ // [locators]: https://playwright.dev/docs/locators
+ SelectOption(selector string, values SelectOptionValues, options ...FrameSelectOptionOptions) ([]string, error)
+
+ // This method checks or unchecks an element matching “[object Object]” by performing the following steps:
+ // 1. Find an element matching “[object Object]”. If there is none, wait until a matching element is attached to
+ // the DOM.
+ // 2. Ensure that matched element is a checkbox or a radio input. If not, this method throws.
+ // 3. If the element already has the right checked state, this method returns immediately.
+ // 4. Wait for [actionability] checks on the matched element, unless “[object Object]” option
+ // is set. If the element is detached during the checks, the whole action is retried.
+ // 5. Scroll the element into view if needed.
+ // 6. Use [Page.Mouse] to click in the center of the element.
+ // 7. Ensure that the element is now checked or unchecked. If not, this method throws.
+ // When all steps combined have not finished during the specified “[object Object]”, this method throws a
+ // [TimeoutError]. Passing zero timeout disables this.
+ //
+ // Deprecated: Use locator-based [Locator.SetChecked] instead. Read more about [locators].
+ //
+ // 1. selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ // 2. checked: Whether to check or uncheck the checkbox.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [locators]: https://playwright.dev/docs/locators
+ SetChecked(selector string, checked bool, options ...FrameSetCheckedOptions) error
+
+ // This method internally calls [document.Write()],
+ // inheriting all its specific characteristics and behaviors.
+ //
+ // html: HTML markup to assign to the page.
+ //
+ // [document.Write()]: https://developer.mozilla.org/en-US/docs/Web/API/Document/write
+ SetContent(html string, options ...FrameSetContentOptions) error
+
+ // Sets the value of the file input to these file paths or files. If some of the `filePaths` are relative paths, then
+ // they are resolved relative to the current working directory. For empty array, clears the selected files.
+ // This method expects “[object Object]” to point to an
+ // [input element]. However, if the element is inside
+ // the `<label>` element that has an associated
+ // [control], targets the control instead.
+ //
+ // Deprecated: Use locator-based [Locator.SetInputFiles] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [input element]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input
+ // [control]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/control
+ // [locators]: https://playwright.dev/docs/locators
+ SetInputFiles(selector string, files interface{}, options ...FrameSetInputFilesOptions) error
+
+ // This method taps an element matching “[object Object]” by performing the following steps:
+ // 1. Find an element matching “[object Object]”. If there is none, wait until a matching element is attached to
+ // the DOM.
+ // 2. Wait for [actionability] checks on the matched element, unless “[object Object]” option
+ // is set. If the element is detached during the checks, the whole action is retried.
+ // 3. Scroll the element into view if needed.
+ // 4. Use [Page.Touchscreen] to tap the center of the element, or the specified “[object Object]”.
+ // When all steps combined have not finished during the specified “[object Object]”, this method throws a
+ // [TimeoutError]. Passing zero timeout disables this.
+ // **NOTE** `frame.tap()` requires that the `hasTouch` option of the browser context be set to true.
+ //
+ // Deprecated: Use locator-based [Locator.Tap] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [locators]: https://playwright.dev/docs/locators
+ Tap(selector string, options ...FrameTapOptions) error
+
+ // Returns `element.textContent`.
+ //
+ // Deprecated: Use locator-based [Locator.TextContent] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [locators]: https://playwright.dev/docs/locators
+ TextContent(selector string, options ...FrameTextContentOptions) (string, error)
+
+ // Returns the page title.
+ Title() (string, error)
+
+ // Sends a `keydown`, `keypress`/`input`, and `keyup` event for each character in the text. `frame.type` can be used
+ // to send fine-grained keyboard events. To fill values in form fields, use [Frame.Fill].
+ // To press a special key, like `Control` or `ArrowDown`, use [Keyboard.Press].
+ //
+ // 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].
+ //
+ // 1. selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ // 2. text: A text to type into a focused element.
+ Type(selector string, text string, options ...FrameTypeOptions) error
+
+ // This method checks an element matching “[object Object]” by performing the following steps:
+ // 1. Find an element matching “[object Object]”. If there is none, wait until a matching element is attached to
+ // the DOM.
+ // 2. Ensure that matched element is a checkbox or a radio input. If not, this method throws. If the element is
+ // already unchecked, this method returns immediately.
+ // 3. Wait for [actionability] checks on the matched element, unless “[object Object]” option
+ // is set. If the element is detached during the checks, the whole action is retried.
+ // 4. Scroll the element into view if needed.
+ // 5. Use [Page.Mouse] to click in the center of the element.
+ // 6. Ensure that the element is now unchecked. If not, this method throws.
+ // When all steps combined have not finished during the specified “[object Object]”, this method throws a
+ // [TimeoutError]. Passing zero timeout disables this.
+ //
+ // Deprecated: Use locator-based [Locator.Uncheck] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [locators]: https://playwright.dev/docs/locators
+ Uncheck(selector string, options ...FrameUncheckOptions) error
+
+ // Returns frame's url.
+ URL() string
+
+ // Returns when the “[object Object]” returns a truthy value, returns that value.
+ //
+ // 1. expression: JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the
+ // function is automatically invoked.
+ // 2. arg: Optional argument to pass to “[object Object]”.
+ WaitForFunction(expression string, arg interface{}, options ...FrameWaitForFunctionOptions) (JSHandle, error)
+
+ // Waits for the required load state to be reached.
+ // This returns when the frame reaches a required load state, `load` by default. The navigation must have been
+ // committed when this method is called. If current document has already reached the required state, resolves
+ // immediately.
+ // **NOTE** Most of the time, this method is not needed because Playwright
+ // [auto-waits before every action].
+ //
+ // [auto-waits before every action]: https://playwright.dev/docs/actionability
+ WaitForLoadState(options ...FrameWaitForLoadStateOptions) error
+
+ // Waits for the frame navigation and returns the main resource response. In case of multiple redirects, the
+ // navigation will resolve with the response of the last redirect. In case of navigation to a different anchor or
+ // navigation due to History API usage, the navigation will resolve with `null`.
+ //
+ // Deprecated: This method is inherently racy, please use [Frame.WaitForURL] instead.
+ //
+ // [History API]: https://developer.mozilla.org/en-US/docs/Web/API/History_API
+ ExpectNavigation(cb func() error, options ...FrameExpectNavigationOptions) (Response, error)
+
+ // Returns when element specified by selector satisfies “[object Object]” option. Returns `null` if waiting for
+ // `hidden` or `detached`.
+ // **NOTE** Playwright automatically waits for element to be ready before performing an action. Using [Locator]
+ // objects and web-first assertions make the code wait-for-selector-free.
+ // Wait for the “[object Object]” to satisfy “[object Object]” option (either appear/disappear from dom, or become
+ // visible/hidden). If at the moment of calling the method “[object Object]” already satisfies the condition, the
+ // method will return immediately. If the selector doesn't satisfy the condition for the “[object Object]”
+ // milliseconds, the function will throw.
+ //
+ // Deprecated: Use web assertions that assert visibility or a locator-based [Locator.WaitFor] instead. Read more about [locators].
+ //
+ // selector: A selector to query for.
+ //
+ // [locators]: https://playwright.dev/docs/locators
+ WaitForSelector(selector string, options ...FrameWaitForSelectorOptions) (ElementHandle, error)
+
+ // Waits for the given “[object Object]” in milliseconds.
+ // Note that `frame.waitForTimeout()` should only be used for debugging. Tests using the timer in production are going
+ // to be flaky. Use signals such as network events, selectors becoming visible and others instead.
+ //
+ // Deprecated: Never wait for timeout in production. Tests that wait for time are inherently flaky. Use [Locator] actions and web assertions that wait automatically.
+ //
+ // timeout: A timeout to wait for
+ WaitForTimeout(timeout float64)
+
+ // Waits for the frame to navigate to the given URL.
+ //
+ // url: A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation. Note that if
+ // the parameter is a string without wildcard characters, the method will wait for navigation to URL that is exactly
+ // equal to the string.
+ WaitForURL(url interface{}, options ...FrameWaitForURLOptions) error
+}
+
+// FrameLocator represents a view to the `iframe` on the page. It captures the logic sufficient to retrieve the
+// `iframe` and locate elements in that iframe. FrameLocator can be created with either [Locator.ContentFrame],
+// [Page.FrameLocator] or [Locator.FrameLocator] method.
+// **Strictness**
+// Frame locators are strict. This means that all operations on frame locators will throw if more than one element
+// matches a given selector.
+// **Converting Locator to FrameLocator**
+// If you have a [Locator] object pointing to an `iframe` it can be converted to [FrameLocator] using
+// [Locator.ContentFrame].
+// **Converting FrameLocator to Locator**
+// If you have a [FrameLocator] object it can be converted to [Locator] pointing to the same `iframe` using
+// [FrameLocator.Owner].
+type FrameLocator interface {
+ // Returns locator to the first matching frame.
+ //
+ // Deprecated: Use [Locator.First] followed by [Locator.ContentFrame] instead.
+ First() FrameLocator
+
+ // When working with iframes, you can create a frame locator that will enter the iframe and allow selecting elements
+ // in that iframe.
+ //
+ // selector: A selector to use when resolving DOM element.
+ FrameLocator(selector string) FrameLocator
+
+ // Allows locating elements by their alt text.
+ //
+ // text: Text to locate the element for.
+ GetByAltText(text interface{}, options ...FrameLocatorGetByAltTextOptions) Locator
+
+ // Allows locating input elements by the text of the associated `<label>` or `aria-labelledby` element, or by the
+ // `aria-label` attribute.
+ //
+ // text: Text to locate the element for.
+ GetByLabel(text interface{}, options ...FrameLocatorGetByLabelOptions) Locator
+
+ // Allows locating input elements by the placeholder text.
+ //
+ // text: Text to locate the element for.
+ GetByPlaceholder(text interface{}, options ...FrameLocatorGetByPlaceholderOptions) Locator
+
+ // Allows locating elements by their [ARIA role],
+ // [ARIA attributes] and
+ // [accessible name].
+ //
+ // # Details
+ //
+ // Role selector **does not replace** accessibility audits and conformance tests, but rather gives early feedback
+ // about the ARIA guidelines.
+ // Many html elements have an implicitly [defined role]
+ // that is recognized by the role selector. You can find all the
+ // [supported roles here]. ARIA guidelines **do not recommend**
+ // duplicating implicit roles and attributes by setting `role` and/or `aria-*` attributes to default values.
+ //
+ // role: Required aria role.
+ //
+ // [ARIA role]: https://www.w3.org/TR/wai-aria-1.2/#roles
+ // [ARIA attributes]: https://www.w3.org/TR/wai-aria-1.2/#aria-attributes
+ // [accessible name]: https://w3c.github.io/accname/#dfn-accessible-name
+ // [defined role]: https://w3c.github.io/html-aam/#html-element-role-mappings
+ // [supported roles here]: https://www.w3.org/TR/wai-aria-1.2/#role_definitions
+ GetByRole(role AriaRole, options ...FrameLocatorGetByRoleOptions) Locator
+
+ // Locate element by the test id.
+ //
+ // # Details
+ //
+ // By default, the `data-testid` attribute is used as a test id. Use [Selectors.SetTestIdAttribute] to configure a
+ // different test id attribute if necessary.
+ //
+ // testId: Id to locate the element by.
+ GetByTestId(testId interface{}) Locator
+
+ // Allows locating elements that contain given text.
+ // See also [Locator.Filter] that allows to match by another criteria, like an accessible role, and then filter by the
+ // text content.
+ //
+ // # Details
+ //
+ // Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into
+ // one, turns line breaks into spaces and ignores leading and trailing whitespace.
+ // Input elements of the type `button` and `submit` are matched by their `value` instead of the text content. For
+ // example, locating by text `"Log in"` matches `<input type=button value="Log in">`.
+ //
+ // text: Text to locate the element for.
+ GetByText(text interface{}, options ...FrameLocatorGetByTextOptions) Locator
+
+ // Allows locating elements by their title attribute.
+ //
+ // text: Text to locate the element for.
+ GetByTitle(text interface{}, options ...FrameLocatorGetByTitleOptions) Locator
+
+ // Returns locator to the last matching frame.
+ //
+ // Deprecated: Use [Locator.Last] followed by [Locator.ContentFrame] instead.
+ Last() FrameLocator
+
+ // The method finds an element matching the specified selector in the locator's subtree. It also accepts filter
+ // options, similar to [Locator.Filter] method.
+ // [Learn more about locators].
+ //
+ // selectorOrLocator: A selector or locator to use when resolving DOM element.
+ //
+ // [Learn more about locators]: https://playwright.dev/docs/locators
+ Locator(selectorOrLocator interface{}, options ...FrameLocatorLocatorOptions) Locator
+
+ // Returns locator to the n-th matching frame. It's zero based, `nth(0)` selects the first frame.
+ //
+ // Deprecated: Use [Locator.Nth] followed by [Locator.ContentFrame] instead.
+ Nth(index int) FrameLocator
+
+ // Returns a [Locator] object pointing to the same `iframe` as this frame locator.
+ // Useful when you have a [FrameLocator] object obtained somewhere, and later on would like to interact with the
+ // `iframe` element.
+ // For a reverse operation, use [Locator.ContentFrame].
+ Owner() Locator
+}
+
+// JSHandle represents an in-page JavaScript object. JSHandles can be created with the [Page.EvaluateHandle] method.
+// JSHandle prevents the referenced JavaScript object being garbage collected unless the handle is exposed with
+// [JSHandle.Dispose]. JSHandles are auto-disposed when their origin frame gets navigated or the parent context gets
+// destroyed.
+// JSHandle instances can be used as an argument in [Page.EvalOnSelector], [Page.Evaluate] and [Page.EvaluateHandle]
+// methods.
+type JSHandle interface {
+ // Returns either `null` or the object handle itself, if the object handle is an instance of [ElementHandle].
+ AsElement() ElementHandle
+
+ // The `jsHandle.dispose` method stops referencing the element handle.
+ Dispose() error
+
+ // Returns the return value of “[object Object]”.
+ // This method passes this handle as the first argument to “[object Object]”.
+ // If “[object Object]” returns a [Promise], then `handle.evaluate` would wait for the promise to resolve and return
+ // its value.
+ //
+ // 1. expression: JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the
+ // function is automatically invoked.
+ // 2. arg: Optional argument to pass to “[object Object]”.
+ Evaluate(expression string, arg ...interface{}) (interface{}, error)
+
+ // Returns the return value of “[object Object]” as a [JSHandle].
+ // This method passes this handle as the first argument to “[object Object]”.
+ // The only difference between `jsHandle.evaluate` and `jsHandle.evaluateHandle` is that `jsHandle.evaluateHandle`
+ // returns [JSHandle].
+ // If the function passed to the `jsHandle.evaluateHandle` returns a [Promise], then `jsHandle.evaluateHandle` would
+ // wait for the promise to resolve and return its value.
+ // See [Page.EvaluateHandle] for more details.
+ //
+ // 1. expression: JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the
+ // function is automatically invoked.
+ // 2. arg: Optional argument to pass to “[object Object]”.
+ EvaluateHandle(expression string, arg ...interface{}) (JSHandle, error)
+
+ // The method returns a map with **own property names** as keys and JSHandle instances for the property values.
+ GetProperties() (map[string]JSHandle, error)
+
+ // Fetches a single property from the referenced object.
+ //
+ // propertyName: property to get
+ GetProperty(propertyName string) (JSHandle, error)
+
+ // Returns a JSON representation of the object. If the object has a `toJSON` function, it **will not be called**.
+ // **NOTE** The method will return an empty JSON object if the referenced object is not stringifiable. It will throw
+ // an error if the object has circular references.
+ JSONValue() (interface{}, error)
+
+ String() string
+}
+
+// Keyboard provides an api for managing a virtual keyboard. The high level api is [Keyboard.Type], which takes raw
+// characters and generates proper `keydown`, `keypress`/`input`, and `keyup` events on your page.
+// For finer control, you can use [Keyboard.Down], [Keyboard.Up], and [Keyboard.InsertText] to manually fire events as
+// if they were generated from a real keyboard.
+// An example of holding down `Shift` in order to select and delete some text:
+// An example of pressing uppercase `A`
+// An example to trigger select-all with the keyboard
+type Keyboard interface {
+ // Dispatches a `keydown` event.
+ // “[object Object]” can specify the intended
+ // [keyboardEvent.Key] value or a single character
+ // to generate the text for. A superset of the “[object Object]” values can be found
+ // [here]. Examples of the keys are:
+ // `F1` - `F12`, `Digit0`- `Digit9`, `KeyA`- `KeyZ`, `Backquote`, `Minus`, `Equal`, `Backslash`, `Backspace`, `Tab`,
+ // `Delete`, `Escape`, `ArrowDown`, `End`, `Enter`, `Home`, `Insert`, `PageDown`, `PageUp`, `ArrowRight`, `ArrowUp`,
+ // etc.
+ // Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`,
+ // `ControlOrMeta`. `ControlOrMeta` resolves to `Control` on Windows and Linux and to `Meta` on macOS.
+ // Holding down `Shift` will type the text that corresponds to the “[object Object]” in the upper case.
+ // If “[object Object]” is a single character, it is case-sensitive, so the values `a` and `A` will generate different
+ // respective texts.
+ // If “[object Object]” is a modifier key, `Shift`, `Meta`, `Control`, or `Alt`, subsequent key presses will be sent
+ // with that modifier active. To release the modifier key, use [Keyboard.Up].
+ // After the key is pressed once, subsequent calls to [Keyboard.Down] will have
+ // [repeat] set to true. To release the key,
+ // use [Keyboard.Up].
+ // **NOTE** Modifier keys DO influence `keyboard.down`. Holding down `Shift` will type the text in upper case.
+ //
+ // key: Name of the key to press or a character to generate, such as `ArrowLeft` or `a`.
+ //
+ // [keyboardEvent.Key]: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key
+ // [here]: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values
+ // [repeat]: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/repeat
+ Down(key string) error
+
+ // Dispatches only `input` event, does not emit the `keydown`, `keyup` or `keypress` events.
+ //
+ // text: Sets input to the specified text value.
+ InsertText(text string) error
+
+ // **NOTE** In most cases, you should use [Locator.Press] instead.
+ // “[object Object]” can specify the intended
+ // [keyboardEvent.Key] value or a single character
+ // to generate the text for. A superset of the “[object Object]” values can be found
+ // [here]. Examples of the keys are:
+ // `F1` - `F12`, `Digit0`- `Digit9`, `KeyA`- `KeyZ`, `Backquote`, `Minus`, `Equal`, `Backslash`, `Backspace`, `Tab`,
+ // `Delete`, `Escape`, `ArrowDown`, `End`, `Enter`, `Home`, `Insert`, `PageDown`, `PageUp`, `ArrowRight`, `ArrowUp`,
+ // etc.
+ // Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`,
+ // `ControlOrMeta`. `ControlOrMeta` resolves to `Control` on Windows and Linux and to `Meta` on macOS.
+ // Holding down `Shift` will type the text that corresponds to the “[object Object]” in the upper case.
+ // If “[object Object]” is a single character, it is case-sensitive, so the values `a` and `A` will generate different
+ // respective texts.
+ // Shortcuts such as `key: "Control+o"`, `key: "Control++` or `key: "Control+Shift+T"` are supported as well. When
+ // specified with the modifier, modifier is pressed and being held while the subsequent key is being pressed.
+ //
+ // key: Name of the key to press or a character to generate, such as `ArrowLeft` or `a`.
+ //
+ // [keyboardEvent.Key]: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key
+ // [here]: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values
+ Press(key string, options ...KeyboardPressOptions) error
+
+ // **NOTE** 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].
+ // Sends a `keydown`, `keypress`/`input`, and `keyup` event for each character in the text.
+ // To press a special key, like `Control` or `ArrowDown`, use [Keyboard.Press].
+ //
+ // text: A text to type into a focused element.
+ Type(text string, options ...KeyboardTypeOptions) error
+
+ // Dispatches a `keyup` event.
+ //
+ // key: Name of the key to press or a character to generate, such as `ArrowLeft` or `a`.
+ Up(key string) error
+}
+
+// Locators are the central piece of Playwright's auto-waiting and retry-ability. In a nutshell, locators represent a
+// way to find element(s) on the page at any moment. A locator can be created with the [Page.Locator] method.
+// [Learn more about locators].
+//
+// [Learn more about locators]: https://playwright.dev/docs/locators
+type Locator interface {
+ // When the locator points to a list of elements, this returns an array of locators, pointing to their respective
+ // elements.
+ // **NOTE** [Locator.All] does not wait for elements to match the locator, and instead immediately returns whatever is
+ // present in the page.
+ // When the list of elements changes dynamically, [Locator.All] will produce unpredictable and flaky results.
+ // When the list of elements is stable, but loaded dynamically, wait for the full list to finish loading before
+ // calling [Locator.All].
+ All() ([]Locator, error)
+
+ // Returns an array of `node.innerText` values for all matching nodes.
+ // **NOTE** If you need to assert text on the page, prefer [LocatorAssertions.ToHaveText] with “[object Object]”
+ // option to avoid flakiness. See [assertions guide] for more details.
+ //
+ // [assertions guide]: https://playwright.dev/docs/test-assertions
+ AllInnerTexts() ([]string, error)
+
+ // Returns an array of `node.textContent` values for all matching nodes.
+ // **NOTE** If you need to assert text on the page, prefer [LocatorAssertions.ToHaveText] to avoid flakiness. See
+ // [assertions guide] for more details.
+ //
+ // [assertions guide]: https://playwright.dev/docs/test-assertions
+ AllTextContents() ([]string, error)
+
+ // Creates a locator that matches both this locator and the argument locator.
+ //
+ // locator: Additional locator to match.
+ And(locator Locator) Locator
+
+ // Captures the aria snapshot of the given element. Read more about [aria snapshots] and
+ // [LocatorAssertions.ToMatchAriaSnapshot] for the corresponding assertion.
+ //
+ // # Details
+ //
+ // This method captures the aria snapshot of the given element. The snapshot is a string that represents the state of
+ // the element and its children. The snapshot can be used to assert the state of the element in the test, or to
+ // compare it to state in the future.
+ // The ARIA snapshot is represented using [YAML] markup language:
+ // - The keys of the objects are the roles and optional accessible names of the elements.
+ // - The values are either text content or an array of child elements.
+ // - Generic static text can be represented with the `text` key.
+ // Below is the HTML markup and the respective ARIA snapshot:
+ // ```html
+ // <ul aria-label="Links">
+ // <li><a href="/">Home</a></li>
+ // <li><a href="/about">About</a></li>
+ // <ul>
+ // ```
+ // ```yml
+ // - list "Links":
+ // - listitem:
+ // - link "Home"
+ // - listitem:
+ // - link "About"
+ // ```
+ //
+ // [aria snapshots]: https://playwright.dev/docs/aria-snapshots
+ // [YAML]: https://yaml.org/spec/1.2.2/
+ AriaSnapshot(options ...LocatorAriaSnapshotOptions) (string, error)
+
+ // Calls [blur] on the element.
+ //
+ // [blur]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/blur
+ Blur(options ...LocatorBlurOptions) error
+
+ // This method returns the bounding box of the element matching the locator, or `null` if the element is not visible.
+ // The bounding box is calculated relative to the main frame viewport - which is usually the same as the browser
+ // window.
+ //
+ // # Details
+ //
+ // Scrolling affects the returned bounding box, similarly to
+ // [Element.GetBoundingClientRect].
+ // That means `x` and/or `y` may be negative.
+ // Elements from child frames return the bounding box relative to the main frame, unlike the
+ // [Element.GetBoundingClientRect].
+ // Assuming the page is static, it is safe to use bounding box coordinates to perform input. For example, the
+ // following snippet should click the center of the element.
+ //
+ // [Element.GetBoundingClientRect]: https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect
+ // [Element.GetBoundingClientRect]: https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect
+ BoundingBox(options ...LocatorBoundingBoxOptions) (*Rect, error)
+
+ // Ensure that checkbox or radio element is checked.
+ //
+ // # Details
+ //
+ // Performs the following steps:
+ // 1. Ensure that element is a checkbox or a radio input. If not, this method throws. If the element is already
+ // checked, this method returns immediately.
+ // 2. Wait for [actionability] checks on the element, unless “[object Object]” option is set.
+ // 3. Scroll the element into view if needed.
+ // 4. Use [Page.Mouse] to click in the center of the element.
+ // 5. Ensure that the element is now checked. If not, this method throws.
+ // If the element is detached from the DOM at any moment during the action, this method throws.
+ // When all steps combined have not finished during the specified “[object Object]”, this method throws a
+ // [TimeoutError]. Passing zero timeout disables this.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Check(options ...LocatorCheckOptions) error
+
+ // Clear the input field.
+ //
+ // # Details
+ //
+ // This method waits for [actionability] checks, focuses the element, clears it and triggers an
+ // `input` event after clearing.
+ // If the target element is not an `<input>`, `<textarea>` or `[contenteditable]` element, this method throws an
+ // error. However, if the element is inside the `<label>` element that has an associated
+ // [control], the control will be cleared
+ // instead.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [control]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/control
+ Clear(options ...LocatorClearOptions) error
+
+ // Click an element.
+ //
+ // # Details
+ //
+ // This method clicks the element by performing the following steps:
+ // 1. Wait for [actionability] checks on the element, unless “[object Object]” option is set.
+ // 2. Scroll the element into view if needed.
+ // 3. Use [Page.Mouse] to click in the center of the element, or the specified “[object Object]”.
+ // 4. Wait for initiated navigations to either succeed or fail, unless “[object Object]” option is set.
+ // If the element is detached from the DOM at any moment during the action, this method throws.
+ // When all steps combined have not finished during the specified “[object Object]”, this method throws a
+ // [TimeoutError]. Passing zero timeout disables this.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Click(options ...LocatorClickOptions) error
+
+ // Returns the number of elements matching the locator.
+ // **NOTE** If you need to assert the number of elements on the page, prefer [LocatorAssertions.ToHaveCount] to avoid
+ // flakiness. See [assertions guide] for more details.
+ //
+ // [assertions guide]: https://playwright.dev/docs/test-assertions
+ Count() (int, error)
+
+ // Double-click an element.
+ //
+ // # Details
+ //
+ // This method double clicks the element by performing the following steps:
+ // 1. Wait for [actionability] checks on the element, unless “[object Object]” option is set.
+ // 2. Scroll the element into view if needed.
+ // 3. Use [Page.Mouse] to double click in the center of the element, or the specified “[object Object]”.
+ // If the element is detached from the DOM at any moment during the action, this method throws.
+ // When all steps combined have not finished during the specified “[object Object]”, this method throws a
+ // [TimeoutError]. Passing zero timeout disables this.
+ // **NOTE** `element.dblclick()` dispatches two `click` events and a single `dblclick` event.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Dblclick(options ...LocatorDblclickOptions) error
+
+ // Programmatically dispatch an event on the matching element.
+ //
+ // # Details
+ //
+ // The snippet above dispatches the `click` event on the element. Regardless of the visibility state of the element,
+ // `click` is dispatched. This is equivalent to calling
+ // [element.Click()].
+ // Under the hood, it creates an instance of an event based on the given “[object Object]”, initializes it with
+ // “[object Object]” properties and dispatches it on the element. Events are `composed`, `cancelable` and bubble by
+ // default.
+ // Since “[object Object]” is event-specific, please refer to the events documentation for the lists of initial
+ // properties:
+ // - [DeviceMotionEvent]
+ // - [DeviceOrientationEvent]
+ // - [DragEvent]
+ // - [Event]
+ // - [FocusEvent]
+ // - [KeyboardEvent]
+ // - [MouseEvent]
+ // - [PointerEvent]
+ // - [TouchEvent]
+ // - [WheelEvent]
+ // You can also specify [JSHandle] as the property value if you want live objects to be passed into the event:
+ //
+ // 1. typ: DOM event type: `"click"`, `"dragstart"`, etc.
+ // 2. eventInit: Optional event-specific initialization properties.
+ //
+ // [element.Click()]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/click
+ // [DeviceMotionEvent]: https://developer.mozilla.org/en-US/docs/Web/API/DeviceMotionEvent/DeviceMotionEvent
+ // [DeviceOrientationEvent]: https://developer.mozilla.org/en-US/docs/Web/API/DeviceOrientationEvent/DeviceOrientationEvent
+ // [DragEvent]: https://developer.mozilla.org/en-US/docs/Web/API/DragEvent/DragEvent
+ // [Event]: https://developer.mozilla.org/en-US/docs/Web/API/Event/Event
+ // [FocusEvent]: https://developer.mozilla.org/en-US/docs/Web/API/FocusEvent/FocusEvent
+ // [KeyboardEvent]: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/KeyboardEvent
+ // [MouseEvent]: https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/MouseEvent
+ // [PointerEvent]: https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/PointerEvent
+ // [TouchEvent]: https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent/TouchEvent
+ // [WheelEvent]: https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent/WheelEvent
+ DispatchEvent(typ string, eventInit interface{}, options ...LocatorDispatchEventOptions) error
+
+ // Drag the source element towards the target element and drop it.
+ //
+ // # Details
+ //
+ // This method drags the locator to another target locator or target position. It will first move to the source
+ // element, perform a `mousedown`, then move to the target element or position and perform a `mouseup`.
+ //
+ // target: Locator of the element to drag to.
+ DragTo(target Locator, options ...LocatorDragToOptions) error
+
+ // Resolves given locator to the first matching DOM element. If there are no matching elements, waits for one. If
+ // multiple elements match the locator, throws.
+ //
+ // Deprecated: Always prefer using [Locator]s and web assertions over [ElementHandle]s because latter are inherently racy.
+ ElementHandle(options ...LocatorElementHandleOptions) (ElementHandle, error)
+
+ // Resolves given locator to all matching DOM elements. If there are no matching elements, returns an empty list.
+ //
+ // Deprecated: Always prefer using [Locator]s and web assertions over [ElementHandle]s because latter are inherently racy.
+ ElementHandles() ([]ElementHandle, error)
+
+ // Returns a [FrameLocator] object pointing to the same `iframe` as this locator.
+ // Useful when you have a [Locator] object obtained somewhere, and later on would like to interact with the content
+ // inside the frame.
+ // For a reverse operation, use [FrameLocator.Owner].
+ ContentFrame() FrameLocator
+
+ // Execute JavaScript code in the page, taking the matching element as an argument.
+ //
+ // # Details
+ //
+ // Returns the return value of “[object Object]”, called with the matching element as a first argument, and
+ // “[object Object]” as a second argument.
+ // If “[object Object]” returns a [Promise], this method will wait for the promise to resolve and return its value.
+ // If “[object Object]” throws or rejects, this method throws.
+ //
+ // 1. expression: JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the
+ // function is automatically invoked.
+ // 2. arg: Optional argument to pass to “[object Object]”.
+ Evaluate(expression string, arg interface{}, options ...LocatorEvaluateOptions) (interface{}, error)
+
+ // Execute JavaScript code in the page, taking all matching elements as an argument.
+ //
+ // # Details
+ //
+ // Returns the return value of “[object Object]”, called with an array of all matching elements as a first argument,
+ // and “[object Object]” as a second argument.
+ // If “[object Object]” returns a [Promise], this method will wait for the promise to resolve and return its value.
+ // If “[object Object]” throws or rejects, this method throws.
+ //
+ // 1. expression: JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the
+ // function is automatically invoked.
+ // 2. arg: Optional argument to pass to “[object Object]”.
+ EvaluateAll(expression string, arg ...interface{}) (interface{}, error)
+
+ // Execute JavaScript code in the page, taking the matching element as an argument, and return a [JSHandle] with the
+ // result.
+ //
+ // # Details
+ //
+ // Returns the return value of “[object Object]” as a[JSHandle], called with the matching element as a first argument,
+ // and “[object Object]” as a second argument.
+ // The only difference between [Locator.Evaluate] and [Locator.EvaluateHandle] is that [Locator.EvaluateHandle]
+ // returns [JSHandle].
+ // If “[object Object]” returns a [Promise], this method will wait for the promise to resolve and return its value.
+ // If “[object Object]” throws or rejects, this method throws.
+ // See [Page.EvaluateHandle] for more details.
+ //
+ // 1. expression: JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the
+ // function is automatically invoked.
+ // 2. arg: Optional argument to pass to “[object Object]”.
+ EvaluateHandle(expression string, arg interface{}, options ...LocatorEvaluateHandleOptions) (JSHandle, error)
+
+ // Set a value to the input field.
+ //
+ // # Details
+ //
+ // This method waits for [actionability] checks, focuses the element, fills it and triggers an
+ // `input` event after filling. Note that you can pass an empty string to clear the input field.
+ // If the target element is not an `<input>`, `<textarea>` or `[contenteditable]` element, this method throws an
+ // error. However, if the element is inside the `<label>` element that has an associated
+ // [control], the control will be filled
+ // instead.
+ // To send fine-grained keyboard events, use [Locator.PressSequentially].
+ //
+ // value: Value to set for the `<input>`, `<textarea>` or `[contenteditable]` element.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [control]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/control
+ Fill(value string, options ...LocatorFillOptions) error
+
+ // This method narrows existing locator according to the options, for example filters by text. It can be chained to
+ // filter multiple times.
+ Filter(options ...LocatorFilterOptions) Locator
+
+ // Returns locator to the first matching element.
+ First() Locator
+
+ // Calls [focus] on the matching element.
+ //
+ // [focus]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus
+ Focus(options ...LocatorFocusOptions) error
+
+ // When working with iframes, you can create a frame locator that will enter the iframe and allow locating elements in
+ // that iframe:
+ //
+ // selector: A selector to use when resolving DOM element.
+ FrameLocator(selector string) FrameLocator
+
+ // Returns the matching element's attribute value.
+ // **NOTE** If you need to assert an element's attribute, prefer [LocatorAssertions.ToHaveAttribute] to avoid
+ // flakiness. See [assertions guide] for more details.
+ //
+ // name: Attribute name to get the value for.
+ //
+ // [assertions guide]: https://playwright.dev/docs/test-assertions
+ GetAttribute(name string, options ...LocatorGetAttributeOptions) (string, error)
+
+ // Allows locating elements by their alt text.
+ //
+ // text: Text to locate the element for.
+ GetByAltText(text interface{}, options ...LocatorGetByAltTextOptions) Locator
+
+ // Allows locating input elements by the text of the associated `<label>` or `aria-labelledby` element, or by the
+ // `aria-label` attribute.
+ //
+ // text: Text to locate the element for.
+ GetByLabel(text interface{}, options ...LocatorGetByLabelOptions) Locator
+
+ // Allows locating input elements by the placeholder text.
+ //
+ // text: Text to locate the element for.
+ GetByPlaceholder(text interface{}, options ...LocatorGetByPlaceholderOptions) Locator
+
+ // Allows locating elements by their [ARIA role],
+ // [ARIA attributes] and
+ // [accessible name].
+ //
+ // # Details
+ //
+ // Role selector **does not replace** accessibility audits and conformance tests, but rather gives early feedback
+ // about the ARIA guidelines.
+ // Many html elements have an implicitly [defined role]
+ // that is recognized by the role selector. You can find all the
+ // [supported roles here]. ARIA guidelines **do not recommend**
+ // duplicating implicit roles and attributes by setting `role` and/or `aria-*` attributes to default values.
+ //
+ // role: Required aria role.
+ //
+ // [ARIA role]: https://www.w3.org/TR/wai-aria-1.2/#roles
+ // [ARIA attributes]: https://www.w3.org/TR/wai-aria-1.2/#aria-attributes
+ // [accessible name]: https://w3c.github.io/accname/#dfn-accessible-name
+ // [defined role]: https://w3c.github.io/html-aam/#html-element-role-mappings
+ // [supported roles here]: https://www.w3.org/TR/wai-aria-1.2/#role_definitions
+ GetByRole(role AriaRole, options ...LocatorGetByRoleOptions) Locator
+
+ // Locate element by the test id.
+ //
+ // # Details
+ //
+ // By default, the `data-testid` attribute is used as a test id. Use [Selectors.SetTestIdAttribute] to configure a
+ // different test id attribute if necessary.
+ //
+ // testId: Id to locate the element by.
+ GetByTestId(testId interface{}) Locator
+
+ // Allows locating elements that contain given text.
+ // See also [Locator.Filter] that allows to match by another criteria, like an accessible role, and then filter by the
+ // text content.
+ //
+ // # Details
+ //
+ // Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into
+ // one, turns line breaks into spaces and ignores leading and trailing whitespace.
+ // Input elements of the type `button` and `submit` are matched by their `value` instead of the text content. For
+ // example, locating by text `"Log in"` matches `<input type=button value="Log in">`.
+ //
+ // text: Text to locate the element for.
+ GetByText(text interface{}, options ...LocatorGetByTextOptions) Locator
+
+ // Allows locating elements by their title attribute.
+ //
+ // text: Text to locate the element for.
+ GetByTitle(text interface{}, options ...LocatorGetByTitleOptions) Locator
+
+ // Highlight the corresponding element(s) on the screen. Useful for debugging, don't commit the code that uses
+ // [Locator.Highlight].
+ Highlight() error
+
+ // Hover over the matching element.
+ //
+ // # Details
+ //
+ // This method hovers over the element by performing the following steps:
+ // 1. Wait for [actionability] checks on the element, unless “[object Object]” option is set.
+ // 2. Scroll the element into view if needed.
+ // 3. Use [Page.Mouse] to hover over the center of the element, or the specified “[object Object]”.
+ // If the element is detached from the DOM at any moment during the action, this method throws.
+ // When all steps combined have not finished during the specified “[object Object]”, this method throws a
+ // [TimeoutError]. Passing zero timeout disables this.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Hover(options ...LocatorHoverOptions) error
+
+ // Returns the [`element.innerHTML`].
+ //
+ // [`element.innerHTML`]: https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML
+ InnerHTML(options ...LocatorInnerHTMLOptions) (string, error)
+
+ // Returns the [`element.innerText`].
+ // **NOTE** If you need to assert text on the page, prefer [LocatorAssertions.ToHaveText] with “[object Object]”
+ // option to avoid flakiness. See [assertions guide] for more details.
+ //
+ // [`element.innerText`]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/innerText
+ // [assertions guide]: https://playwright.dev/docs/test-assertions
+ InnerText(options ...LocatorInnerTextOptions) (string, error)
+
+ // Returns the value for the matching `<input>` or `<textarea>` or `<select>` element.
+ // **NOTE** If you need to assert input value, prefer [LocatorAssertions.ToHaveValue] to avoid flakiness. See
+ // [assertions guide] for more details.
+ //
+ // # Details
+ //
+ // Throws elements that are not an input, textarea or a select. However, if the element is inside the `<label>`
+ // element that has an associated
+ // [control], returns the value of the
+ // control.
+ //
+ // [assertions guide]: https://playwright.dev/docs/test-assertions
+ // [control]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/control
+ InputValue(options ...LocatorInputValueOptions) (string, error)
+
+ // Returns whether the element is checked. Throws if the element is not a checkbox or radio input.
+ // **NOTE** If you need to assert that checkbox is checked, prefer [LocatorAssertions.ToBeChecked] to avoid flakiness.
+ // See [assertions guide] for more details.
+ //
+ // [assertions guide]: https://playwright.dev/docs/test-assertions
+ IsChecked(options ...LocatorIsCheckedOptions) (bool, error)
+
+ // Returns whether the element is disabled, the opposite of [enabled].
+ // **NOTE** If you need to assert that an element is disabled, prefer [LocatorAssertions.ToBeDisabled] to avoid
+ // flakiness. See [assertions guide] for more details.
+ //
+ // [enabled]: https://playwright.dev/docs/actionability#enabled
+ // [assertions guide]: https://playwright.dev/docs/test-assertions
+ IsDisabled(options ...LocatorIsDisabledOptions) (bool, error)
+
+ // Returns whether the element is [editable]. If the target element is not an `<input>`,
+ // `<textarea>`, `<select>`, `[contenteditable]` and does not have a role allowing `[aria-readonly]`, this method
+ // throws an error.
+ // **NOTE** If you need to assert that an element is editable, prefer [LocatorAssertions.ToBeEditable] to avoid
+ // flakiness. See [assertions guide] for more details.
+ //
+ // [editable]: https://playwright.dev/docs/actionability#editable
+ // [assertions guide]: https://playwright.dev/docs/test-assertions
+ IsEditable(options ...LocatorIsEditableOptions) (bool, error)
+
+ // Returns whether the element is [enabled].
+ // **NOTE** If you need to assert that an element is enabled, prefer [LocatorAssertions.ToBeEnabled] to avoid
+ // flakiness. See [assertions guide] for more details.
+ //
+ // [enabled]: https://playwright.dev/docs/actionability#enabled
+ // [assertions guide]: https://playwright.dev/docs/test-assertions
+ IsEnabled(options ...LocatorIsEnabledOptions) (bool, error)
+
+ // Returns whether the element is hidden, the opposite of [visible].
+ // **NOTE** If you need to assert that element is hidden, prefer [LocatorAssertions.ToBeHidden] to avoid flakiness.
+ // See [assertions guide] for more details.
+ //
+ // [visible]: https://playwright.dev/docs/actionability#visible
+ // [assertions guide]: https://playwright.dev/docs/test-assertions
+ IsHidden(options ...LocatorIsHiddenOptions) (bool, error)
+
+ // Returns whether the element is [visible].
+ // **NOTE** If you need to assert that element is visible, prefer [LocatorAssertions.ToBeVisible] to avoid flakiness.
+ // See [assertions guide] for more details.
+ //
+ // [visible]: https://playwright.dev/docs/actionability#visible
+ // [assertions guide]: https://playwright.dev/docs/test-assertions
+ IsVisible(options ...LocatorIsVisibleOptions) (bool, error)
+
+ // Returns locator to the last matching element.
+ Last() Locator
+
+ // The method finds an element matching the specified selector in the locator's subtree. It also accepts filter
+ // options, similar to [Locator.Filter] method.
+ // [Learn more about locators].
+ //
+ // selectorOrLocator: A selector or locator to use when resolving DOM element.
+ //
+ // [Learn more about locators]: https://playwright.dev/docs/locators
+ Locator(selectorOrLocator interface{}, options ...LocatorLocatorOptions) Locator
+
+ // Returns locator to the n-th matching element. It's zero based, `nth(0)` selects the first element.
+ Nth(index int) Locator
+
+ // Creates a locator matching all elements that match one or both of the two locators.
+ // Note that when both locators match something, the resulting locator will have multiple matches, potentially causing
+ // a [locator strictness] violation.
+ //
+ // locator: Alternative locator to match.
+ //
+ // [locator strictness]: https://playwright.dev/docs/locators#strictness
+ // ["strict mode violation" error]: https://playwright.dev/docs/locators#strictness
+ Or(locator Locator) Locator
+
+ // A page this locator belongs to.
+ Page() (Page, error)
+
+ // Focuses the matching element and presses a combination of the keys.
+ //
+ // # Details
+ //
+ // Focuses the element, and then uses [Keyboard.Down] and [Keyboard.Up].
+ // “[object Object]” can specify the intended
+ // [keyboardEvent.Key] value or a single character
+ // to generate the text for. A superset of the “[object Object]” values can be found
+ // [here]. Examples of the keys are:
+ // `F1` - `F12`, `Digit0`- `Digit9`, `KeyA`- `KeyZ`, `Backquote`, `Minus`, `Equal`, `Backslash`, `Backspace`, `Tab`,
+ // `Delete`, `Escape`, `ArrowDown`, `End`, `Enter`, `Home`, `Insert`, `PageDown`, `PageUp`, `ArrowRight`, `ArrowUp`,
+ // etc.
+ // Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`,
+ // `ControlOrMeta`. `ControlOrMeta` resolves to `Control` on Windows and Linux and to `Meta` on macOS.
+ // Holding down `Shift` will type the text that corresponds to the “[object Object]” in the upper case.
+ // If “[object Object]” is a single character, it is case-sensitive, so the values `a` and `A` will generate different
+ // respective texts.
+ // Shortcuts such as `key: "Control+o"`, `key: "Control++` or `key: "Control+Shift+T"` are supported as well. When
+ // specified with the modifier, modifier is pressed and being held while the subsequent key is being pressed.
+ //
+ // key: Name of the key to press or a character to generate, such as `ArrowLeft` or `a`.
+ //
+ // [keyboardEvent.Key]: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key
+ // [here]: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values
+ Press(key string, options ...LocatorPressOptions) error
+
+ // **NOTE** 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.
+ // Focuses the element, and then sends a `keydown`, `keypress`/`input`, and `keyup` event for each character in the
+ // text.
+ // To press a special key, like `Control` or `ArrowDown`, use [Locator.Press].
+ //
+ // text: String of characters to sequentially press into a focused element.
+ PressSequentially(text string, options ...LocatorPressSequentiallyOptions) error
+
+ // Take a screenshot of the element matching the locator.
+ //
+ // # Details
+ //
+ // This method captures a screenshot of the page, clipped to the size and position of a particular element matching
+ // the locator. If the element is covered by other elements, it will not be actually visible on the screenshot. If the
+ // element is a scrollable container, only the currently scrolled content will be visible on the screenshot.
+ // This method waits for the [actionability] checks, then scrolls element into view before taking
+ // a screenshot. If the element is detached from DOM, the method throws an error.
+ // Returns the buffer with the captured screenshot.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Screenshot(options ...LocatorScreenshotOptions) ([]byte, error)
+
+ // This method waits for [actionability] checks, then tries to scroll element into view, unless
+ // it is completely visible as defined by
+ // [IntersectionObserver]'s `ratio`.
+ // See [scrolling] for alternative ways to scroll.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [IntersectionObserver]: https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API
+ // [scrolling]: https://playwright.dev/docs/input#scrolling
+ ScrollIntoViewIfNeeded(options ...LocatorScrollIntoViewIfNeededOptions) error
+
+ // Selects option or options in `<select>`.
+ //
+ // # Details
+ //
+ // This method waits for [actionability] checks, waits until all specified options are present in
+ // the `<select>` element and selects these options.
+ // If the target element is not a `<select>` element, this method throws an error. However, if the element is inside
+ // the `<label>` element that has an associated
+ // [control], the control will be used
+ // instead.
+ // Returns the array of option values that have been successfully selected.
+ // Triggers a `change` and `input` event once all the provided options have been selected.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [control]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/control
+ SelectOption(values SelectOptionValues, options ...LocatorSelectOptionOptions) ([]string, error)
+
+ // This method waits for [actionability] checks, then focuses the element and selects all its
+ // text content.
+ // If the element is inside the `<label>` element that has an associated
+ // [control], focuses and selects text in
+ // the control instead.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [control]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/control
+ SelectText(options ...LocatorSelectTextOptions) error
+
+ // Set the state of a checkbox or a radio element.
+ //
+ // # Details
+ //
+ // This method checks or unchecks an element by performing the following steps:
+ // 1. Ensure that matched element is a checkbox or a radio input. If not, this method throws.
+ // 2. If the element already has the right checked state, this method returns immediately.
+ // 3. Wait for [actionability] checks on the matched element, unless “[object Object]” option
+ // is set. If the element is detached during the checks, the whole action is retried.
+ // 4. Scroll the element into view if needed.
+ // 5. Use [Page.Mouse] to click in the center of the element.
+ // 6. Ensure that the element is now checked or unchecked. If not, this method throws.
+ // When all steps combined have not finished during the specified “[object Object]”, this method throws a
+ // [TimeoutError]. Passing zero timeout disables this.
+ //
+ // checked: Whether to check or uncheck the checkbox.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ SetChecked(checked bool, options ...LocatorSetCheckedOptions) error
+
+ // Upload file or multiple files into `<input type=file>`. For inputs with a `[webkitdirectory]` attribute, only a
+ // single directory path is supported.
+ //
+ // # Details
+ //
+ // Sets the value of the file input to these file paths or files. If some of the `filePaths` are relative paths, then
+ // they are resolved relative to the current working directory. For empty array, clears the selected files.
+ // This method expects [Locator] to point to an
+ // [input element]. However, if the element is inside
+ // the `<label>` element that has an associated
+ // [control], targets the control instead.
+ //
+ // [input element]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input
+ // [control]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/control
+ SetInputFiles(files interface{}, options ...LocatorSetInputFilesOptions) error
+
+ // Perform a tap gesture on the element matching the locator. For examples of emulating other gestures by manually
+ // dispatching touch events, see the [emulating legacy touch events] page.
+ //
+ // # Details
+ //
+ // This method taps the element by performing the following steps:
+ // 1. Wait for [actionability] checks on the element, unless “[object Object]” option is set.
+ // 2. Scroll the element into view if needed.
+ // 3. Use [Page.Touchscreen] to tap the center of the element, or the specified “[object Object]”.
+ // If the element is detached from the DOM at any moment during the action, this method throws.
+ // When all steps combined have not finished during the specified “[object Object]”, this method throws a
+ // [TimeoutError]. Passing zero timeout disables this.
+ // **NOTE** `element.tap()` requires that the `hasTouch` option of the browser context be set to true.
+ //
+ // [emulating legacy touch events]: https://playwright.dev/docs/touch-events
+ // [actionability]: https://playwright.dev/docs/actionability
+ Tap(options ...LocatorTapOptions) error
+
+ // Returns the [`node.textContent`].
+ // **NOTE** If you need to assert text on the page, prefer [LocatorAssertions.ToHaveText] to avoid flakiness. See
+ // [assertions guide] for more details.
+ //
+ // [`node.textContent`]: https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent
+ // [assertions guide]: https://playwright.dev/docs/test-assertions
+ TextContent(options ...LocatorTextContentOptions) (string, error)
+
+ // Focuses the element, and then sends a `keydown`, `keypress`/`input`, and `keyup` event for each character in the
+ // text.
+ // To press a special key, like `Control` or `ArrowDown`, use [Locator.Press].
+ //
+ // 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].
+ //
+ // text: A text to type into a focused element.
+ Type(text string, options ...LocatorTypeOptions) error
+
+ // Ensure that checkbox or radio element is unchecked.
+ //
+ // # Details
+ //
+ // This method unchecks the element by performing the following steps:
+ // 1. Ensure that element is a checkbox or a radio input. If not, this method throws. If the element is already
+ // unchecked, this method returns immediately.
+ // 2. Wait for [actionability] checks on the element, unless “[object Object]” option is set.
+ // 3. Scroll the element into view if needed.
+ // 4. Use [Page.Mouse] to click in the center of the element.
+ // 5. Ensure that the element is now unchecked. If not, this method throws.
+ // If the element is detached from the DOM at any moment during the action, this method throws.
+ // When all steps combined have not finished during the specified “[object Object]”, this method throws a
+ // [TimeoutError]. Passing zero timeout disables this.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Uncheck(options ...LocatorUncheckOptions) error
+
+ // Returns when element specified by locator satisfies the “[object Object]” option.
+ // If target element already satisfies the condition, the method returns immediately. Otherwise, waits for up to
+ // “[object Object]” milliseconds until the condition is met.
+ WaitFor(options ...LocatorWaitForOptions) error
+
+ Err() error
+}
+
+// The [LocatorAssertions] class provides assertion methods that can be used to make assertions about the [Locator]
+// state in the tests.
+type LocatorAssertions interface {
+ // Makes the assertion check for the opposite condition. For example, this code tests that the Locator doesn't contain
+ // text `"error"`:
+ Not() LocatorAssertions
+
+ // Ensures that [Locator] points to an element that is
+ // [connected] to a Document or a ShadowRoot.
+ //
+ // [connected]: https://developer.mozilla.org/en-US/docs/Web/API/Node/isConnected
+ ToBeAttached(options ...LocatorAssertionsToBeAttachedOptions) error
+
+ // Ensures the [Locator] points to a checked input.
+ ToBeChecked(options ...LocatorAssertionsToBeCheckedOptions) error
+
+ // Ensures the [Locator] points to a disabled element. Element is disabled if it has "disabled" attribute or is
+ // disabled via
+ // ['aria-disabled']. Note
+ // that only native control elements such as HTML `button`, `input`, `select`, `textarea`, `option`, `optgroup` can be
+ // disabled by setting "disabled" attribute. "disabled" attribute on other elements is ignored by the browser.
+ //
+ // ['aria-disabled']: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-disabled
+ ToBeDisabled(options ...LocatorAssertionsToBeDisabledOptions) error
+
+ // Ensures the [Locator] points to an editable element.
+ ToBeEditable(options ...LocatorAssertionsToBeEditableOptions) error
+
+ // Ensures the [Locator] points to an empty editable element or to a DOM node that has no text.
+ ToBeEmpty(options ...LocatorAssertionsToBeEmptyOptions) error
+
+ // Ensures the [Locator] points to an enabled element.
+ ToBeEnabled(options ...LocatorAssertionsToBeEnabledOptions) error
+
+ // Ensures the [Locator] points to a focused DOM node.
+ ToBeFocused(options ...LocatorAssertionsToBeFocusedOptions) error
+
+ // Ensures that [Locator] either does not resolve to any DOM node, or resolves to a
+ // [non-visible] one.
+ //
+ // [non-visible]: https://playwright.dev/docs/actionability#visible
+ ToBeHidden(options ...LocatorAssertionsToBeHiddenOptions) error
+
+ // Ensures the [Locator] points to an element that intersects viewport, according to the
+ // [intersection observer API].
+ //
+ // [intersection observer API]: https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API
+ ToBeInViewport(options ...LocatorAssertionsToBeInViewportOptions) error
+
+ // Ensures that [Locator] points to an attached and [visible] DOM node.
+ // To check that at least one element from the list is visible, use [Locator.First].
+ //
+ // [visible]: https://playwright.dev/docs/actionability#visible
+ ToBeVisible(options ...LocatorAssertionsToBeVisibleOptions) error
+
+ // Ensures the [Locator] points to an element with given CSS classes. All classes from the asserted value, separated
+ // by spaces, must be present in the
+ // [Element.ClassList] in any order.
+ //
+ // expected: A string containing expected class names, separated by spaces, or a list of such strings to assert multiple
+ // elements.
+ //
+ // [Element.ClassList]: https://developer.mozilla.org/en-US/docs/Web/API/Element/classList
+ ToContainClass(expected interface{}, options ...LocatorAssertionsToContainClassOptions) error
+
+ // Ensures the [Locator] points to an element that contains the given text. All nested elements will be considered
+ // when computing the text content of the element. You can use regular expressions for the value as well.
+ //
+ // # Details
+ //
+ // When `expected` parameter is a string, Playwright will normalize whitespaces and line breaks both in the actual
+ // text and in the expected string before matching. When regular expression is used, the actual text is matched as is.
+ //
+ // expected: Expected substring or RegExp or a list of those.
+ ToContainText(expected interface{}, options ...LocatorAssertionsToContainTextOptions) error
+
+ // Ensures the [Locator] points to an element with a given
+ // [accessible description].
+ //
+ // description: Expected accessible description.
+ //
+ // [accessible description]: https://w3c.github.io/accname/#dfn-accessible-description
+ ToHaveAccessibleDescription(description interface{}, options ...LocatorAssertionsToHaveAccessibleDescriptionOptions) error
+
+ // Ensures the [Locator] points to an element with a given
+ // [aria errormessage].
+ //
+ // errorMessage: Expected accessible error message.
+ //
+ // [aria errormessage]: https://w3c.github.io/aria/#aria-errormessage
+ ToHaveAccessibleErrorMessage(errorMessage interface{}, options ...LocatorAssertionsToHaveAccessibleErrorMessageOptions) error
+
+ // Ensures the [Locator] points to an element with a given
+ // [accessible name].
+ //
+ // name: Expected accessible name.
+ //
+ // [accessible name]: https://w3c.github.io/accname/#dfn-accessible-name
+ ToHaveAccessibleName(name interface{}, options ...LocatorAssertionsToHaveAccessibleNameOptions) error
+
+ // Ensures the [Locator] points to an element with given attribute.
+ //
+ // 1. name: Attribute name.
+ // 2. value: Expected attribute value.
+ ToHaveAttribute(name string, value interface{}, options ...LocatorAssertionsToHaveAttributeOptions) error
+
+ // Ensures the [Locator] points to an element with given CSS classes. When a string is provided, it must fully match
+ // the element's `class` attribute. To match individual classes use [LocatorAssertions.ToContainClass].
+ //
+ // expected: Expected class or RegExp or a list of those.
+ ToHaveClass(expected interface{}, options ...LocatorAssertionsToHaveClassOptions) error
+
+ // Ensures the [Locator] resolves to an exact number of DOM nodes.
+ //
+ // count: Expected count.
+ ToHaveCount(count int, options ...LocatorAssertionsToHaveCountOptions) error
+
+ // Ensures the [Locator] resolves to an element with the given computed CSS style.
+ //
+ // 1. name: CSS property name.
+ // 2. value: CSS property value.
+ ToHaveCSS(name string, value interface{}, options ...LocatorAssertionsToHaveCSSOptions) error
+
+ // Ensures the [Locator] points to an element with the given DOM Node ID.
+ //
+ // id: Element id.
+ ToHaveId(id interface{}, options ...LocatorAssertionsToHaveIdOptions) error
+
+ // Ensures the [Locator] points to an element with given JavaScript property. Note that this property can be of a
+ // primitive type as well as a plain serializable JavaScript object.
+ //
+ // 1. name: Property name.
+ // 2. value: Property value.
+ ToHaveJSProperty(name string, value interface{}, options ...LocatorAssertionsToHaveJSPropertyOptions) error
+
+ // Ensures the [Locator] points to an element with a given [ARIA role].
+ // Note that role is matched as a string, disregarding the ARIA role hierarchy. For example, asserting a superclass
+ // role `"checkbox"` on an element with a subclass role `"switch"` will fail.
+ //
+ // role: Required aria role.
+ //
+ // [ARIA role]: https://www.w3.org/TR/wai-aria-1.2/#roles
+ ToHaveRole(role AriaRole, options ...LocatorAssertionsToHaveRoleOptions) error
+
+ // Ensures the [Locator] points to an element with the given text. All nested elements will be considered when
+ // computing the text content of the element. You can use regular expressions for the value as well.
+ //
+ // # Details
+ //
+ // When `expected` parameter is a string, Playwright will normalize whitespaces and line breaks both in the actual
+ // text and in the expected string before matching. When regular expression is used, the actual text is matched as is.
+ //
+ // expected: Expected string or RegExp or a list of those.
+ ToHaveText(expected interface{}, options ...LocatorAssertionsToHaveTextOptions) error
+
+ // Ensures the [Locator] points to an element with the given input value. You can use regular expressions for the
+ // value as well.
+ //
+ // value: Expected value.
+ ToHaveValue(value interface{}, options ...LocatorAssertionsToHaveValueOptions) error
+
+ // Ensures the [Locator] points to multi-select/combobox (i.e. a `select` with the `multiple` attribute) and the
+ // specified values are selected.
+ //
+ // values: Expected options currently selected.
+ ToHaveValues(values []interface{}, options ...LocatorAssertionsToHaveValuesOptions) error
+
+ // Asserts that the target element matches the given [accessibility snapshot].
+ //
+ // [accessibility snapshot]: https://playwright.dev/docs/aria-snapshots
+ ToMatchAriaSnapshot(expected string, options ...LocatorAssertionsToMatchAriaSnapshotOptions) error
+}
+
+// The Mouse class operates in main-frame CSS pixels relative to the top-left corner of the viewport.
+// Every `page` object has its own Mouse, accessible with [Page.Mouse].
+type Mouse interface {
+ // Shortcut for [Mouse.Move], [Mouse.Down], [Mouse.Up].
+ //
+ // 1. x: X coordinate relative to the main frame's viewport in CSS pixels.
+ // 2. y: Y coordinate relative to the main frame's viewport in CSS pixels.
+ Click(x float64, y float64, options ...MouseClickOptions) error
+
+ // Shortcut for [Mouse.Move], [Mouse.Down], [Mouse.Up], [Mouse.Down] and [Mouse.Up].
+ //
+ // 1. x: X coordinate relative to the main frame's viewport in CSS pixels.
+ // 2. y: Y coordinate relative to the main frame's viewport in CSS pixels.
+ Dblclick(x float64, y float64, options ...MouseDblclickOptions) error
+
+ // Dispatches a `mousedown` event.
+ Down(options ...MouseDownOptions) error
+
+ // Dispatches a `mousemove` event.
+ //
+ // 1. x: X coordinate relative to the main frame's viewport in CSS pixels.
+ // 2. y: Y coordinate relative to the main frame's viewport in CSS pixels.
+ Move(x float64, y float64, options ...MouseMoveOptions) error
+
+ // Dispatches a `mouseup` event.
+ Up(options ...MouseUpOptions) error
+
+ // Dispatches a `wheel` event. This method is usually used to manually scroll the page. See
+ // [scrolling] for alternative ways to scroll.
+ // **NOTE** Wheel events may cause scrolling if they are not handled, and this method does not wait for the scrolling
+ // to finish before returning.
+ //
+ // 1. deltaX: Pixels to scroll horizontally.
+ // 2. deltaY: Pixels to scroll vertically.
+ //
+ // [scrolling]: https://playwright.dev/docs/input#scrolling
+ Wheel(deltaX float64, deltaY float64) error
+}
+
+// Page provides methods to interact with a single tab in a [Browser], or an
+// [extension background page] in Chromium. One [Browser]
+// instance might have multiple [Page] instances.
+// This example creates a page, navigates it to a URL, and then saves a screenshot:
+// The Page class emits various events (described below) which can be handled using any of Node's native
+// [`EventEmitter`] methods, such as `on`, `once` or
+// `removeListener`.
+// This example logs a message for a single page `load` event:
+// To unsubscribe from events use the `removeListener` method:
+//
+// [extension background page]: https://developer.chrome.com/extensions/background_pages
+// [`EventEmitter`]: https://nodejs.org/api/events.html#events_class_eventemitter
+type Page interface {
+ EventEmitter
+ // Playwright has ability to mock clock and passage of time.
+ Clock() Clock
+
+ // Emitted when the page closes.
+ OnClose(fn func(Page))
+
+ // Emitted when JavaScript within the page calls one of console API methods, e.g. `console.log` or `console.dir`.
+ // The arguments passed into `console.log` are available on the [ConsoleMessage] event handler argument.
+ OnConsole(fn func(ConsoleMessage))
+
+ // Emitted when the page crashes. Browser pages might crash if they try to allocate too much memory. When the page
+ // crashes, ongoing and subsequent operations will throw.
+ // The most common way to deal with crashes is to catch an exception:
+ OnCrash(fn func(Page))
+
+ // Emitted when a JavaScript dialog appears, such as `alert`, `prompt`, `confirm` or `beforeunload`. Listener **must**
+ // either [Dialog.Accept] or [Dialog.Dismiss] the dialog - otherwise the page will
+ // [freeze] waiting for the dialog,
+ // and actions like click will never finish.
+ //
+ // [freeze]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop#never_blocking
+ OnDialog(fn func(Dialog))
+
+ // Emitted when the JavaScript
+ // [`DOMContentLoaded`] event is dispatched.
+ //
+ // [`DOMContentLoaded`]: https://developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded
+ OnDOMContentLoaded(fn func(Page))
+
+ // Emitted when attachment download started. User can access basic file operations on downloaded content via the
+ // passed [Download] instance.
+ OnDownload(fn func(Download))
+
+ // Emitted when a file chooser is supposed to appear, such as after clicking the `<input type=file>`. Playwright can
+ // respond to it via setting the input files using [FileChooser.SetFiles] that can be uploaded after that.
+ OnFileChooser(fn func(FileChooser))
+
+ // Emitted when a frame is attached.
+ OnFrameAttached(fn func(Frame))
+
+ // Emitted when a frame is detached.
+ OnFrameDetached(fn func(Frame))
+
+ // Emitted when a frame is navigated to a new url.
+ OnFrameNavigated(fn func(Frame))
+
+ // Emitted when the JavaScript [`load`] event is dispatched.
+ //
+ // [`load`]: https://developer.mozilla.org/en-US/docs/Web/Events/load
+ OnLoad(fn func(Page))
+
+ // Emitted when an uncaught exception happens within the page.
+ OnPageError(fn func(error))
+
+ // Emitted when the page opens a new tab or window. This event is emitted in addition to the [BrowserContext.OnPage],
+ // but only for popups relevant to this page.
+ // The earliest moment that page is available is when it has navigated to the initial url. For example, when opening a
+ // popup with `window.open('http://example.com')`, this event will fire when the network request to
+ // "http://example.com" is done and its response has started loading in the popup. If you would like to route/listen
+ // to this network request, use [BrowserContext.Route] and [BrowserContext.OnRequest] respectively instead of similar
+ // methods on the [Page].
+ // **NOTE** Use [Page.WaitForLoadState] to wait until the page gets to a particular state (you should not need it in
+ // most cases).
+ OnPopup(fn func(Page))
+
+ // Emitted when a page issues a request. The [request] object is read-only. In order to intercept and mutate requests,
+ // see [Page.Route] or [BrowserContext.Route].
+ OnRequest(fn func(Request))
+
+ // Emitted when a request fails, for example by timing out.
+ // **NOTE** HTTP Error responses, such as 404 or 503, are still successful responses from HTTP standpoint, so request
+ // will complete with [Page.OnRequestFinished] event and not with [Page.OnRequestFailed]. A request will only be
+ // considered failed when the client cannot get an HTTP response from the server, e.g. due to network error
+ // net::ERR_FAILED.
+ OnRequestFailed(fn func(Request))
+
+ // Emitted when a request finishes successfully after downloading the response body. For a successful response, the
+ // sequence of events is `request`, `response` and `requestfinished`.
+ OnRequestFinished(fn func(Request))
+
+ // Emitted when [response] status and headers are received for a request. For a successful response, the sequence of
+ // events is `request`, `response` and `requestfinished`.
+ OnResponse(fn func(Response))
+
+ // Emitted when [WebSocket] request is sent.
+ OnWebSocket(fn func(WebSocket))
+
+ // Emitted when a dedicated [WebWorker] is spawned
+ // by the page.
+ //
+ // [WebWorker]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API
+ OnWorker(fn func(Worker))
+
+ // Adds a script which would be evaluated in one of the following scenarios:
+ // - Whenever the page is navigated.
+ // - Whenever the child frame is attached or navigated. In this case, the script is evaluated in the context of the
+ // newly attached frame.
+ // The script is evaluated after the document was created but before any of its scripts were run. This is useful to
+ // amend the JavaScript environment, e.g. to seed `Math.random`.
+ //
+ // script: Script to be evaluated in the page.
+ AddInitScript(script Script) error
+
+ // Adds a `<script>` tag into the page with the desired url or content. Returns the added tag when the script's onload
+ // fires or when the script content was injected into frame.
+ AddScriptTag(options PageAddScriptTagOptions) (ElementHandle, error)
+
+ // Adds a `<link rel="stylesheet">` tag into the page with the desired url or a `<style type="text/css">` tag with the
+ // content. Returns the added tag when the stylesheet's onload fires or when the CSS content was injected into frame.
+ AddStyleTag(options PageAddStyleTagOptions) (ElementHandle, error)
+
+ // Brings page to front (activates tab).
+ BringToFront() error
+
+ // This method checks an element matching “[object Object]” by performing the following steps:
+ // 1. Find an element matching “[object Object]”. If there is none, wait until a matching element is attached to
+ // the DOM.
+ // 2. Ensure that matched element is a checkbox or a radio input. If not, this method throws. If the element is
+ // already checked, this method returns immediately.
+ // 3. Wait for [actionability] checks on the matched element, unless “[object Object]” option
+ // is set. If the element is detached during the checks, the whole action is retried.
+ // 4. Scroll the element into view if needed.
+ // 5. Use [Page.Mouse] to click in the center of the element.
+ // 6. Ensure that the element is now checked. If not, this method throws.
+ // When all steps combined have not finished during the specified “[object Object]”, this method throws a
+ // [TimeoutError]. Passing zero timeout disables this.
+ //
+ // Deprecated: Use locator-based [Locator.Check] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [locators]: https://playwright.dev/docs/locators
+ Check(selector string, options ...PageCheckOptions) error
+
+ // This method clicks an element matching “[object Object]” by performing the following steps:
+ // 1. Find an element matching “[object Object]”. If there is none, wait until a matching element is attached to
+ // the DOM.
+ // 2. Wait for [actionability] checks on the matched element, unless “[object Object]” option
+ // is set. If the element is detached during the checks, the whole action is retried.
+ // 3. Scroll the element into view if needed.
+ // 4. Use [Page.Mouse] to click in the center of the element, or the specified “[object Object]”.
+ // 5. Wait for initiated navigations to either succeed or fail, unless “[object Object]” option is set.
+ // When all steps combined have not finished during the specified “[object Object]”, this method throws a
+ // [TimeoutError]. Passing zero timeout disables this.
+ //
+ // Deprecated: Use locator-based [Locator.Click] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [locators]: https://playwright.dev/docs/locators
+ Click(selector string, options ...PageClickOptions) error
+
+ // If “[object Object]” is `false`, does not run any unload handlers and waits for the page to be closed. If
+ // “[object Object]” is `true` the method will run unload handlers, but will **not** wait for the page to close.
+ // By default, `page.close()` **does not** run `beforeunload` handlers.
+ // **NOTE** if “[object Object]” is passed as true, a `beforeunload` dialog might be summoned and should be handled
+ // manually via [Page.OnDialog] event.
+ Close(options ...PageCloseOptions) error
+
+ // Gets the full HTML contents of the page, including the doctype.
+ Content() (string, error)
+
+ // Get the browser context that the page belongs to.
+ Context() BrowserContext
+
+ // This method double clicks an element matching “[object Object]” by performing the following steps:
+ // 1. Find an element matching “[object Object]”. If there is none, wait until a matching element is attached to
+ // the DOM.
+ // 2. Wait for [actionability] checks on the matched element, unless “[object Object]” option
+ // is set. If the element is detached during the checks, the whole action is retried.
+ // 3. Scroll the element into view if needed.
+ // 4. Use [Page.Mouse] to double click in the center of the element, or the specified “[object Object]”.
+ // When all steps combined have not finished during the specified “[object Object]”, this method throws a
+ // [TimeoutError]. Passing zero timeout disables this.
+ // **NOTE** `page.dblclick()` dispatches two `click` events and a single `dblclick` event.
+ //
+ // Deprecated: Use locator-based [Locator.Dblclick] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [locators]: https://playwright.dev/docs/locators
+ Dblclick(selector string, options ...PageDblclickOptions) error
+
+ // The snippet below dispatches the `click` event on the element. Regardless of the visibility state of the element,
+ // `click` is dispatched. This is equivalent to calling
+ // [element.Click()].
+ //
+ // Deprecated: Use locator-based [Locator.DispatchEvent] instead. Read more about [locators].
+ //
+ // 1. selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ // 2. typ: DOM event type: `"click"`, `"dragstart"`, etc.
+ // 3. eventInit: Optional event-specific initialization properties.
+ //
+ // [element.Click()]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/click
+ // [DeviceMotionEvent]: https://developer.mozilla.org/en-US/docs/Web/API/DeviceMotionEvent/DeviceMotionEvent
+ // [DeviceOrientationEvent]: https://developer.mozilla.org/en-US/docs/Web/API/DeviceOrientationEvent/DeviceOrientationEvent
+ // [DragEvent]: https://developer.mozilla.org/en-US/docs/Web/API/DragEvent/DragEvent
+ // [Event]: https://developer.mozilla.org/en-US/docs/Web/API/Event/Event
+ // [FocusEvent]: https://developer.mozilla.org/en-US/docs/Web/API/FocusEvent/FocusEvent
+ // [KeyboardEvent]: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/KeyboardEvent
+ // [MouseEvent]: https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/MouseEvent
+ // [PointerEvent]: https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/PointerEvent
+ // [TouchEvent]: https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent/TouchEvent
+ // [WheelEvent]: https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent/WheelEvent
+ // [locators]: https://playwright.dev/docs/locators
+ DispatchEvent(selector string, typ string, eventInit interface{}, options ...PageDispatchEventOptions) error
+
+ // This method drags the source element to the target element. It will first move to the source element, perform a
+ // `mousedown`, then move to the target element and perform a `mouseup`.
+ //
+ // 1. source: A selector to search for an element to drag. If there are multiple elements satisfying the selector, the first will
+ // be used.
+ // 2. target: A selector to search for an element to drop onto. If there are multiple elements satisfying the selector, the first
+ // will be used.
+ DragAndDrop(source string, target string, options ...PageDragAndDropOptions) error
+
+ // This method changes the `CSS media type` through the `media` argument, and/or the `prefers-colors-scheme` media
+ // feature, using the `colorScheme` argument.
+ EmulateMedia(options ...PageEmulateMediaOptions) error
+
+ // The method finds an element matching the specified selector within the page and passes it as a first argument to
+ // “[object Object]”. If no elements match the selector, the method throws an error. Returns the value of
+ // “[object Object]”.
+ // If “[object Object]” returns a [Promise], then [Page.EvalOnSelector] would wait for the promise to resolve and
+ // return its value.
+ //
+ // Deprecated: This method does not wait for the element to pass actionability checks and therefore can lead to the flaky tests. Use [Locator.Evaluate], other [Locator] helper methods or web-first assertions instead.
+ //
+ // 1. selector: A selector to query for.
+ // 2. expression: JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the
+ // function is automatically invoked.
+ // 3. arg: Optional argument to pass to “[object Object]”.
+ EvalOnSelector(selector string, expression string, arg interface{}, options ...PageEvalOnSelectorOptions) (interface{}, error)
+
+ // The method finds all elements matching the specified selector within the page and passes an array of matched
+ // elements as a first argument to “[object Object]”. Returns the result of “[object Object]” invocation.
+ // If “[object Object]” returns a [Promise], then [Page.EvalOnSelectorAll] would wait for the promise to resolve and
+ // return its value.
+ //
+ // Deprecated: In most cases, [Locator.EvaluateAll], other [Locator] helper methods and web-first assertions do a better job.
+ //
+ // 1. selector: A selector to query for.
+ // 2. expression: JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the
+ // function is automatically invoked.
+ // 3. arg: Optional argument to pass to “[object Object]”.
+ EvalOnSelectorAll(selector string, expression string, arg ...interface{}) (interface{}, error)
+
+ // Returns the value of the “[object Object]” invocation.
+ // If the function passed to the [Page.Evaluate] returns a [Promise], then [Page.Evaluate] would wait for the promise
+ // to resolve and return its value.
+ // If the function passed to the [Page.Evaluate] returns a non-[Serializable] value, then [Page.Evaluate] resolves to
+ // `undefined`. Playwright also supports transferring some additional values that are not serializable by `JSON`:
+ // `-0`, `NaN`, `Infinity`, `-Infinity`.
+ //
+ // 1. expression: JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the
+ // function is automatically invoked.
+ // 2. arg: Optional argument to pass to “[object Object]”.
+ Evaluate(expression string, arg ...interface{}) (interface{}, error)
+
+ // Returns the value of the “[object Object]” invocation as a [JSHandle].
+ // The only difference between [Page.Evaluate] and [Page.EvaluateHandle] is that [Page.EvaluateHandle] returns
+ // [JSHandle].
+ // If the function passed to the [Page.EvaluateHandle] returns a [Promise], then [Page.EvaluateHandle] would wait for
+ // the promise to resolve and return its value.
+ //
+ // 1. expression: JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the
+ // function is automatically invoked.
+ // 2. arg: Optional argument to pass to “[object Object]”.
+ EvaluateHandle(expression string, arg ...interface{}) (JSHandle, error)
+
+ // The method adds a function called “[object Object]” on the `window` object of every frame in this page. When
+ // called, the function executes “[object Object]” and returns a [Promise] which resolves to the return value of
+ // “[object Object]”. If the “[object Object]” returns a [Promise], it will be awaited.
+ // The first argument of the “[object Object]” function contains information about the caller: `{ browserContext:
+ // BrowserContext, page: Page, frame: Frame }`.
+ // See [BrowserContext.ExposeBinding] for the context-wide version.
+ // **NOTE** Functions installed via [Page.ExposeBinding] survive navigations.
+ //
+ // 1. name: Name of the function on the window object.
+ // 2. binding: Callback function that will be called in the Playwright's context.
+ ExposeBinding(name string, binding BindingCallFunction, handle ...bool) error
+
+ // The method adds a function called “[object Object]” on the `window` object of every frame in the page. When called,
+ // the function executes “[object Object]” and returns a [Promise] which resolves to the return value of
+ // “[object Object]”.
+ // If the “[object Object]” returns a [Promise], it will be awaited.
+ // See [BrowserContext.ExposeFunction] for context-wide exposed function.
+ // **NOTE** Functions installed via [Page.ExposeFunction] survive navigations.
+ //
+ // 1. name: Name of the function on the window object
+ // 2. binding: Callback function which will be called in Playwright's context.
+ ExposeFunction(name string, binding ExposedFunction) error
+
+ // This method waits for an element matching “[object Object]”, waits for [actionability] checks,
+ // focuses the element, fills it and triggers an `input` event after filling. Note that you can pass an empty string
+ // to clear the input field.
+ // If the target element is not an `<input>`, `<textarea>` or `[contenteditable]` element, this method throws an
+ // error. However, if the element is inside the `<label>` element that has an associated
+ // [control], the control will be filled
+ // instead.
+ // To send fine-grained keyboard events, use [Locator.PressSequentially].
+ //
+ // Deprecated: Use locator-based [Locator.Fill] instead. Read more about [locators].
+ //
+ // 1. selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ // 2. value: Value to fill for the `<input>`, `<textarea>` or `[contenteditable]` element.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [control]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/control
+ // [locators]: https://playwright.dev/docs/locators
+ Fill(selector string, value string, options ...PageFillOptions) error
+
+ // This method fetches an element with “[object Object]” and focuses it. If there's no element matching
+ // “[object Object]”, the method waits until a matching element appears in the DOM.
+ //
+ // Deprecated: Use locator-based [Locator.Focus] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [locators]: https://playwright.dev/docs/locators
+ Focus(selector string, options ...PageFocusOptions) error
+
+ // Returns frame matching the specified criteria. Either `name` or `url` must be specified.
+ Frame(options ...PageFrameOptions) Frame
+
+ // When working with iframes, you can create a frame locator that will enter the iframe and allow selecting elements
+ // in that iframe.
+ //
+ // selector: A selector to use when resolving DOM element.
+ FrameLocator(selector string) FrameLocator
+
+ // An array of all frames attached to the page.
+ Frames() []Frame
+
+ // Returns element attribute value.
+ //
+ // Deprecated: Use locator-based [Locator.GetAttribute] instead. Read more about [locators].
+ //
+ // 1. selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ // 2. name: Attribute name to get the value for.
+ //
+ // [locators]: https://playwright.dev/docs/locators
+ GetAttribute(selector string, name string, options ...PageGetAttributeOptions) (string, error)
+
+ // Allows locating elements by their alt text.
+ //
+ // text: Text to locate the element for.
+ GetByAltText(text interface{}, options ...PageGetByAltTextOptions) Locator
+
+ // Allows locating input elements by the text of the associated `<label>` or `aria-labelledby` element, or by the
+ // `aria-label` attribute.
+ //
+ // text: Text to locate the element for.
+ GetByLabel(text interface{}, options ...PageGetByLabelOptions) Locator
+
+ // Allows locating input elements by the placeholder text.
+ //
+ // text: Text to locate the element for.
+ GetByPlaceholder(text interface{}, options ...PageGetByPlaceholderOptions) Locator
+
+ // Allows locating elements by their [ARIA role],
+ // [ARIA attributes] and
+ // [accessible name].
+ //
+ // # Details
+ //
+ // Role selector **does not replace** accessibility audits and conformance tests, but rather gives early feedback
+ // about the ARIA guidelines.
+ // Many html elements have an implicitly [defined role]
+ // that is recognized by the role selector. You can find all the
+ // [supported roles here]. ARIA guidelines **do not recommend**
+ // duplicating implicit roles and attributes by setting `role` and/or `aria-*` attributes to default values.
+ //
+ // role: Required aria role.
+ //
+ // [ARIA role]: https://www.w3.org/TR/wai-aria-1.2/#roles
+ // [ARIA attributes]: https://www.w3.org/TR/wai-aria-1.2/#aria-attributes
+ // [accessible name]: https://w3c.github.io/accname/#dfn-accessible-name
+ // [defined role]: https://w3c.github.io/html-aam/#html-element-role-mappings
+ // [supported roles here]: https://www.w3.org/TR/wai-aria-1.2/#role_definitions
+ GetByRole(role AriaRole, options ...PageGetByRoleOptions) Locator
+
+ // Locate element by the test id.
+ //
+ // # Details
+ //
+ // By default, the `data-testid` attribute is used as a test id. Use [Selectors.SetTestIdAttribute] to configure a
+ // different test id attribute if necessary.
+ //
+ // testId: Id to locate the element by.
+ GetByTestId(testId interface{}) Locator
+
+ // Allows locating elements that contain given text.
+ // See also [Locator.Filter] that allows to match by another criteria, like an accessible role, and then filter by the
+ // text content.
+ //
+ // # Details
+ //
+ // Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into
+ // one, turns line breaks into spaces and ignores leading and trailing whitespace.
+ // Input elements of the type `button` and `submit` are matched by their `value` instead of the text content. For
+ // example, locating by text `"Log in"` matches `<input type=button value="Log in">`.
+ //
+ // text: Text to locate the element for.
+ GetByText(text interface{}, options ...PageGetByTextOptions) Locator
+
+ // Allows locating elements by their title attribute.
+ //
+ // text: Text to locate the element for.
+ GetByTitle(text interface{}, options ...PageGetByTitleOptions) Locator
+
+ // Returns the main resource response. In case of multiple redirects, the navigation will resolve with the response of
+ // the last redirect. If cannot go back, returns `null`.
+ // Navigate to the previous page in history.
+ GoBack(options ...PageGoBackOptions) (Response, error)
+
+ // Returns the main resource response. In case of multiple redirects, the navigation will resolve with the response of
+ // the last redirect. If cannot go forward, returns `null`.
+ // Navigate to the next page in history.
+ GoForward(options ...PageGoForwardOptions) (Response, error)
+
+ // Request the page to perform garbage collection. Note that there is no guarantee that all unreachable objects will
+ // be collected.
+ // This is useful to help detect memory leaks. For example, if your page has a large object `suspect` that might be
+ // leaked, you can check that it does not leak by using a
+ // [`WeakRef`].
+ //
+ // [`WeakRef`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakRef
+ RequestGC() error
+
+ // Returns the main resource response. In case of multiple redirects, the navigation will resolve with the first
+ // non-redirect response.
+ // The method will throw an error if:
+ // - there's an SSL error (e.g. in case of self-signed certificates).
+ // - target URL is invalid.
+ // - the “[object Object]” is exceeded during navigation.
+ // - the remote server does not respond or is unreachable.
+ // - the main resource failed to load.
+ // The method will not throw an error when any valid HTTP status code is returned by the remote server, including 404
+ // "Not Found" and 500 "Internal Server Error". The status code for such responses can be retrieved by calling
+ // [Response.Status].
+ // **NOTE** The method either throws an error or returns a main resource response. The only exceptions are navigation
+ // to `about:blank` or navigation to the same URL with a different hash, which would succeed and return `null`.
+ // **NOTE** Headless mode doesn't support navigation to a PDF document. See the
+ // [upstream issue].
+ //
+ // url: URL to navigate page to. The url should include scheme, e.g. `https://`. When a “[object Object]” via the context
+ // options was provided and the passed URL is a path, it gets merged via the
+ // [`new URL()`](https://developer.mozilla.org/en-US/docs/Web/API/URL/URL) constructor.
+ //
+ // [upstream issue]: https://bugs.chromium.org/p/chromium/issues/detail?id=761295
+ Goto(url string, options ...PageGotoOptions) (Response, error)
+
+ // This method hovers over an element matching “[object Object]” by performing the following steps:
+ // 1. Find an element matching “[object Object]”. If there is none, wait until a matching element is attached to
+ // the DOM.
+ // 2. Wait for [actionability] checks on the matched element, unless “[object Object]” option
+ // is set. If the element is detached during the checks, the whole action is retried.
+ // 3. Scroll the element into view if needed.
+ // 4. Use [Page.Mouse] to hover over the center of the element, or the specified “[object Object]”.
+ // When all steps combined have not finished during the specified “[object Object]”, this method throws a
+ // [TimeoutError]. Passing zero timeout disables this.
+ //
+ // Deprecated: Use locator-based [Locator.Hover] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [locators]: https://playwright.dev/docs/locators
+ Hover(selector string, options ...PageHoverOptions) error
+
+ // Returns `element.innerHTML`.
+ //
+ // Deprecated: Use locator-based [Locator.InnerHTML] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [locators]: https://playwright.dev/docs/locators
+ InnerHTML(selector string, options ...PageInnerHTMLOptions) (string, error)
+
+ // Returns `element.innerText`.
+ //
+ // Deprecated: Use locator-based [Locator.InnerText] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [locators]: https://playwright.dev/docs/locators
+ InnerText(selector string, options ...PageInnerTextOptions) (string, error)
+
+ // Returns `input.value` for the selected `<input>` or `<textarea>` or `<select>` element.
+ // Throws for non-input elements. However, if the element is inside the `<label>` element that has an associated
+ // [control], returns the value of the
+ // control.
+ //
+ // Deprecated: Use locator-based [Locator.InputValue] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [control]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/control
+ // [locators]: https://playwright.dev/docs/locators
+ InputValue(selector string, options ...PageInputValueOptions) (string, error)
+
+ // Returns whether the element is checked. Throws if the element is not a checkbox or radio input.
+ //
+ // Deprecated: Use locator-based [Locator.IsChecked] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [locators]: https://playwright.dev/docs/locators
+ IsChecked(selector string, options ...PageIsCheckedOptions) (bool, error)
+
+ // Indicates that the page has been closed.
+ IsClosed() bool
+
+ // Returns whether the element is disabled, the opposite of [enabled].
+ //
+ // Deprecated: Use locator-based [Locator.IsDisabled] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [enabled]: https://playwright.dev/docs/actionability#enabled
+ // [locators]: https://playwright.dev/docs/locators
+ IsDisabled(selector string, options ...PageIsDisabledOptions) (bool, error)
+
+ // Returns whether the element is [editable].
+ //
+ // Deprecated: Use locator-based [Locator.IsEditable] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [editable]: https://playwright.dev/docs/actionability#editable
+ // [locators]: https://playwright.dev/docs/locators
+ IsEditable(selector string, options ...PageIsEditableOptions) (bool, error)
+
+ // Returns whether the element is [enabled].
+ //
+ // Deprecated: Use locator-based [Locator.IsEnabled] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [enabled]: https://playwright.dev/docs/actionability#enabled
+ // [locators]: https://playwright.dev/docs/locators
+ IsEnabled(selector string, options ...PageIsEnabledOptions) (bool, error)
+
+ // Returns whether the element is hidden, the opposite of [visible]. “[object Object]”
+ // that does not match any elements is considered hidden.
+ //
+ // Deprecated: Use locator-based [Locator.IsHidden] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [visible]: https://playwright.dev/docs/actionability#visible
+ // [locators]: https://playwright.dev/docs/locators
+ IsHidden(selector string, options ...PageIsHiddenOptions) (bool, error)
+
+ // Returns whether the element is [visible]. “[object Object]” that does not match any
+ // elements is considered not visible.
+ //
+ // Deprecated: Use locator-based [Locator.IsVisible] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [visible]: https://playwright.dev/docs/actionability#visible
+ // [locators]: https://playwright.dev/docs/locators
+ IsVisible(selector string, options ...PageIsVisibleOptions) (bool, error)
+
+ Keyboard() Keyboard
+
+ // The method returns an element locator that can be used to perform actions on this page / frame. Locator is resolved
+ // to the element immediately before performing an action, so a series of actions on the same locator can in fact be
+ // performed on different DOM elements. That would happen if the DOM structure between those actions has changed.
+ // [Learn more about locators].
+ //
+ // selector: A selector to use when resolving DOM element.
+ //
+ // [Learn more about locators]: https://playwright.dev/docs/locators
+ Locator(selector string, options ...PageLocatorOptions) Locator
+
+ // The page's main frame. Page is guaranteed to have a main frame which persists during navigations.
+ MainFrame() Frame
+
+ Mouse() Mouse
+
+ // Returns the opener for popup pages and `null` for others. If the opener has been closed already the returns `null`.
+ Opener() (Page, error)
+
+ // Pauses script execution. Playwright will stop executing the script and wait for the user to either press 'Resume'
+ // button in the page overlay or to call `playwright.resume()` in the DevTools console.
+ // User can inspect selectors or perform manual steps while paused. Resume will continue running the original script
+ // from the place it was paused.
+ // **NOTE** This method requires Playwright to be started in a headed mode, with a falsy “[object Object]” option.
+ Pause() error
+
+ // Returns the PDF buffer.
+ // `page.pdf()` generates a pdf of the page with `print` css media. To generate a pdf with `screen` media, call
+ // [Page.EmulateMedia] before calling `page.pdf()`:
+ // **NOTE** By default, `page.pdf()` generates a pdf with modified colors for printing. Use the
+ // [`-webkit-print-color-adjust`]
+ // property to force rendering of exact colors.
+ //
+ // [`-webkit-print-color-adjust`]: https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-print-color-adjust
+ PDF(options ...PagePdfOptions) ([]byte, error)
+
+ // Focuses the element, and then uses [Keyboard.Down] and [Keyboard.Up].
+ // “[object Object]” can specify the intended
+ // [keyboardEvent.Key] value or a single character
+ // to generate the text for. A superset of the “[object Object]” values can be found
+ // [here]. Examples of the keys are:
+ // `F1` - `F12`, `Digit0`- `Digit9`, `KeyA`- `KeyZ`, `Backquote`, `Minus`, `Equal`, `Backslash`, `Backspace`, `Tab`,
+ // `Delete`, `Escape`, `ArrowDown`, `End`, `Enter`, `Home`, `Insert`, `PageDown`, `PageUp`, `ArrowRight`, `ArrowUp`,
+ // etc.
+ // Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`,
+ // `ControlOrMeta`. `ControlOrMeta` resolves to `Control` on Windows and Linux and to `Meta` on macOS.
+ // Holding down `Shift` will type the text that corresponds to the “[object Object]” in the upper case.
+ // If “[object Object]” is a single character, it is case-sensitive, so the values `a` and `A` will generate different
+ // respective texts.
+ // Shortcuts such as `key: "Control+o"`, `key: "Control++` or `key: "Control+Shift+T"` are supported as well. When
+ // specified with the modifier, modifier is pressed and being held while the subsequent key is being pressed.
+ //
+ // Deprecated: Use locator-based [Locator.Press] instead. Read more about [locators].
+ //
+ // 1. selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ // 2. key: Name of the key to press or a character to generate, such as `ArrowLeft` or `a`.
+ //
+ // [keyboardEvent.Key]: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key
+ // [here]: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values
+ // [locators]: https://playwright.dev/docs/locators
+ Press(selector string, key string, options ...PagePressOptions) error
+
+ // The method finds an element matching the specified selector within the page. If no elements match the selector, the
+ // return value resolves to `null`. To wait for an element on the page, use [Locator.WaitFor].
+ //
+ // Deprecated: Use locator-based [Page.Locator] instead. Read more about [locators].
+ //
+ // selector: A selector to query for.
+ //
+ // [locators]: https://playwright.dev/docs/locators
+ QuerySelector(selector string, options ...PageQuerySelectorOptions) (ElementHandle, error)
+
+ // The method finds all elements matching the specified selector within the page. If no elements match the selector,
+ // the return value resolves to `[]`.
+ //
+ // Deprecated: Use locator-based [Page.Locator] instead. Read more about [locators].
+ //
+ // selector: A selector to query for.
+ //
+ // [locators]: https://playwright.dev/docs/locators
+ QuerySelectorAll(selector string) ([]ElementHandle, error)
+
+ // When testing a web page, sometimes unexpected overlays like a "Sign up" dialog appear and block actions you want to
+ // automate, e.g. clicking a button. These overlays don't always show up in the same way or at the same time, making
+ // them tricky to handle in automated tests.
+ // This method lets you set up a special function, called a handler, that activates when it detects that overlay is
+ // visible. The handler's job is to remove the overlay, allowing your test to continue as if the overlay wasn't there.
+ // Things to keep in mind:
+ // - When an overlay is shown predictably, we recommend explicitly waiting for it in your test and dismissing it as
+ // a part of your normal test flow, instead of using [Page.AddLocatorHandler].
+ // - Playwright checks for the overlay every time before executing or retrying an action that requires an
+ // [actionability check], or before performing an auto-waiting assertion check. When overlay
+ // is visible, Playwright calls the handler first, and then proceeds with the action/assertion. Note that the
+ // handler is only called when you perform an action/assertion - if the overlay becomes visible but you don't
+ // perform any actions, the handler will not be triggered.
+ // - After executing the handler, Playwright will ensure that overlay that triggered the handler is not visible
+ // anymore. You can opt-out of this behavior with “[object Object]”.
+ // - The execution time of the handler counts towards the timeout of the action/assertion that executed the handler.
+ // If your handler takes too long, it might cause timeouts.
+ // - You can register multiple handlers. However, only a single handler will be running at a time. Make sure the
+ // actions within a handler don't depend on another handler.
+ // **NOTE** Running the handler will alter your page state mid-test. For example it will change the currently focused
+ // element and move the mouse. Make sure that actions that run after the handler are self-contained and do not rely on
+ // the focus and mouse state being unchanged.
+ // For example, consider a test that calls [Locator.Focus] followed by [Keyboard.Press]. If your handler clicks a
+ // button between these two actions, the focused element most likely will be wrong, and key press will happen on the
+ // unexpected element. Use [Locator.Press] instead to avoid this problem.
+ // Another example is a series of mouse actions, where [Mouse.Move] is followed by [Mouse.Down]. Again, when the
+ // handler runs between these two actions, the mouse position will be wrong during the mouse down. Prefer
+ // self-contained actions like [Locator.Click] that do not rely on the state being unchanged by a handler.
+ //
+ // 1. locator: Locator that triggers the handler.
+ // 2. handler: Function that should be run once “[object Object]” appears. This function should get rid of the element that blocks
+ // actions like click.
+ //
+ // [actionability check]: https://playwright.dev/docs/actionability
+ AddLocatorHandler(locator Locator, handler func(Locator), options ...PageAddLocatorHandlerOptions) error
+
+ // Removes all locator handlers added by [Page.AddLocatorHandler] for a specific locator.
+ //
+ // locator: Locator passed to [Page.AddLocatorHandler].
+ RemoveLocatorHandler(locator Locator) error
+
+ // This method reloads the current page, in the same way as if the user had triggered a browser refresh. Returns the
+ // main resource response. In case of multiple redirects, the navigation will resolve with the response of the last
+ // redirect.
+ Reload(options ...PageReloadOptions) (Response, error)
+
+ // API testing helper associated with this page. This method returns the same instance as [BrowserContext.Request] on
+ // the page's context. See [BrowserContext.Request] for more details.
+ Request() APIRequestContext
+
+ // Routing provides the capability to modify network requests that are made by a page.
+ // Once routing is enabled, every request matching the url pattern will stall unless it's continued, fulfilled or
+ // aborted.
+ // **NOTE** The handler will only be called for the first url if the response is a redirect.
+ // **NOTE** [Page.Route] will not intercept requests intercepted by Service Worker. See
+ // [this] issue. We recommend disabling Service Workers when
+ // using request interception by setting “[object Object]” to `block`.
+ // **NOTE** [Page.Route] will not intercept the first request of a popup page. Use [BrowserContext.Route] instead.
+ //
+ // 1. url: A glob pattern, regex pattern, or predicate that receives a [URL] to match during routing. If “[object Object]” is
+ // set in the context options and the provided URL is a string that does not start with `*`, it is resolved using the
+ // [`new URL()`](https://developer.mozilla.org/en-US/docs/Web/API/URL/URL) constructor.
+ // 2. handler: handler function to route the request.
+ //
+ // [this]: https://github.com/microsoft/playwright/issues/1090
+ Route(url interface{}, handler routeHandler, times ...int) error
+
+ // If specified the network requests that are made in the page will be served from the HAR file. Read more about
+ // [Replaying from HAR].
+ // Playwright will not serve requests intercepted by Service Worker from the HAR file. See
+ // [this] issue. We recommend disabling Service Workers when
+ // using request interception by setting “[object Object]” to `block`.
+ //
+ // har: Path to a [HAR](http://www.softwareishard.com/blog/har-12-spec) file with prerecorded network data. If `path` is a
+ // relative path, then it is resolved relative to the current working directory.
+ //
+ // [Replaying from HAR]: https://playwright.dev/docs/mock#replaying-from-har
+ // [this]: https://github.com/microsoft/playwright/issues/1090
+ RouteFromHAR(har string, options ...PageRouteFromHAROptions) error
+
+ // This method allows to modify websocket connections that are made by the page.
+ // Note that only `WebSocket`s created after this method was called will be routed. It is recommended to call this
+ // method before navigating the page.
+ //
+ // 1. url: Only WebSockets with the url matching this pattern will be routed. A string pattern can be relative to the
+ // “[object Object]” context option.
+ // 2. handler: Handler function to route the WebSocket.
+ RouteWebSocket(url interface{}, handler func(WebSocketRoute)) error
+
+ // Returns the buffer with the captured screenshot.
+ Screenshot(options ...PageScreenshotOptions) ([]byte, error)
+
+ // This method waits for an element matching “[object Object]”, waits for [actionability] checks,
+ // waits until all specified options are present in the `<select>` element and selects these options.
+ // If the target element is not a `<select>` element, this method throws an error. However, if the element is inside
+ // the `<label>` element that has an associated
+ // [control], the control will be used
+ // instead.
+ // Returns the array of option values that have been successfully selected.
+ // Triggers a `change` and `input` event once all the provided options have been selected.
+ //
+ // Deprecated: Use locator-based [Locator.SelectOption] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [control]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/control
+ // [locators]: https://playwright.dev/docs/locators
+ SelectOption(selector string, values SelectOptionValues, options ...PageSelectOptionOptions) ([]string, error)
+
+ // This method checks or unchecks an element matching “[object Object]” by performing the following steps:
+ // 1. Find an element matching “[object Object]”. If there is none, wait until a matching element is attached to
+ // the DOM.
+ // 2. Ensure that matched element is a checkbox or a radio input. If not, this method throws.
+ // 3. If the element already has the right checked state, this method returns immediately.
+ // 4. Wait for [actionability] checks on the matched element, unless “[object Object]” option
+ // is set. If the element is detached during the checks, the whole action is retried.
+ // 5. Scroll the element into view if needed.
+ // 6. Use [Page.Mouse] to click in the center of the element.
+ // 7. Ensure that the element is now checked or unchecked. If not, this method throws.
+ // When all steps combined have not finished during the specified “[object Object]”, this method throws a
+ // [TimeoutError]. Passing zero timeout disables this.
+ //
+ // Deprecated: Use locator-based [Locator.SetChecked] instead. Read more about [locators].
+ //
+ // 1. selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ // 2. checked: Whether to check or uncheck the checkbox.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [locators]: https://playwright.dev/docs/locators
+ SetChecked(selector string, checked bool, options ...PageSetCheckedOptions) error
+
+ // This method internally calls [document.Write()],
+ // inheriting all its specific characteristics and behaviors.
+ //
+ // html: HTML markup to assign to the page.
+ //
+ // [document.Write()]: https://developer.mozilla.org/en-US/docs/Web/API/Document/write
+ SetContent(html string, options ...PageSetContentOptions) error
+
+ // This setting will change the default maximum navigation time for the following methods and related shortcuts:
+ // - [Page.GoBack]
+ // - [Page.GoForward]
+ // - [Page.Goto]
+ // - [Page.Reload]
+ // - [Page.SetContent]
+ // - [Page.ExpectNavigation]
+ // - [Page.WaitForURL]
+ // **NOTE** [Page.SetDefaultNavigationTimeout] takes priority over [Page.SetDefaultTimeout],
+ // [BrowserContext.SetDefaultTimeout] and [BrowserContext.SetDefaultNavigationTimeout].
+ //
+ // timeout: Maximum navigation time in milliseconds
+ SetDefaultNavigationTimeout(timeout float64)
+
+ // This setting will change the default maximum time for all the methods accepting “[object Object]” option.
+ // **NOTE** [Page.SetDefaultNavigationTimeout] takes priority over [Page.SetDefaultTimeout].
+ //
+ // timeout: Maximum time in milliseconds. Pass `0` to disable timeout.
+ SetDefaultTimeout(timeout float64)
+
+ // The extra HTTP headers will be sent with every request the page initiates.
+ // **NOTE** [Page.SetExtraHTTPHeaders] does not guarantee the order of headers in the outgoing requests.
+ //
+ // headers: An object containing additional HTTP headers to be sent with every request. All header values must be strings.
+ SetExtraHTTPHeaders(headers map[string]string) error
+
+ // Sets the value of the file input to these file paths or files. If some of the `filePaths` are relative paths, then
+ // they are resolved relative to the current working directory. For empty array, clears the selected files. For inputs
+ // with a `[webkitdirectory]` attribute, only a single directory path is supported.
+ // This method expects “[object Object]” to point to an
+ // [input element]. However, if the element is inside
+ // the `<label>` element that has an associated
+ // [control], targets the control instead.
+ //
+ // Deprecated: Use locator-based [Locator.SetInputFiles] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [input element]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input
+ // [control]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/control
+ // [locators]: https://playwright.dev/docs/locators
+ SetInputFiles(selector string, files interface{}, options ...PageSetInputFilesOptions) error
+
+ // In the case of multiple pages in a single browser, each page can have its own viewport size. However,
+ // [Browser.NewContext] allows to set viewport size (and more) for all pages in the context at once.
+ // [Page.SetViewportSize] will resize the page. A lot of websites don't expect phones to change size, so you should
+ // set the viewport size before navigating to the page. [Page.SetViewportSize] will also reset `screen` size, use
+ // [Browser.NewContext] with `screen` and `viewport` parameters if you need better control of these properties.
+ //
+ // 1. width: Page width in pixels.
+ // 2. height: Page height in pixels.
+ SetViewportSize(width int, height int) error
+
+ // This method taps an element matching “[object Object]” by performing the following steps:
+ // 1. Find an element matching “[object Object]”. If there is none, wait until a matching element is attached to
+ // the DOM.
+ // 2. Wait for [actionability] checks on the matched element, unless “[object Object]” option
+ // is set. If the element is detached during the checks, the whole action is retried.
+ // 3. Scroll the element into view if needed.
+ // 4. Use [Page.Touchscreen] to tap the center of the element, or the specified “[object Object]”.
+ // When all steps combined have not finished during the specified “[object Object]”, this method throws a
+ // [TimeoutError]. Passing zero timeout disables this.
+ // **NOTE** [Page.Tap] the method will throw if “[object Object]” option of the browser context is false.
+ //
+ // Deprecated: Use locator-based [Locator.Tap] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [locators]: https://playwright.dev/docs/locators
+ Tap(selector string, options ...PageTapOptions) error
+
+ // Returns `element.textContent`.
+ //
+ // Deprecated: Use locator-based [Locator.TextContent] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [locators]: https://playwright.dev/docs/locators
+ TextContent(selector string, options ...PageTextContentOptions) (string, error)
+
+ // Returns the page's title.
+ Title() (string, error)
+
+ Touchscreen() Touchscreen
+
+ // Sends a `keydown`, `keypress`/`input`, and `keyup` event for each character in the text. `page.type` can be used to
+ // send fine-grained keyboard events. To fill values in form fields, use [Page.Fill].
+ // To press a special key, like `Control` or `ArrowDown`, use [Keyboard.Press].
+ //
+ // 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].
+ //
+ // 1. selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ // 2. text: A text to type into a focused element.
+ Type(selector string, text string, options ...PageTypeOptions) error
+
+ // This method unchecks an element matching “[object Object]” by performing the following steps:
+ // 1. Find an element matching “[object Object]”. If there is none, wait until a matching element is attached to
+ // the DOM.
+ // 2. Ensure that matched element is a checkbox or a radio input. If not, this method throws. If the element is
+ // already unchecked, this method returns immediately.
+ // 3. Wait for [actionability] checks on the matched element, unless “[object Object]” option
+ // is set. If the element is detached during the checks, the whole action is retried.
+ // 4. Scroll the element into view if needed.
+ // 5. Use [Page.Mouse] to click in the center of the element.
+ // 6. Ensure that the element is now unchecked. If not, this method throws.
+ // When all steps combined have not finished during the specified “[object Object]”, this method throws a
+ // [TimeoutError]. Passing zero timeout disables this.
+ //
+ // Deprecated: Use locator-based [Locator.Uncheck] instead. Read more about [locators].
+ //
+ // selector: A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
+ // used.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ // [locators]: https://playwright.dev/docs/locators
+ Uncheck(selector string, options ...PageUncheckOptions) error
+
+ // Removes all routes created with [Page.Route] and [Page.RouteFromHAR].
+ UnrouteAll(options ...PageUnrouteAllOptions) error
+
+ // Removes a route created with [Page.Route]. When “[object Object]” is not specified, removes all routes for the
+ // “[object Object]”.
+ //
+ // 1. url: A glob pattern, regex pattern or predicate receiving [URL] to match while routing.
+ // 2. handler: Optional handler function to route the request.
+ Unroute(url interface{}, handler ...routeHandler) error
+
+ URL() string
+
+ // Video object associated with this page.
+ Video() Video
+
+ ViewportSize() *Size
+
+ // Performs action and waits for a [ConsoleMessage] to be logged by in the page. If predicate is provided, it passes
+ // [ConsoleMessage] value into the `predicate` function and waits for `predicate(message)` to return a truthy value.
+ // Will throw an error if the page is closed before the [Page.OnConsole] event is fired.
+ ExpectConsoleMessage(cb func() error, options ...PageExpectConsoleMessageOptions) (ConsoleMessage, error)
+
+ // Performs action and waits for a new [Download]. If predicate is provided, it passes [Download] value into the
+ // `predicate` function and waits for `predicate(download)` to return a truthy value. Will throw an error if the page
+ // is closed before the download event is fired.
+ ExpectDownload(cb func() error, options ...PageExpectDownloadOptions) (Download, error)
+
+ // Waits for event to fire and passes its value into the predicate function. Returns when the predicate returns truthy
+ // value. Will throw an error if the page is closed before the event is fired. Returns the event data value.
+ //
+ // event: Event name, same one typically passed into `*.on(event)`.
+ ExpectEvent(event string, cb func() error, options ...PageExpectEventOptions) (interface{}, error)
+
+ // Performs action and waits for a new [FileChooser] to be created. If predicate is provided, it passes [FileChooser]
+ // value into the `predicate` function and waits for `predicate(fileChooser)` to return a truthy value. Will throw an
+ // error if the page is closed before the file chooser is opened.
+ ExpectFileChooser(cb func() error, options ...PageExpectFileChooserOptions) (FileChooser, error)
+
+ // Returns when the “[object Object]” returns a truthy value. It resolves to a JSHandle of the truthy value.
+ //
+ // 1. expression: JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the
+ // function is automatically invoked.
+ // 2. arg: Optional argument to pass to “[object Object]”.
+ WaitForFunction(expression string, arg interface{}, options ...PageWaitForFunctionOptions) (JSHandle, error)
+
+ // Returns when the required load state has been reached.
+ // This resolves when the page reaches a required load state, `load` by default. The navigation must have been
+ // committed when this method is called. If current document has already reached the required state, resolves
+ // immediately.
+ // **NOTE** Most of the time, this method is not needed because Playwright
+ // [auto-waits before every action].
+ //
+ // [auto-waits before every action]: https://playwright.dev/docs/actionability
+ WaitForLoadState(options ...PageWaitForLoadStateOptions) error
+
+ // Waits for the main frame navigation and returns the main resource response. In case of multiple redirects, the
+ // navigation will resolve with the response of the last redirect. In case of navigation to a different anchor or
+ // navigation due to History API usage, the navigation will resolve with `null`.
+ //
+ // Deprecated: This method is inherently racy, please use [Page.WaitForURL] instead.
+ //
+ // [History API]: https://developer.mozilla.org/en-US/docs/Web/API/History_API
+ ExpectNavigation(cb func() error, options ...PageExpectNavigationOptions) (Response, error)
+
+ // Performs action and waits for a popup [Page]. If predicate is provided, it passes [Popup] value into the
+ // `predicate` function and waits for `predicate(page)` to return a truthy value. Will throw an error if the page is
+ // closed before the popup event is fired.
+ ExpectPopup(cb func() error, options ...PageExpectPopupOptions) (Page, error)
+
+ // Waits for the matching request and returns it. See [waiting for event] for more
+ // details about events.
+ //
+ // urlOrPredicate: Request URL string, regex or predicate receiving [Request] object. When a “[object Object]” via the context options
+ // was provided and the passed URL is a path, it gets merged via the
+ // [`new URL()`](https://developer.mozilla.org/en-US/docs/Web/API/URL/URL) constructor.
+ //
+ // [waiting for event]: https://playwright.dev/docs/events#waiting-for-event
+ ExpectRequest(urlOrPredicate interface{}, cb func() error, options ...PageExpectRequestOptions) (Request, error)
+
+ // Performs action and waits for a [Request] to finish loading. If predicate is provided, it passes [Request] value
+ // into the `predicate` function and waits for `predicate(request)` to return a truthy value. Will throw an error if
+ // the page is closed before the [Page.OnRequestFinished] event is fired.
+ ExpectRequestFinished(cb func() error, options ...PageExpectRequestFinishedOptions) (Request, error)
+
+ // Returns the matched response. See [waiting for event] for more details about
+ // events.
+ //
+ // urlOrPredicate: Request URL string, regex or predicate receiving [Response] object. When a “[object Object]” via the context
+ // options was provided and the passed URL is a path, it gets merged via the
+ // [`new URL()`](https://developer.mozilla.org/en-US/docs/Web/API/URL/URL) constructor.
+ //
+ // [waiting for event]: https://playwright.dev/docs/events#waiting-for-event
+ ExpectResponse(urlOrPredicate interface{}, cb func() error, options ...PageExpectResponseOptions) (Response, error)
+
+ // Returns when element specified by selector satisfies “[object Object]” option. Returns `null` if waiting for
+ // `hidden` or `detached`.
+ // **NOTE** Playwright automatically waits for element to be ready before performing an action. Using [Locator]
+ // objects and web-first assertions makes the code wait-for-selector-free.
+ // Wait for the “[object Object]” to satisfy “[object Object]” option (either appear/disappear from dom, or become
+ // visible/hidden). If at the moment of calling the method “[object Object]” already satisfies the condition, the
+ // method will return immediately. If the selector doesn't satisfy the condition for the “[object Object]”
+ // milliseconds, the function will throw.
+ //
+ // Deprecated: Use web assertions that assert visibility or a locator-based [Locator.WaitFor] instead. Read more about [locators].
+ //
+ // selector: A selector to query for.
+ //
+ // [locators]: https://playwright.dev/docs/locators
+ WaitForSelector(selector string, options ...PageWaitForSelectorOptions) (ElementHandle, error)
+
+ // Waits for the given “[object Object]” in milliseconds.
+ // Note that `page.waitForTimeout()` should only be used for debugging. Tests using the timer in production are going
+ // to be flaky. Use signals such as network events, selectors becoming visible and others instead.
+ //
+ // Deprecated: Never wait for timeout in production. Tests that wait for time are inherently flaky. Use [Locator] actions and web assertions that wait automatically.
+ //
+ // timeout: A timeout to wait for
+ WaitForTimeout(timeout float64)
+
+ // Waits for the main frame to navigate to the given URL.
+ //
+ // url: A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation. Note that if
+ // the parameter is a string without wildcard characters, the method will wait for navigation to URL that is exactly
+ // equal to the string.
+ WaitForURL(url interface{}, options ...PageWaitForURLOptions) error
+
+ // Performs action and waits for a new [WebSocket]. If predicate is provided, it passes [WebSocket] value into the
+ // `predicate` function and waits for `predicate(webSocket)` to return a truthy value. Will throw an error if the page
+ // is closed before the WebSocket event is fired.
+ ExpectWebSocket(cb func() error, options ...PageExpectWebSocketOptions) (WebSocket, error)
+
+ // Performs action and waits for a new [Worker]. If predicate is provided, it passes [Worker] value into the
+ // `predicate` function and waits for `predicate(worker)` to return a truthy value. Will throw an error if the page is
+ // closed before the worker event is fired.
+ ExpectWorker(cb func() error, options ...PageExpectWorkerOptions) (Worker, error)
+
+ // This method returns all of the dedicated
+ // [WebWorkers] associated with the page.
+ // **NOTE** This does not contain ServiceWorkers
+ //
+ // [WebWorkers]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API
+ Workers() []Worker
+
+ // **NOTE** In most cases, you should use [Page.ExpectEvent].
+ // Waits for given `event` to fire. If predicate is provided, it passes event's value into the `predicate` function
+ // and waits for `predicate(event)` to return a truthy value. Will throw an error if the page is closed before the
+ // `event` is fired.
+ //
+ // event: Event name, same one typically passed into `*.on(event)`.
+ WaitForEvent(event string, options ...PageWaitForEventOptions) (interface{}, error)
+}
+
+// The [PageAssertions] class provides assertion methods that can be used to make assertions about the [Page] state in
+// the tests.
+type PageAssertions interface {
+ // Makes the assertion check for the opposite condition. For example, this code tests that the page URL doesn't
+ // contain `"error"`:
+ Not() PageAssertions
+
+ // Ensures the page has the given title.
+ //
+ // titleOrRegExp: Expected title or RegExp.
+ ToHaveTitle(titleOrRegExp interface{}, options ...PageAssertionsToHaveTitleOptions) error
+
+ // Ensures the page is navigated to the given URL.
+ //
+ // urlOrRegExp: Expected URL string or RegExp.
+ ToHaveURL(urlOrRegExp interface{}, options ...PageAssertionsToHaveURLOptions) error
+}
+
+// Playwright gives you Web-First Assertions with convenience methods for creating assertions that will wait and retry
+// until the expected condition is met.
+// Consider the following example:
+// Playwright will be re-testing the node with the selector `.status` until fetched Node has the `"Submitted"` text.
+// It will be re-fetching the node and checking it over and over, until the condition is met or until the timeout is
+// reached. You can pass this timeout as an option.
+// By default, the timeout for assertions is set to 5 seconds.
+type PlaywrightAssertions interface {
+ // Creates a [APIResponseAssertions] object for the given [APIResponse].
+ //
+ // response: [APIResponse] object to use for assertions.
+ APIResponse(response APIResponse) APIResponseAssertions
+
+ // Creates a [LocatorAssertions] object for the given [Locator].
+ //
+ // locator: [Locator] object to use for assertions.
+ Locator(locator Locator) LocatorAssertions
+
+ // Creates a [PageAssertions] object for the given [Page].
+ //
+ // page: [Page] object to use for assertions.
+ Page(page Page) PageAssertions
+}
+
+// Whenever the page sends a request for a network resource the following sequence of events are emitted by [Page]:
+// - [Page.OnRequest] emitted when the request is issued by the page.
+// - [Page.OnResponse] emitted when/if the response status and headers are received for the request.
+// - [Page.OnRequestFinished] emitted when the response body is downloaded and the request is complete.
+//
+// If request fails at some point, then instead of `requestfinished` event (and possibly instead of 'response'
+// event), the [Page.OnRequestFailed] event is emitted.
+// **NOTE** HTTP Error responses, such as 404 or 503, are still successful responses from HTTP standpoint, so request
+// will complete with `requestfinished` event.
+// If request gets a 'redirect' response, the request is successfully finished with the `requestfinished` event, and a
+// new request is issued to a redirected url.
+type Request interface {
+ // An object with all the request HTTP headers associated with this request. The header names are lower-cased.
+ AllHeaders() (map[string]string, error)
+
+ // The method returns `null` unless this request has failed, as reported by `requestfailed` event.
+ Failure() error
+
+ // Returns the [Frame] that initiated this request.
+ //
+ // # Details
+ //
+ // Note that in some cases the frame is not available, and this method will throw.
+ // - When request originates in the Service Worker. You can use `request.serviceWorker()` to check that.
+ // - When navigation request is issued before the corresponding frame is created. You can use
+ // [Request.IsNavigationRequest] to check that.
+ // Here is an example that handles all the cases:
+ Frame() Frame
+
+ // An object with the request HTTP headers. The header names are lower-cased. Note that this method does not return
+ // security-related headers, including cookie-related ones. You can use [Request.AllHeaders] for complete list of
+ // headers that include `cookie` information.
+ Headers() map[string]string
+
+ // An array with all the request HTTP headers associated with this request. Unlike [Request.AllHeaders], header names
+ // are NOT lower-cased. Headers with multiple entries, such as `Set-Cookie`, appear in the array multiple times.
+ HeadersArray() ([]NameValue, error)
+
+ // Returns the value of the header matching the name. The name is case-insensitive.
+ //
+ // name: Name of the header.
+ HeaderValue(name string) (string, error)
+
+ // Whether this request is driving frame's navigation.
+ // Some navigation requests are issued before the corresponding frame is created, and therefore do not have
+ // [Request.Frame] available.
+ IsNavigationRequest() bool
+
+ // Request's method (GET, POST, etc.)
+ Method() string
+
+ // Request's post body, if any.
+ PostData() (string, error)
+
+ // Request's post body in a binary form, if any.
+ PostDataBuffer() ([]byte, error)
+
+ // Returns parsed request's body for `form-urlencoded` and JSON as a fallback if any.
+ // When the response is `application/x-www-form-urlencoded` then a key/value object of the values will be returned.
+ // Otherwise it will be parsed as JSON.
+ PostDataJSON(v interface{}) error
+
+ // Request that was redirected by the server to this one, if any.
+ // When the server responds with a redirect, Playwright creates a new [Request] object. The two requests are connected
+ // by `redirectedFrom()` and `redirectedTo()` methods. When multiple server redirects has happened, it is possible to
+ // construct the whole redirect chain by repeatedly calling `redirectedFrom()`.
+ RedirectedFrom() Request
+
+ // New request issued by the browser if the server responded with redirect.
+ RedirectedTo() Request
+
+ // Contains the request's resource type as it was perceived by the rendering engine. ResourceType will be one of the
+ // following: `document`, `stylesheet`, `image`, `media`, `font`, `script`, `texttrack`, `xhr`, `fetch`,
+ // `eventsource`, `websocket`, `manifest`, `other`.
+ ResourceType() string
+
+ // Returns the matching [Response] object, or `null` if the response was not received due to error.
+ Response() (Response, error)
+
+ // Returns resource size information for given request.
+ Sizes() (*RequestSizesResult, error)
+
+ // Returns resource timing information for given request. Most of the timing values become available upon the
+ // response, `responseEnd` becomes available when request finishes. Find more information at
+ // [Resource Timing API].
+ //
+ // [Resource Timing API]: https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming
+ Timing() *RequestTiming
+
+ // URL of the request.
+ URL() string
+}
+
+// [Response] class represents responses which are received by page.
+type Response interface {
+ // An object with all the response HTTP headers associated with this response.
+ AllHeaders() (map[string]string, error)
+
+ // Returns the buffer with response body.
+ Body() ([]byte, error)
+
+ // Waits for this response to finish, returns always `null`.
+ Finished() error
+
+ // Returns the [Frame] that initiated this response.
+ Frame() Frame
+
+ // Indicates whether this Response was fulfilled by a Service Worker's Fetch Handler (i.e. via
+ // [FetchEvent.RespondWith].
+ //
+ // [FetchEvent.RespondWith]: https://developer.mozilla.org/en-US/docs/Web/API/FetchEvent/respondWith)
+ FromServiceWorker() bool
+
+ // An object with the response HTTP headers. The header names are lower-cased. Note that this method does not return
+ // security-related headers, including cookie-related ones. You can use [Response.AllHeaders] for complete list of
+ // headers that include `cookie` information.
+ Headers() map[string]string
+
+ // An array with all the request HTTP headers associated with this response. Unlike [Response.AllHeaders], header
+ // names are NOT lower-cased. Headers with multiple entries, such as `Set-Cookie`, appear in the array multiple times.
+ HeadersArray() ([]NameValue, error)
+
+ // Returns the value of the header matching the name. The name is case-insensitive. If multiple headers have the same
+ // name (except `set-cookie`), they are returned as a list separated by `, `. For `set-cookie`, the `\n` separator is
+ // used. If no headers are found, `null` is returned.
+ //
+ // name: Name of the header.
+ HeaderValue(name string) (string, error)
+
+ // Returns all values of the headers matching the name, for example `set-cookie`. The name is case-insensitive.
+ //
+ // name: Name of the header.
+ HeaderValues(name string) ([]string, error)
+
+ // Returns the JSON representation of response body.
+ // This method will throw if the response body is not parsable via `JSON.parse`.
+ JSON(v interface{}) error
+
+ // Contains a boolean stating whether the response was successful (status in the range 200-299) or not.
+ Ok() bool
+
+ // Returns the matching [Request] object.
+ Request() Request
+
+ // Returns SSL and other security information.
+ SecurityDetails() (*ResponseSecurityDetailsResult, error)
+
+ // Returns the IP address and port of the server.
+ ServerAddr() (*ResponseServerAddrResult, error)
+
+ // Contains the status code of the response (e.g., 200 for a success).
+ Status() int
+
+ // Contains the status text of the response (e.g. usually an "OK" for a success).
+ StatusText() string
+
+ // Returns the text representation of response body.
+ Text() (string, error)
+
+ // Contains the URL of the response.
+ URL() string
+}
+
+// Whenever a network route is set up with [Page.Route] or [BrowserContext.Route], the `Route` object allows to handle
+// the route.
+// Learn more about [networking].
+//
+// [networking]: https://playwright.dev/docs/network
+type Route interface {
+ // Aborts the route's request.
+ Abort(errorCode ...string) error
+
+ // Sends route's request to the network with optional overrides.
+ //
+ // # Details
+ //
+ // The “[object Object]” option applies to both the routed request and any redirects it initiates. However,
+ // “[object Object]”, “[object Object]”, and “[object Object]” only apply to the original request and are not carried
+ // over to redirected requests.
+ // [Route.Continue] will immediately send the request to the network, other matching handlers won't be invoked. Use
+ // [Route.Fallback] If you want next matching handler in the chain to be invoked.
+ // **NOTE** The `Cookie` header cannot be overridden using this method. If a value is provided, it will be ignored,
+ // and the cookie will be loaded from the browser's cookie store. To set custom cookies, use
+ // [BrowserContext.AddCookies].
+ Continue(options ...RouteContinueOptions) error
+
+ // Continues route's request with optional overrides. The method is similar to [Route.Continue] with the difference
+ // that other matching handlers will be invoked before sending the request.
+ Fallback(options ...RouteFallbackOptions) error
+
+ // Performs the request and fetches result without fulfilling it, so that the response could be modified and then
+ // fulfilled.
+ //
+ // # Details
+ //
+ // Note that “[object Object]” option will apply to the fetched request as well as any redirects initiated by it. If
+ // you want to only apply “[object Object]” to the original request, but not to redirects, look into [Route.Continue]
+ // instead.
+ Fetch(options ...RouteFetchOptions) (APIResponse, error)
+
+ // Fulfills route's request with given response.
+ Fulfill(options ...RouteFulfillOptions) error
+
+ // A request to be routed.
+ Request() Request
+}
+
+// Selectors can be used to install custom selector engines. See [extensibility] for more
+// information.
+//
+// [extensibility]: https://playwright.dev/docs/extensibility
+type Selectors interface {
+ // Selectors must be registered before creating the page.
+ //
+ // 1. name: Name that is used in selectors as a prefix, e.g. `{name: 'foo'}` enables `foo=myselectorbody` selectors. May only
+ // contain `[a-zA-Z0-9_]` characters.
+ // 2. script: Script that evaluates to a selector engine instance. The script is evaluated in the page context.
+ Register(name string, script Script, options ...SelectorsRegisterOptions) error
+
+ // Defines custom attribute name to be used in [Page.GetByTestId]. `data-testid` is used by default.
+ //
+ // attributeName: Test id attribute name.
+ SetTestIdAttribute(attributeName string)
+}
+
+// The Touchscreen class operates in main-frame CSS pixels relative to the top-left corner of the viewport. Methods on
+// the touchscreen can only be used in browser contexts that have been initialized with `hasTouch` set to true.
+// This class is limited to emulating tap gestures. For examples of other gestures simulated by manually dispatching
+// touch events, see the [emulating legacy touch events] page.
+//
+// [emulating legacy touch events]: https://playwright.dev/docs/touch-events
+type Touchscreen interface {
+ // Dispatches a `touchstart` and `touchend` event with a single touch at the position
+ // (“[object Object]”,“[object Object]”).
+ // **NOTE** [Page.Tap] the method will throw if “[object Object]” option of the browser context is false.
+ //
+ // 1. x: X coordinate relative to the main frame's viewport in CSS pixels.
+ // 2. y: Y coordinate relative to the main frame's viewport in CSS pixels.
+ Tap(x int, y int) error
+}
+
+// API for collecting and saving Playwright traces. Playwright traces can be opened in
+// [Trace Viewer] after Playwright script runs.
+// Start recording a trace before performing actions. At the end, stop tracing and save it to a file.
+//
+// [Trace Viewer]: https://playwright.dev/docs/trace-viewer
+type Tracing interface {
+ // Start tracing.
+ Start(options ...TracingStartOptions) error
+
+ // Start a new trace chunk. If you'd like to record multiple traces on the same [BrowserContext], use [Tracing.Start]
+ // once, and then create multiple trace chunks with [Tracing.StartChunk] and [Tracing.StopChunk].
+ StartChunk(options ...TracingStartChunkOptions) error
+
+ // **NOTE** Use `test.step` instead when available.
+ // Creates a new group within the trace, assigning any subsequent API calls to this group, until [Tracing.GroupEnd] is
+ // called. Groups can be nested and will be visible in the trace viewer.
+ //
+ // name: Group name shown in the trace viewer.
+ Group(name string, options ...TracingGroupOptions) error
+
+ // Closes the last group created by [Tracing.Group].
+ GroupEnd() error
+
+ // Stop tracing.
+ Stop(path ...string) error
+
+ // Stop the trace chunk. See [Tracing.StartChunk] for more details about multiple trace chunks.
+ StopChunk(path ...string) error
+}
+
+// When browser context is created with the `recordVideo` option, each page has a video object associated with it.
+type Video interface {
+ // Deletes the video file. Will wait for the video to finish if necessary.
+ Delete() error
+
+ // Returns the file system path this video will be recorded to. The video is guaranteed to be written to the
+ // filesystem upon closing the browser context. This method throws when connected remotely.
+ Path() (string, error)
+
+ // Saves the video to a user-specified path. It is safe to call this method while the video is still in progress, or
+ // after the page has closed. This method waits until the page is closed and the video is fully saved.
+ //
+ // path: Path where the video should be saved.
+ SaveAs(path string) error
+}
+
+// [WebError] class represents an unhandled exception thrown in the page. It is dispatched via the
+// [BrowserContext.OnWebError] event.
+type WebError interface {
+ // The page that produced this unhandled exception, if any.
+ Page() Page
+
+ // Unhandled error that was thrown.
+ Error() error
+}
+
+// The [WebSocket] class represents WebSocket connections within a page. It provides the ability to inspect and
+// manipulate the data being transmitted and received.
+// If you want to intercept or modify WebSocket frames, consider using [WebSocketRoute].
+type WebSocket interface {
+ // Fired when the websocket closes.
+ OnClose(fn func(WebSocket))
+
+ // Fired when the websocket receives a frame.
+ OnFrameReceived(fn func([]byte))
+
+ // Fired when the websocket sends a frame.
+ OnFrameSent(fn func([]byte))
+
+ // Fired when the websocket has an error.
+ OnSocketError(fn func(string))
+
+ // Indicates that the web socket has been closed.
+ IsClosed() bool
+
+ // Contains the URL of the WebSocket.
+ URL() string
+
+ // Waits for event to fire and passes its value into the predicate function. Returns when the predicate returns truthy
+ // value. Will throw an error if the webSocket is closed before the event is fired. Returns the event data value.
+ //
+ // event: Event name, same one would pass into `webSocket.on(event)`.
+ ExpectEvent(event string, cb func() error, options ...WebSocketExpectEventOptions) (interface{}, error)
+
+ // **NOTE** In most cases, you should use [WebSocket.ExpectEvent].
+ // Waits for given `event` to fire. If predicate is provided, it passes event's value into the `predicate` function
+ // and waits for `predicate(event)` to return a truthy value. Will throw an error if the socket is closed before the
+ // `event` is fired.
+ //
+ // event: Event name, same one typically passed into `*.on(event)`.
+ WaitForEvent(event string, options ...WebSocketWaitForEventOptions) (interface{}, error)
+}
+
+// Whenever a [`WebSocket`] route is set up with
+// [Page.RouteWebSocket] or [BrowserContext.RouteWebSocket], the `WebSocketRoute` object allows to handle the
+// WebSocket, like an actual server would do.
+// **Mocking**
+// By default, the routed WebSocket will not connect to the server. This way, you can mock entire communcation over
+// the WebSocket. Here is an example that responds to a `"request"` with a `"response"`.
+// Since we do not call [WebSocketRoute.ConnectToServer] inside the WebSocket route handler, Playwright assumes that
+// WebSocket will be mocked, and opens the WebSocket inside the page automatically.
+// Here is another example that handles JSON messages:
+// **Intercepting**
+// Alternatively, you may want to connect to the actual server, but intercept messages in-between and modify or block
+// them. Calling [WebSocketRoute.ConnectToServer] returns a server-side `WebSocketRoute` instance that you can send
+// messages to, or handle incoming messages.
+// Below is an example that modifies some messages sent by the page to the server. Messages sent from the server to
+// the page are left intact, relying on the default forwarding.
+// After connecting to the server, all **messages are forwarded** between the page and the server by default.
+// However, if you call [WebSocketRoute.OnMessage] on the original route, messages from the page to the server **will
+// not be forwarded** anymore, but should instead be handled by the “[object Object]”.
+// Similarly, calling [WebSocketRoute.OnMessage] on the server-side WebSocket will **stop forwarding messages** from
+// the server to the page, and “[object Object]” should take care of them.
+// The following example blocks some messages in both directions. Since it calls [WebSocketRoute.OnMessage] in both
+// directions, there is no automatic forwarding at all.
+//
+// [`WebSocket`]: https://developer.mozilla.org/en-US/docs/Web/API/WebSocket
+type WebSocketRoute interface {
+ // Closes one side of the WebSocket connection.
+ Close(options ...WebSocketRouteCloseOptions)
+
+ // By default, routed WebSocket does not connect to the server, so you can mock entire WebSocket communication. This
+ // method connects to the actual WebSocket server, and returns the server-side [WebSocketRoute] instance, giving the
+ // ability to send and receive messages from the server.
+ // Once connected to the server:
+ // - Messages received from the server will be **automatically forwarded** to the WebSocket in the page, unless
+ // [WebSocketRoute.OnMessage] is called on the server-side `WebSocketRoute`.
+ // - Messages sent by the [`WebSocket.send()`] call
+ // in the page will be **automatically forwarded** to the server, unless [WebSocketRoute.OnMessage] is called on
+ // the original `WebSocketRoute`.
+ // See examples at the top for more details.
+ //
+ // [`WebSocket.send()`]: https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/send
+ ConnectToServer() (WebSocketRoute, error)
+
+ // Allows to handle [`WebSocket.close`].
+ // By default, closing one side of the connection, either in the page or on the server, will close the other side.
+ // However, when [WebSocketRoute.OnClose] handler is set up, the default forwarding of closure is disabled, and
+ // handler should take care of it.
+ //
+ // handler: Function that will handle WebSocket closure. Received an optional
+ // [close code](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/close#code) and an optional
+ // [close reason](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/close#reason).
+ //
+ // [`WebSocket.close`]: https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/close
+ OnClose(handler func(*int, *string))
+
+ // This method allows to handle messages that are sent by the WebSocket, either from the page or from the server.
+ // When called on the original WebSocket route, this method handles messages sent from the page. You can handle this
+ // messages by responding to them with [WebSocketRoute.Send], forwarding them to the server-side connection returned
+ // by [WebSocketRoute.ConnectToServer] or do something else.
+ // Once this method is called, messages are not automatically forwarded to the server or to the page - you should do
+ // that manually by calling [WebSocketRoute.Send]. See examples at the top for more details.
+ // Calling this method again will override the handler with a new one.
+ //
+ // handler: Function that will handle messages.
+ OnMessage(handler func(interface{}))
+
+ // Sends a message to the WebSocket. When called on the original WebSocket, sends the message to the page. When called
+ // on the result of [WebSocketRoute.ConnectToServer], sends the message to the server. See examples at the top for
+ // more details.
+ //
+ // message: Message to send.
+ Send(message interface{})
+
+ // URL of the WebSocket created in the page.
+ URL() string
+}
+
+// The Worker class represents a [WebWorker].
+// `worker` event is emitted on the page object to signal a worker creation. `close` event is emitted on the worker
+// object when the worker is gone.
+//
+// [WebWorker]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API
+type Worker interface {
+ // Emitted when this dedicated [WebWorker] is
+ // terminated.
+ //
+ // [WebWorker]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API
+ OnClose(fn func(Worker))
+
+ // Returns the return value of “[object Object]”.
+ // If the function passed to the [Worker.Evaluate] returns a [Promise], then [Worker.Evaluate] would wait for the
+ // promise to resolve and return its value.
+ // If the function passed to the [Worker.Evaluate] returns a non-[Serializable] value, then [Worker.Evaluate] returns
+ // `undefined`. Playwright also supports transferring some additional values that are not serializable by `JSON`:
+ // `-0`, `NaN`, `Infinity`, `-Infinity`.
+ //
+ // 1. expression: JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the
+ // function is automatically invoked.
+ // 2. arg: Optional argument to pass to “[object Object]”.
+ Evaluate(expression string, arg ...interface{}) (interface{}, error)
+
+ // Returns the return value of “[object Object]” as a [JSHandle].
+ // The only difference between [Worker.Evaluate] and [Worker.EvaluateHandle] is that [Worker.EvaluateHandle] returns
+ // [JSHandle].
+ // If the function passed to the [Worker.EvaluateHandle] returns a [Promise], then [Worker.EvaluateHandle] would wait
+ // for the promise to resolve and return its value.
+ //
+ // 1. expression: JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the
+ // function is automatically invoked.
+ // 2. arg: Optional argument to pass to “[object Object]”.
+ EvaluateHandle(expression string, arg ...interface{}) (JSHandle, error)
+
+ URL() string
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/generated-structs.go b/vendor/github.com/playwright-community/playwright-go/generated-structs.go
new file mode 100644
index 0000000..7a90f5a
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/generated-structs.go
@@ -0,0 +1,4364 @@
+package playwright
+
+type APIRequestNewContextOptions struct {
+ // Methods like [APIRequestContext.Get] take the base URL into consideration by using the
+ // [`URL()`] constructor for building the corresponding URL.
+ // Examples:
+ // - baseURL: `http://localhost:3000` and sending request to `/bar.html` results in `http://localhost:3000/bar.html`
+ // - baseURL: `http://localhost:3000/foo/` and sending request to `./bar.html` results in
+ // `http://localhost:3000/foo/bar.html`
+ // - baseURL: `http://localhost:3000/foo` (without trailing slash) and navigating to `./bar.html` results in
+ // `http://localhost:3000/bar.html`
+ //
+ // [`URL()`]: https://developer.mozilla.org/en-US/docs/Web/API/URL/URL
+ BaseURL *string `json:"baseURL"`
+ // TLS Client Authentication allows the server to request a client certificate and verify it.
+ //
+ // # Details
+ //
+ // An array of client certificates to be used. Each certificate object must have either both `certPath` and `keyPath`,
+ // a single `pfxPath`, or their corresponding direct value equivalents (`cert` and `key`, or `pfx`). Optionally,
+ // `passphrase` property should be provided if the certificate is encrypted. The `origin` property should be provided
+ // with an exact match to the request origin that the certificate is valid for.
+ // **NOTE** When using WebKit on macOS, accessing `localhost` will not pick up client certificates. You can make it
+ // work by replacing `localhost` with `local.playwright`.
+ ClientCertificates []ClientCertificate `json:"clientCertificates"`
+ // An object containing additional HTTP headers to be sent with every request. Defaults to none.
+ ExtraHttpHeaders map[string]string `json:"extraHTTPHeaders"`
+ // Whether to throw on response codes other than 2xx and 3xx. By default response object is returned for all status
+ // codes.
+ FailOnStatusCode *bool `json:"failOnStatusCode"`
+ // Credentials for [HTTP authentication]. If no
+ // origin is specified, the username and password are sent to any servers upon unauthorized responses.
+ //
+ // [HTTP authentication]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication
+ HttpCredentials *HttpCredentials `json:"httpCredentials"`
+ // Whether to ignore HTTPS errors when sending network requests. Defaults to `false`.
+ IgnoreHttpsErrors *bool `json:"ignoreHTTPSErrors"`
+ // Maximum number of request redirects that will be followed automatically. An error will be thrown if the number is
+ // exceeded. Defaults to `20`. Pass `0` to not follow redirects. This can be overwritten for each request
+ // individually.
+ MaxRedirects *int `json:"maxRedirects"`
+ // Network proxy settings.
+ Proxy *Proxy `json:"proxy"`
+ // Populates context with given storage state. This option can be used to initialize context with logged-in
+ // information obtained via [BrowserContext.StorageState] or [APIRequestContext.StorageState]. Either a path to the
+ // file with saved storage, or the value returned by one of [BrowserContext.StorageState] or
+ // [APIRequestContext.StorageState] methods.
+ StorageState *StorageState `json:"storageState"`
+ // Populates context with given storage state. This option can be used to initialize context with logged-in
+ // information obtained via [BrowserContext.StorageState]. Path to the file with saved storage state.
+ StorageStatePath *string `json:"storageStatePath"`
+ // Maximum time in milliseconds to wait for the response. Defaults to `30000` (30 seconds). Pass `0` to disable
+ // timeout.
+ Timeout *float64 `json:"timeout"`
+ // Specific user agent to use in this context.
+ UserAgent *string `json:"userAgent"`
+}
+
+type APIRequestContextDeleteOptions struct {
+ // Allows to set post data of the request. If the data parameter is an object, it will be serialized to json string
+ // and `content-type` header will be set to `application/json` if not explicitly set. Otherwise the `content-type`
+ // header will be set to `application/octet-stream` if not explicitly set.
+ Data interface{} `json:"data"`
+ // Whether to throw on response codes other than 2xx and 3xx. By default response object is returned for all status
+ // codes.
+ FailOnStatusCode *bool `json:"failOnStatusCode"`
+ // Provides an object that will be serialized as html form using `application/x-www-form-urlencoded` encoding and sent
+ // as this request body. If this parameter is specified `content-type` header will be set to
+ // `application/x-www-form-urlencoded` unless explicitly provided.
+ Form interface{} `json:"form"`
+ // Allows to set HTTP headers. These headers will apply to the fetched request as well as any redirects initiated by
+ // it.
+ Headers map[string]string `json:"headers"`
+ // Whether to ignore HTTPS errors when sending network requests. Defaults to `false`.
+ IgnoreHttpsErrors *bool `json:"ignoreHTTPSErrors"`
+ // Maximum number of request redirects that will be followed automatically. An error will be thrown if the number is
+ // exceeded. Defaults to `20`. Pass `0` to not follow redirects.
+ MaxRedirects *int `json:"maxRedirects"`
+ // Maximum number of times network errors should be retried. Currently only `ECONNRESET` error is retried. Does not
+ // retry based on HTTP response codes. An error will be thrown if the limit is exceeded. Defaults to `0` - no retries.
+ MaxRetries *int `json:"maxRetries"`
+ // Provides an object that will be serialized as html form using `multipart/form-data` encoding and sent as this
+ // request body. If this parameter is specified `content-type` header will be set to `multipart/form-data` unless
+ // explicitly provided. File values can be passed either as
+ // [`fs.ReadStream`] or as file-like object containing file
+ // name, mime-type and its content.
+ //
+ // [`fs.ReadStream`]: https://nodejs.org/api/fs.html#fs_class_fs_readstream
+ Multipart interface{} `json:"multipart"`
+ // Query parameters to be sent with the URL.
+ Params map[string]interface{} `json:"params"`
+ // Request timeout in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout.
+ Timeout *float64 `json:"timeout"`
+}
+
+type APIRequestContextDisposeOptions struct {
+ // The reason to be reported to the operations interrupted by the context disposal.
+ Reason *string `json:"reason"`
+}
+
+type APIRequestContextFetchOptions struct {
+ // Allows to set post data of the request. If the data parameter is an object, it will be serialized to json string
+ // and `content-type` header will be set to `application/json` if not explicitly set. Otherwise the `content-type`
+ // header will be set to `application/octet-stream` if not explicitly set.
+ Data interface{} `json:"data"`
+ // Whether to throw on response codes other than 2xx and 3xx. By default response object is returned for all status
+ // codes.
+ FailOnStatusCode *bool `json:"failOnStatusCode"`
+ // Provides an object that will be serialized as html form using `application/x-www-form-urlencoded` encoding and sent
+ // as this request body. If this parameter is specified `content-type` header will be set to
+ // `application/x-www-form-urlencoded` unless explicitly provided.
+ Form interface{} `json:"form"`
+ // Allows to set HTTP headers. These headers will apply to the fetched request as well as any redirects initiated by
+ // it.
+ Headers map[string]string `json:"headers"`
+ // Whether to ignore HTTPS errors when sending network requests. Defaults to `false`.
+ IgnoreHttpsErrors *bool `json:"ignoreHTTPSErrors"`
+ // Maximum number of request redirects that will be followed automatically. An error will be thrown if the number is
+ // exceeded. Defaults to `20`. Pass `0` to not follow redirects.
+ MaxRedirects *int `json:"maxRedirects"`
+ // Maximum number of times network errors should be retried. Currently only `ECONNRESET` error is retried. Does not
+ // retry based on HTTP response codes. An error will be thrown if the limit is exceeded. Defaults to `0` - no retries.
+ MaxRetries *int `json:"maxRetries"`
+ // If set changes the fetch method (e.g. [PUT] or
+ // [POST]. If not specified, GET method is used.
+ //
+ // [PUT]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT
+ // [POST]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST)
+ Method *string `json:"method"`
+ // Provides an object that will be serialized as html form using `multipart/form-data` encoding and sent as this
+ // request body. If this parameter is specified `content-type` header will be set to `multipart/form-data` unless
+ // explicitly provided. File values can be passed either as
+ // [`fs.ReadStream`] or as file-like object containing file
+ // name, mime-type and its content.
+ //
+ // [`fs.ReadStream`]: https://nodejs.org/api/fs.html#fs_class_fs_readstream
+ Multipart interface{} `json:"multipart"`
+ // Query parameters to be sent with the URL.
+ Params map[string]interface{} `json:"params"`
+ // Request timeout in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout.
+ Timeout *float64 `json:"timeout"`
+}
+
+type APIRequestContextGetOptions struct {
+ // Allows to set post data of the request. If the data parameter is an object, it will be serialized to json string
+ // and `content-type` header will be set to `application/json` if not explicitly set. Otherwise the `content-type`
+ // header will be set to `application/octet-stream` if not explicitly set.
+ Data interface{} `json:"data"`
+ // Whether to throw on response codes other than 2xx and 3xx. By default response object is returned for all status
+ // codes.
+ FailOnStatusCode *bool `json:"failOnStatusCode"`
+ // Provides an object that will be serialized as html form using `application/x-www-form-urlencoded` encoding and sent
+ // as this request body. If this parameter is specified `content-type` header will be set to
+ // `application/x-www-form-urlencoded` unless explicitly provided.
+ Form interface{} `json:"form"`
+ // Allows to set HTTP headers. These headers will apply to the fetched request as well as any redirects initiated by
+ // it.
+ Headers map[string]string `json:"headers"`
+ // Whether to ignore HTTPS errors when sending network requests. Defaults to `false`.
+ IgnoreHttpsErrors *bool `json:"ignoreHTTPSErrors"`
+ // Maximum number of request redirects that will be followed automatically. An error will be thrown if the number is
+ // exceeded. Defaults to `20`. Pass `0` to not follow redirects.
+ MaxRedirects *int `json:"maxRedirects"`
+ // Maximum number of times network errors should be retried. Currently only `ECONNRESET` error is retried. Does not
+ // retry based on HTTP response codes. An error will be thrown if the limit is exceeded. Defaults to `0` - no retries.
+ MaxRetries *int `json:"maxRetries"`
+ // Provides an object that will be serialized as html form using `multipart/form-data` encoding and sent as this
+ // request body. If this parameter is specified `content-type` header will be set to `multipart/form-data` unless
+ // explicitly provided. File values can be passed either as
+ // [`fs.ReadStream`] or as file-like object containing file
+ // name, mime-type and its content.
+ //
+ // [`fs.ReadStream`]: https://nodejs.org/api/fs.html#fs_class_fs_readstream
+ Multipart interface{} `json:"multipart"`
+ // Query parameters to be sent with the URL.
+ Params map[string]interface{} `json:"params"`
+ // Request timeout in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout.
+ Timeout *float64 `json:"timeout"`
+}
+
+type APIRequestContextHeadOptions struct {
+ // Allows to set post data of the request. If the data parameter is an object, it will be serialized to json string
+ // and `content-type` header will be set to `application/json` if not explicitly set. Otherwise the `content-type`
+ // header will be set to `application/octet-stream` if not explicitly set.
+ Data interface{} `json:"data"`
+ // Whether to throw on response codes other than 2xx and 3xx. By default response object is returned for all status
+ // codes.
+ FailOnStatusCode *bool `json:"failOnStatusCode"`
+ // Provides an object that will be serialized as html form using `application/x-www-form-urlencoded` encoding and sent
+ // as this request body. If this parameter is specified `content-type` header will be set to
+ // `application/x-www-form-urlencoded` unless explicitly provided.
+ Form interface{} `json:"form"`
+ // Allows to set HTTP headers. These headers will apply to the fetched request as well as any redirects initiated by
+ // it.
+ Headers map[string]string `json:"headers"`
+ // Whether to ignore HTTPS errors when sending network requests. Defaults to `false`.
+ IgnoreHttpsErrors *bool `json:"ignoreHTTPSErrors"`
+ // Maximum number of request redirects that will be followed automatically. An error will be thrown if the number is
+ // exceeded. Defaults to `20`. Pass `0` to not follow redirects.
+ MaxRedirects *int `json:"maxRedirects"`
+ // Maximum number of times network errors should be retried. Currently only `ECONNRESET` error is retried. Does not
+ // retry based on HTTP response codes. An error will be thrown if the limit is exceeded. Defaults to `0` - no retries.
+ MaxRetries *int `json:"maxRetries"`
+ // Provides an object that will be serialized as html form using `multipart/form-data` encoding and sent as this
+ // request body. If this parameter is specified `content-type` header will be set to `multipart/form-data` unless
+ // explicitly provided. File values can be passed either as
+ // [`fs.ReadStream`] or as file-like object containing file
+ // name, mime-type and its content.
+ //
+ // [`fs.ReadStream`]: https://nodejs.org/api/fs.html#fs_class_fs_readstream
+ Multipart interface{} `json:"multipart"`
+ // Query parameters to be sent with the URL.
+ Params map[string]interface{} `json:"params"`
+ // Request timeout in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout.
+ Timeout *float64 `json:"timeout"`
+}
+
+type APIRequestContextPatchOptions struct {
+ // Allows to set post data of the request. If the data parameter is an object, it will be serialized to json string
+ // and `content-type` header will be set to `application/json` if not explicitly set. Otherwise the `content-type`
+ // header will be set to `application/octet-stream` if not explicitly set.
+ Data interface{} `json:"data"`
+ // Whether to throw on response codes other than 2xx and 3xx. By default response object is returned for all status
+ // codes.
+ FailOnStatusCode *bool `json:"failOnStatusCode"`
+ // Provides an object that will be serialized as html form using `application/x-www-form-urlencoded` encoding and sent
+ // as this request body. If this parameter is specified `content-type` header will be set to
+ // `application/x-www-form-urlencoded` unless explicitly provided.
+ Form interface{} `json:"form"`
+ // Allows to set HTTP headers. These headers will apply to the fetched request as well as any redirects initiated by
+ // it.
+ Headers map[string]string `json:"headers"`
+ // Whether to ignore HTTPS errors when sending network requests. Defaults to `false`.
+ IgnoreHttpsErrors *bool `json:"ignoreHTTPSErrors"`
+ // Maximum number of request redirects that will be followed automatically. An error will be thrown if the number is
+ // exceeded. Defaults to `20`. Pass `0` to not follow redirects.
+ MaxRedirects *int `json:"maxRedirects"`
+ // Maximum number of times network errors should be retried. Currently only `ECONNRESET` error is retried. Does not
+ // retry based on HTTP response codes. An error will be thrown if the limit is exceeded. Defaults to `0` - no retries.
+ MaxRetries *int `json:"maxRetries"`
+ // Provides an object that will be serialized as html form using `multipart/form-data` encoding and sent as this
+ // request body. If this parameter is specified `content-type` header will be set to `multipart/form-data` unless
+ // explicitly provided. File values can be passed either as
+ // [`fs.ReadStream`] or as file-like object containing file
+ // name, mime-type and its content.
+ //
+ // [`fs.ReadStream`]: https://nodejs.org/api/fs.html#fs_class_fs_readstream
+ Multipart interface{} `json:"multipart"`
+ // Query parameters to be sent with the URL.
+ Params map[string]interface{} `json:"params"`
+ // Request timeout in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout.
+ Timeout *float64 `json:"timeout"`
+}
+
+type APIRequestContextPostOptions struct {
+ // Allows to set post data of the request. If the data parameter is an object, it will be serialized to json string
+ // and `content-type` header will be set to `application/json` if not explicitly set. Otherwise the `content-type`
+ // header will be set to `application/octet-stream` if not explicitly set.
+ Data interface{} `json:"data"`
+ // Whether to throw on response codes other than 2xx and 3xx. By default response object is returned for all status
+ // codes.
+ FailOnStatusCode *bool `json:"failOnStatusCode"`
+ // Provides an object that will be serialized as html form using `application/x-www-form-urlencoded` encoding and sent
+ // as this request body. If this parameter is specified `content-type` header will be set to
+ // `application/x-www-form-urlencoded` unless explicitly provided.
+ Form interface{} `json:"form"`
+ // Allows to set HTTP headers. These headers will apply to the fetched request as well as any redirects initiated by
+ // it.
+ Headers map[string]string `json:"headers"`
+ // Whether to ignore HTTPS errors when sending network requests. Defaults to `false`.
+ IgnoreHttpsErrors *bool `json:"ignoreHTTPSErrors"`
+ // Maximum number of request redirects that will be followed automatically. An error will be thrown if the number is
+ // exceeded. Defaults to `20`. Pass `0` to not follow redirects.
+ MaxRedirects *int `json:"maxRedirects"`
+ // Maximum number of times network errors should be retried. Currently only `ECONNRESET` error is retried. Does not
+ // retry based on HTTP response codes. An error will be thrown if the limit is exceeded. Defaults to `0` - no retries.
+ MaxRetries *int `json:"maxRetries"`
+ // Provides an object that will be serialized as html form using `multipart/form-data` encoding and sent as this
+ // request body. If this parameter is specified `content-type` header will be set to `multipart/form-data` unless
+ // explicitly provided. File values can be passed either as
+ // [`fs.ReadStream`] or as file-like object containing file
+ // name, mime-type and its content.
+ //
+ // [`fs.ReadStream`]: https://nodejs.org/api/fs.html#fs_class_fs_readstream
+ Multipart interface{} `json:"multipart"`
+ // Query parameters to be sent with the URL.
+ Params map[string]interface{} `json:"params"`
+ // Request timeout in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout.
+ Timeout *float64 `json:"timeout"`
+}
+
+type APIRequestContextPutOptions struct {
+ // Allows to set post data of the request. If the data parameter is an object, it will be serialized to json string
+ // and `content-type` header will be set to `application/json` if not explicitly set. Otherwise the `content-type`
+ // header will be set to `application/octet-stream` if not explicitly set.
+ Data interface{} `json:"data"`
+ // Whether to throw on response codes other than 2xx and 3xx. By default response object is returned for all status
+ // codes.
+ FailOnStatusCode *bool `json:"failOnStatusCode"`
+ // Provides an object that will be serialized as html form using `application/x-www-form-urlencoded` encoding and sent
+ // as this request body. If this parameter is specified `content-type` header will be set to
+ // `application/x-www-form-urlencoded` unless explicitly provided.
+ Form interface{} `json:"form"`
+ // Allows to set HTTP headers. These headers will apply to the fetched request as well as any redirects initiated by
+ // it.
+ Headers map[string]string `json:"headers"`
+ // Whether to ignore HTTPS errors when sending network requests. Defaults to `false`.
+ IgnoreHttpsErrors *bool `json:"ignoreHTTPSErrors"`
+ // Maximum number of request redirects that will be followed automatically. An error will be thrown if the number is
+ // exceeded. Defaults to `20`. Pass `0` to not follow redirects.
+ MaxRedirects *int `json:"maxRedirects"`
+ // Maximum number of times network errors should be retried. Currently only `ECONNRESET` error is retried. Does not
+ // retry based on HTTP response codes. An error will be thrown if the limit is exceeded. Defaults to `0` - no retries.
+ MaxRetries *int `json:"maxRetries"`
+ // Provides an object that will be serialized as html form using `multipart/form-data` encoding and sent as this
+ // request body. If this parameter is specified `content-type` header will be set to `multipart/form-data` unless
+ // explicitly provided. File values can be passed either as
+ // [`fs.ReadStream`] or as file-like object containing file
+ // name, mime-type and its content.
+ //
+ // [`fs.ReadStream`]: https://nodejs.org/api/fs.html#fs_class_fs_readstream
+ Multipart interface{} `json:"multipart"`
+ // Query parameters to be sent with the URL.
+ Params map[string]interface{} `json:"params"`
+ // Request timeout in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout.
+ Timeout *float64 `json:"timeout"`
+}
+
+type StorageState struct {
+ Cookies []Cookie `json:"cookies"`
+ Origins []Origin `json:"origins"`
+}
+
+type NameValue struct {
+ // Name of the header.
+ Name string `json:"name"`
+ // Value of the header.
+ Value string `json:"value"`
+}
+
+type BrowserCloseOptions struct {
+ // The reason to be reported to the operations interrupted by the browser closure.
+ Reason *string `json:"reason"`
+}
+
+type BrowserNewContextOptions struct {
+ // Whether to automatically download all the attachments. Defaults to `true` where all the downloads are accepted.
+ AcceptDownloads *bool `json:"acceptDownloads"`
+ // When using [Page.Goto], [Page.Route], [Page.WaitForURL], [Page.ExpectRequest], or [Page.ExpectResponse] it takes
+ // the base URL in consideration by using the [`URL()`]
+ // constructor for building the corresponding URL. Unset by default. Examples:
+ // - baseURL: `http://localhost:3000` and navigating to `/bar.html` results in `http://localhost:3000/bar.html`
+ // - baseURL: `http://localhost:3000/foo/` and navigating to `./bar.html` results in
+ // `http://localhost:3000/foo/bar.html`
+ // - baseURL: `http://localhost:3000/foo` (without trailing slash) and navigating to `./bar.html` results in
+ // `http://localhost:3000/bar.html`
+ //
+ // [`URL()`]: https://developer.mozilla.org/en-US/docs/Web/API/URL/URL
+ BaseURL *string `json:"baseURL"`
+ // Toggles bypassing page's Content-Security-Policy. Defaults to `false`.
+ BypassCSP *bool `json:"bypassCSP"`
+ // TLS Client Authentication allows the server to request a client certificate and verify it.
+ //
+ // # Details
+ //
+ // An array of client certificates to be used. Each certificate object must have either both `certPath` and `keyPath`,
+ // a single `pfxPath`, or their corresponding direct value equivalents (`cert` and `key`, or `pfx`). Optionally,
+ // `passphrase` property should be provided if the certificate is encrypted. The `origin` property should be provided
+ // with an exact match to the request origin that the certificate is valid for.
+ // **NOTE** When using WebKit on macOS, accessing `localhost` will not pick up client certificates. You can make it
+ // work by replacing `localhost` with `local.playwright`.
+ ClientCertificates []ClientCertificate `json:"clientCertificates"`
+ // Emulates [prefers-colors-scheme]
+ // media feature, supported values are `light` and `dark`. See [Page.EmulateMedia] for more details. Passing
+ // `no-override` resets emulation to system defaults. Defaults to `light`.
+ //
+ // [prefers-colors-scheme]: https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme
+ ColorScheme *ColorScheme `json:"colorScheme"`
+ // Specify device scale factor (can be thought of as dpr). Defaults to `1`. Learn more about
+ // [emulating devices with device scale factor].
+ //
+ // [emulating devices with device scale factor]: https://playwright.dev/docs/emulation#devices
+ DeviceScaleFactor *float64 `json:"deviceScaleFactor"`
+ // An object containing additional HTTP headers to be sent with every request. Defaults to none.
+ ExtraHttpHeaders map[string]string `json:"extraHTTPHeaders"`
+ // Emulates `forced-colors` media feature, supported values are `active`, `none`. See [Page.EmulateMedia] for
+ // more details. Passing `no-override` resets emulation to system defaults. Defaults to `none`.
+ ForcedColors *ForcedColors `json:"forcedColors"`
+ Geolocation *Geolocation `json:"geolocation"`
+ // Specifies if viewport supports touch events. Defaults to false. Learn more about
+ // [mobile emulation].
+ //
+ // [mobile emulation]: https://playwright.dev/docs/emulation#devices
+ HasTouch *bool `json:"hasTouch"`
+ // Credentials for [HTTP authentication]. If no
+ // origin is specified, the username and password are sent to any servers upon unauthorized responses.
+ //
+ // [HTTP authentication]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication
+ HttpCredentials *HttpCredentials `json:"httpCredentials"`
+ // Whether to ignore HTTPS errors when sending network requests. Defaults to `false`.
+ IgnoreHttpsErrors *bool `json:"ignoreHTTPSErrors"`
+ // Whether the `meta viewport` tag is taken into account and touch events are enabled. isMobile is a part of device,
+ // so you don't actually need to set it manually. Defaults to `false` and is not supported in Firefox. Learn more
+ // about [mobile emulation].
+ //
+ // [mobile emulation]: https://playwright.dev/docs/emulation#ismobile
+ IsMobile *bool `json:"isMobile"`
+ // Whether or not to enable JavaScript in the context. Defaults to `true`. Learn more about
+ // [disabling JavaScript].
+ //
+ // [disabling JavaScript]: https://playwright.dev/docs/emulation#javascript-enabled
+ JavaScriptEnabled *bool `json:"javaScriptEnabled"`
+ // Specify user locale, for example `en-GB`, `de-DE`, etc. Locale will affect `navigator.language` value,
+ // `Accept-Language` request header value as well as number and date formatting rules. Defaults to the system default
+ // locale. Learn more about emulation in our [emulation guide].
+ //
+ // [emulation guide]: https://playwright.dev/docs/emulation#locale--timezone
+ Locale *string `json:"locale"`
+ // Does not enforce fixed viewport, allows resizing window in the headed mode.
+ NoViewport *bool `json:"noViewport"`
+ // Whether to emulate network being offline. Defaults to `false`. Learn more about
+ // [network emulation].
+ //
+ // [network emulation]: https://playwright.dev/docs/emulation#offline
+ Offline *bool `json:"offline"`
+ // A list of permissions to grant to all pages in this context. See [BrowserContext.GrantPermissions] for more
+ // details. Defaults to none.
+ Permissions []string `json:"permissions"`
+ // Network proxy settings to use with this context. Defaults to none.
+ Proxy *Proxy `json:"proxy"`
+ // Optional setting to control resource content management. If `omit` is specified, content is not persisted. If
+ // `attach` is specified, resources are persisted as separate files and all of these files are archived along with the
+ // HAR file. Defaults to `embed`, which stores content inline the HAR file as per HAR specification.
+ RecordHarContent *HarContentPolicy `json:"recordHarContent"`
+ // When set to `minimal`, only record information necessary for routing from HAR. This omits sizes, timing, page,
+ // cookies, security and other types of HAR information that are not used when replaying from HAR. Defaults to `full`.
+ RecordHarMode *HarMode `json:"recordHarMode"`
+ // Optional setting to control whether to omit request content from the HAR. Defaults to `false`.
+ RecordHarOmitContent *bool `json:"recordHarOmitContent"`
+ // Enables [HAR] recording for all pages into the specified HAR file
+ // on the filesystem. If not specified, the HAR is not recorded. Make sure to call [BrowserContext.Close] for the HAR
+ // to be saved.
+ //
+ // [HAR]: http://www.softwareishard.com/blog/har-12-spec
+ RecordHarPath *string `json:"recordHarPath"`
+ RecordHarURLFilter interface{} `json:"recordHarUrlFilter"`
+ // Enables video recording for all pages into `recordVideo.dir` directory. If not specified videos are not recorded.
+ // Make sure to await [BrowserContext.Close] for videos to be saved.
+ RecordVideo *RecordVideo `json:"recordVideo"`
+ // Emulates `prefers-reduced-motion` media feature, supported values are `reduce`, `no-preference`. See
+ // [Page.EmulateMedia] for more details. Passing `no-override` resets emulation to system defaults. Defaults to
+ // `no-preference`.
+ ReducedMotion *ReducedMotion `json:"reducedMotion"`
+ // Emulates consistent window screen size available inside web page via `window.screen`. Is only used when the
+ // “[object Object]” is set.
+ Screen *Size `json:"screen"`
+ // Whether to allow sites to register Service workers. Defaults to `allow`.
+ // - `allow`: [Service Workers] can be
+ // registered.
+ // - `block`: Playwright will block all registration of Service Workers.
+ //
+ // [Service Workers]: https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API
+ ServiceWorkers *ServiceWorkerPolicy `json:"serviceWorkers"`
+ // Learn more about [storage state and auth].
+ // Populates context with given storage state. This option can be used to initialize context with logged-in
+ // information obtained via [BrowserContext.StorageState].
+ //
+ // [storage state and auth]: https://playwright.dev/docs/auth
+ StorageState *OptionalStorageState `json:"storageState"`
+ // Populates context with given storage state. This option can be used to initialize context with logged-in
+ // information obtained via [BrowserContext.StorageState]. Path to the file with saved storage state.
+ StorageStatePath *string `json:"storageStatePath"`
+ // If set to true, enables strict selectors mode for this context. In the strict selectors mode all operations on
+ // selectors that imply single target DOM element will throw when more than one element matches the selector. This
+ // option does not affect any Locator APIs (Locators are always strict). Defaults to `false`. See [Locator] to learn
+ // more about the strict mode.
+ StrictSelectors *bool `json:"strictSelectors"`
+ // Changes the timezone of the context. See
+ // [ICU's metaZones.txt]
+ // for a list of supported timezone IDs. Defaults to the system timezone.
+ //
+ // [ICU's metaZones.txt]: https://cs.chromium.org/chromium/src/third_party/icu/source/data/misc/metaZones.txt?rcl=faee8bc70570192d82d2978a71e2a615788597d1
+ TimezoneId *string `json:"timezoneId"`
+ // Specific user agent to use in this context.
+ UserAgent *string `json:"userAgent"`
+ // Sets a consistent viewport for each page. Defaults to an 1280x720 viewport. `no_viewport` disables the fixed
+ // viewport. Learn more about [viewport emulation].
+ //
+ // [viewport emulation]: https://playwright.dev/docs/emulation#viewport
+ Viewport *Size `json:"viewport"`
+}
+
+type BrowserNewPageOptions struct {
+ // Whether to automatically download all the attachments. Defaults to `true` where all the downloads are accepted.
+ AcceptDownloads *bool `json:"acceptDownloads"`
+ // When using [Page.Goto], [Page.Route], [Page.WaitForURL], [Page.ExpectRequest], or [Page.ExpectResponse] it takes
+ // the base URL in consideration by using the [`URL()`]
+ // constructor for building the corresponding URL. Unset by default. Examples:
+ // - baseURL: `http://localhost:3000` and navigating to `/bar.html` results in `http://localhost:3000/bar.html`
+ // - baseURL: `http://localhost:3000/foo/` and navigating to `./bar.html` results in
+ // `http://localhost:3000/foo/bar.html`
+ // - baseURL: `http://localhost:3000/foo` (without trailing slash) and navigating to `./bar.html` results in
+ // `http://localhost:3000/bar.html`
+ //
+ // [`URL()`]: https://developer.mozilla.org/en-US/docs/Web/API/URL/URL
+ BaseURL *string `json:"baseURL"`
+ // Toggles bypassing page's Content-Security-Policy. Defaults to `false`.
+ BypassCSP *bool `json:"bypassCSP"`
+ // TLS Client Authentication allows the server to request a client certificate and verify it.
+ //
+ // # Details
+ //
+ // An array of client certificates to be used. Each certificate object must have either both `certPath` and `keyPath`,
+ // a single `pfxPath`, or their corresponding direct value equivalents (`cert` and `key`, or `pfx`). Optionally,
+ // `passphrase` property should be provided if the certificate is encrypted. The `origin` property should be provided
+ // with an exact match to the request origin that the certificate is valid for.
+ // **NOTE** When using WebKit on macOS, accessing `localhost` will not pick up client certificates. You can make it
+ // work by replacing `localhost` with `local.playwright`.
+ ClientCertificates []ClientCertificate `json:"clientCertificates"`
+ // Emulates [prefers-colors-scheme]
+ // media feature, supported values are `light` and `dark`. See [Page.EmulateMedia] for more details. Passing
+ // `no-override` resets emulation to system defaults. Defaults to `light`.
+ //
+ // [prefers-colors-scheme]: https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme
+ ColorScheme *ColorScheme `json:"colorScheme"`
+ // Specify device scale factor (can be thought of as dpr). Defaults to `1`. Learn more about
+ // [emulating devices with device scale factor].
+ //
+ // [emulating devices with device scale factor]: https://playwright.dev/docs/emulation#devices
+ DeviceScaleFactor *float64 `json:"deviceScaleFactor"`
+ // An object containing additional HTTP headers to be sent with every request. Defaults to none.
+ ExtraHttpHeaders map[string]string `json:"extraHTTPHeaders"`
+ // Emulates `forced-colors` media feature, supported values are `active`, `none`. See [Page.EmulateMedia] for
+ // more details. Passing `no-override` resets emulation to system defaults. Defaults to `none`.
+ ForcedColors *ForcedColors `json:"forcedColors"`
+ Geolocation *Geolocation `json:"geolocation"`
+ // Specifies if viewport supports touch events. Defaults to false. Learn more about
+ // [mobile emulation].
+ //
+ // [mobile emulation]: https://playwright.dev/docs/emulation#devices
+ HasTouch *bool `json:"hasTouch"`
+ // Credentials for [HTTP authentication]. If no
+ // origin is specified, the username and password are sent to any servers upon unauthorized responses.
+ //
+ // [HTTP authentication]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication
+ HttpCredentials *HttpCredentials `json:"httpCredentials"`
+ // Whether to ignore HTTPS errors when sending network requests. Defaults to `false`.
+ IgnoreHttpsErrors *bool `json:"ignoreHTTPSErrors"`
+ // Whether the `meta viewport` tag is taken into account and touch events are enabled. isMobile is a part of device,
+ // so you don't actually need to set it manually. Defaults to `false` and is not supported in Firefox. Learn more
+ // about [mobile emulation].
+ //
+ // [mobile emulation]: https://playwright.dev/docs/emulation#ismobile
+ IsMobile *bool `json:"isMobile"`
+ // Whether or not to enable JavaScript in the context. Defaults to `true`. Learn more about
+ // [disabling JavaScript].
+ //
+ // [disabling JavaScript]: https://playwright.dev/docs/emulation#javascript-enabled
+ JavaScriptEnabled *bool `json:"javaScriptEnabled"`
+ // Specify user locale, for example `en-GB`, `de-DE`, etc. Locale will affect `navigator.language` value,
+ // `Accept-Language` request header value as well as number and date formatting rules. Defaults to the system default
+ // locale. Learn more about emulation in our [emulation guide].
+ //
+ // [emulation guide]: https://playwright.dev/docs/emulation#locale--timezone
+ Locale *string `json:"locale"`
+ // Does not enforce fixed viewport, allows resizing window in the headed mode.
+ NoViewport *bool `json:"noViewport"`
+ // Whether to emulate network being offline. Defaults to `false`. Learn more about
+ // [network emulation].
+ //
+ // [network emulation]: https://playwright.dev/docs/emulation#offline
+ Offline *bool `json:"offline"`
+ // A list of permissions to grant to all pages in this context. See [BrowserContext.GrantPermissions] for more
+ // details. Defaults to none.
+ Permissions []string `json:"permissions"`
+ // Network proxy settings to use with this context. Defaults to none.
+ Proxy *Proxy `json:"proxy"`
+ // Optional setting to control resource content management. If `omit` is specified, content is not persisted. If
+ // `attach` is specified, resources are persisted as separate files and all of these files are archived along with the
+ // HAR file. Defaults to `embed`, which stores content inline the HAR file as per HAR specification.
+ RecordHarContent *HarContentPolicy `json:"recordHarContent"`
+ // When set to `minimal`, only record information necessary for routing from HAR. This omits sizes, timing, page,
+ // cookies, security and other types of HAR information that are not used when replaying from HAR. Defaults to `full`.
+ RecordHarMode *HarMode `json:"recordHarMode"`
+ // Optional setting to control whether to omit request content from the HAR. Defaults to `false`.
+ RecordHarOmitContent *bool `json:"recordHarOmitContent"`
+ // Enables [HAR] recording for all pages into the specified HAR file
+ // on the filesystem. If not specified, the HAR is not recorded. Make sure to call [BrowserContext.Close] for the HAR
+ // to be saved.
+ //
+ // [HAR]: http://www.softwareishard.com/blog/har-12-spec
+ RecordHarPath *string `json:"recordHarPath"`
+ RecordHarURLFilter interface{} `json:"recordHarUrlFilter"`
+ // Enables video recording for all pages into `recordVideo.dir` directory. If not specified videos are not recorded.
+ // Make sure to await [BrowserContext.Close] for videos to be saved.
+ RecordVideo *RecordVideo `json:"recordVideo"`
+ // Emulates `prefers-reduced-motion` media feature, supported values are `reduce`, `no-preference`. See
+ // [Page.EmulateMedia] for more details. Passing `no-override` resets emulation to system defaults. Defaults to
+ // `no-preference`.
+ ReducedMotion *ReducedMotion `json:"reducedMotion"`
+ // Emulates consistent window screen size available inside web page via `window.screen`. Is only used when the
+ // “[object Object]” is set.
+ Screen *Size `json:"screen"`
+ // Whether to allow sites to register Service workers. Defaults to `allow`.
+ // - `allow`: [Service Workers] can be
+ // registered.
+ // - `block`: Playwright will block all registration of Service Workers.
+ //
+ // [Service Workers]: https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API
+ ServiceWorkers *ServiceWorkerPolicy `json:"serviceWorkers"`
+ // Learn more about [storage state and auth].
+ // Populates context with given storage state. This option can be used to initialize context with logged-in
+ // information obtained via [BrowserContext.StorageState].
+ //
+ // [storage state and auth]: https://playwright.dev/docs/auth
+ StorageState *OptionalStorageState `json:"storageState"`
+ // Populates context with given storage state. This option can be used to initialize context with logged-in
+ // information obtained via [BrowserContext.StorageState]. Path to the file with saved storage state.
+ StorageStatePath *string `json:"storageStatePath"`
+ // If set to true, enables strict selectors mode for this context. In the strict selectors mode all operations on
+ // selectors that imply single target DOM element will throw when more than one element matches the selector. This
+ // option does not affect any Locator APIs (Locators are always strict). Defaults to `false`. See [Locator] to learn
+ // more about the strict mode.
+ StrictSelectors *bool `json:"strictSelectors"`
+ // Changes the timezone of the context. See
+ // [ICU's metaZones.txt]
+ // for a list of supported timezone IDs. Defaults to the system timezone.
+ //
+ // [ICU's metaZones.txt]: https://cs.chromium.org/chromium/src/third_party/icu/source/data/misc/metaZones.txt?rcl=faee8bc70570192d82d2978a71e2a615788597d1
+ TimezoneId *string `json:"timezoneId"`
+ // Specific user agent to use in this context.
+ UserAgent *string `json:"userAgent"`
+ // Sets a consistent viewport for each page. Defaults to an 1280x720 viewport. `no_viewport` disables the fixed
+ // viewport. Learn more about [viewport emulation].
+ //
+ // [viewport emulation]: https://playwright.dev/docs/emulation#viewport
+ Viewport *Size `json:"viewport"`
+}
+
+type BrowserStartTracingOptions struct {
+ // specify custom categories to use instead of default.
+ Categories []string `json:"categories"`
+ // Optional, if specified, tracing includes screenshots of the given page.
+ Page Page `json:"page"`
+ // A path to write the trace file to.
+ Path *string `json:"path"`
+ // captures screenshots in the trace.
+ Screenshots *bool `json:"screenshots"`
+}
+
+type OptionalCookie struct {
+ Name string `json:"name"`
+ Value string `json:"value"`
+ // Either url or domain / path are required. Optional.
+ URL *string `json:"url"`
+ // For the cookie to apply to all subdomains as well, prefix domain with a dot, like this: ".example.com". Either url
+ // or domain / path are required. Optional.
+ Domain *string `json:"domain"`
+ // Either url or domain / path are required Optional.
+ Path *string `json:"path"`
+ // Unix time in seconds. Optional.
+ Expires *float64 `json:"expires"`
+ // Optional.
+ HttpOnly *bool `json:"httpOnly"`
+ // Optional.
+ Secure *bool `json:"secure"`
+ // Optional.
+ SameSite *SameSiteAttribute `json:"sameSite"`
+}
+
+type Script struct {
+ // Path to the JavaScript file. If `path` is a relative path, then it is resolved relative to the current working
+ // directory. Optional.
+ Path *string `json:"path"`
+ // Raw script content. Optional.
+ Content *string `json:"content"`
+}
+
+type BrowserContextClearCookiesOptions struct {
+ // Only removes cookies with the given domain.
+ Domain interface{} `json:"domain"`
+ // Only removes cookies with the given name.
+ Name interface{} `json:"name"`
+ // Only removes cookies with the given path.
+ Path interface{} `json:"path"`
+}
+
+type BrowserContextCloseOptions struct {
+ // The reason to be reported to the operations interrupted by the context closure.
+ Reason *string `json:"reason"`
+}
+
+type Cookie struct {
+ Name string `json:"name"`
+ Value string `json:"value"`
+ Domain string `json:"domain"`
+ Path string `json:"path"`
+ // Unix time in seconds.
+ Expires float64 `json:"expires"`
+ HttpOnly bool `json:"httpOnly"`
+ Secure bool `json:"secure"`
+ SameSite *SameSiteAttribute `json:"sameSite"`
+}
+
+type BrowserContextGrantPermissionsOptions struct {
+ // The [origin] to grant permissions to, e.g. "https://example.com".
+ Origin *string `json:"origin"`
+}
+
+type BrowserContextRouteFromHAROptions struct {
+ // - If set to 'abort' any request not found in the HAR file will be aborted.
+ // - If set to 'fallback' falls through to the next route handler in the handler chain.
+ // Defaults to abort.
+ NotFound *HarNotFound `json:"notFound"`
+ // If specified, updates the given HAR with the actual network information instead of serving from file. The file is
+ // written to disk when [BrowserContext.Close] is called.
+ Update *bool `json:"update"`
+ // Optional setting to control resource content management. If `attach` is specified, resources are persisted as
+ // separate files or entries in the ZIP archive. If `embed` is specified, content is stored inline the HAR file.
+ UpdateContent *RouteFromHarUpdateContentPolicy `json:"updateContent"`
+ // When set to `minimal`, only record information necessary for routing from HAR. This omits sizes, timing, page,
+ // cookies, security and other types of HAR information that are not used when replaying from HAR. Defaults to
+ // `minimal`.
+ UpdateMode *HarMode `json:"updateMode"`
+ // A glob pattern, regular expression or predicate to match the request URL. Only requests with URL matching the
+ // pattern will be served from the HAR file. If not specified, all requests are served from the HAR file.
+ URL interface{} `json:"url"`
+}
+
+type Geolocation struct {
+ // Latitude between -90 and 90.
+ Latitude float64 `json:"latitude"`
+ // Longitude between -180 and 180.
+ Longitude float64 `json:"longitude"`
+ // Non-negative accuracy value. Defaults to `0`.
+ Accuracy *float64 `json:"accuracy"`
+}
+
+type BrowserContextUnrouteAllOptions struct {
+ // Specifies whether to wait for already running handlers and what to do if they throw errors:
+ // - `default` - do not wait for current handler calls (if any) to finish, if unrouted handler throws, it may
+ // result in unhandled error
+ // - `wait` - wait for current handler calls (if any) to finish
+ // - `ignoreErrors` - do not wait for current handler calls (if any) to finish, all errors thrown by the handlers
+ // after unrouting are silently caught
+ Behavior *UnrouteBehavior `json:"behavior"`
+}
+
+type BrowserContextExpectConsoleMessageOptions struct {
+ // Receives the [ConsoleMessage] object and resolves to truthy value when the waiting should resolve.
+ Predicate func(ConsoleMessage) bool `json:"predicate"`
+ // Maximum time to wait for in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The
+ // default value can be changed by using the [BrowserContext.SetDefaultTimeout].
+ Timeout *float64 `json:"timeout"`
+}
+
+type BrowserContextExpectEventOptions struct {
+ // Receives the event data and resolves to truthy value when the waiting should resolve.
+ Predicate interface{} `json:"predicate"`
+ // Maximum time to wait for in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The
+ // default value can be changed by using the [BrowserContext.SetDefaultTimeout].
+ Timeout *float64 `json:"timeout"`
+}
+
+type BrowserContextExpectPageOptions struct {
+ // Receives the [Page] object and resolves to truthy value when the waiting should resolve.
+ Predicate func(Page) bool `json:"predicate"`
+ // Maximum time to wait for in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The
+ // default value can be changed by using the [BrowserContext.SetDefaultTimeout].
+ Timeout *float64 `json:"timeout"`
+}
+
+type BrowserContextWaitForEventOptions struct {
+ // Receives the event data and resolves to truthy value when the waiting should resolve.
+ Predicate interface{} `json:"predicate"`
+ // Maximum time to wait for in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The
+ // default value can be changed by using the [BrowserContext.SetDefaultTimeout].
+ Timeout *float64 `json:"timeout"`
+}
+
+type BrowserTypeConnectOptions struct {
+ // This option exposes network available on the connecting client to the browser being connected to. Consists of a
+ // list of rules separated by comma.
+ // Available rules:
+ // 1. Hostname pattern, for example: `example.com`, `*.org:99`, `x.*.y.com`, `*foo.org`.
+ // 2. IP literal, for example: `127.0.0.1`, `0.0.0.0:99`, `[::1]`, `[0:0::1]:99`.
+ // 3. `<loopback>` that matches local loopback interfaces: `localhost`, `*.localhost`, `127.0.0.1`, `[::1]`.
+ // Some common examples:
+ // 4. `"*"` to expose all network.
+ // 5. `"<loopback>"` to expose localhost network.
+ // 6. `"*.test.internal-domain,*.staging.internal-domain,<loopback>"` to expose test/staging deployments and
+ // localhost.
+ ExposeNetwork *string `json:"exposeNetwork"`
+ // Additional HTTP headers to be sent with web socket connect request. Optional.
+ Headers map[string]string `json:"headers"`
+ // Slows down Playwright operations by the specified amount of milliseconds. Useful so that you can see what is going
+ // on. Defaults to 0.
+ SlowMo *float64 `json:"slowMo"`
+ // Maximum time in milliseconds to wait for the connection to be established. Defaults to `0` (no timeout).
+ Timeout *float64 `json:"timeout"`
+}
+
+type BrowserTypeConnectOverCDPOptions struct {
+ // Additional HTTP headers to be sent with connect request. Optional.
+ Headers map[string]string `json:"headers"`
+ // Slows down Playwright operations by the specified amount of milliseconds. Useful so that you can see what is going
+ // on. Defaults to 0.
+ SlowMo *float64 `json:"slowMo"`
+ // Maximum time in milliseconds to wait for the connection to be established. Defaults to `30000` (30 seconds). Pass
+ // `0` to disable timeout.
+ Timeout *float64 `json:"timeout"`
+}
+
+type BrowserTypeLaunchOptions struct {
+ // **NOTE** Use custom browser args at your own risk, as some of them may break Playwright functionality.
+ // Additional arguments to pass to the browser instance. The list of Chromium flags can be found
+ // [here].
+ //
+ // [here]: https://peter.sh/experiments/chromium-command-line-switches/
+ Args []string `json:"args"`
+ // Browser distribution channel.
+ // Use "chromium" to [opt in to new headless mode].
+ // Use "chrome", "chrome-beta", "chrome-dev", "chrome-canary", "msedge", "msedge-beta", "msedge-dev", or
+ // "msedge-canary" to use branded [Google Chrome and Microsoft Edge].
+ //
+ // [opt in to new headless mode]: https://playwright.dev/docs/browsers#chromium-new-headless-mode
+ // [Google Chrome and Microsoft Edge]: https://playwright.dev/docs/browsers#google-chrome--microsoft-edge
+ Channel *string `json:"channel"`
+ // Enable Chromium sandboxing. Defaults to `false`.
+ ChromiumSandbox *bool `json:"chromiumSandbox"`
+ // **Chromium-only** Whether to auto-open a Developer Tools panel for each tab. If this option is `true`, the
+ // “[object Object]” option will be set `false`.
+ //
+ // Deprecated: Use [debugging tools] instead.
+ //
+ // [debugging tools]: https://playwright.dev/docs/debug
+ Devtools *bool `json:"devtools"`
+ // If specified, accepted downloads are downloaded into this directory. Otherwise, temporary directory is created and
+ // is deleted when browser is closed. In either case, the downloads are deleted when the browser context they were
+ // created in is closed.
+ DownloadsPath *string `json:"downloadsPath"`
+ // Specify environment variables that will be visible to the browser. Defaults to `process.env`.
+ Env map[string]string `json:"env"`
+ // Path to a browser executable to run instead of the bundled one. If “[object Object]” is a relative path, then it is
+ // resolved relative to the current working directory. Note that Playwright only works with the bundled Chromium,
+ // Firefox or WebKit, use at your own risk.
+ ExecutablePath *string `json:"executablePath"`
+ // Firefox user preferences. Learn more about the Firefox user preferences at
+ // [`about:config`].
+ //
+ // [`about:config`]: https://support.mozilla.org/en-US/kb/about-config-editor-firefox
+ FirefoxUserPrefs map[string]interface{} `json:"firefoxUserPrefs"`
+ // Close the browser process on SIGHUP. Defaults to `true`.
+ HandleSIGHUP *bool `json:"handleSIGHUP"`
+ // Close the browser process on Ctrl-C. Defaults to `true`.
+ HandleSIGINT *bool `json:"handleSIGINT"`
+ // Close the browser process on SIGTERM. Defaults to `true`.
+ HandleSIGTERM *bool `json:"handleSIGTERM"`
+ // Whether to run browser in headless mode. More details for
+ // [Chromium] and
+ // [Firefox]. Defaults to `true` unless the
+ // “[object Object]” option is `true`.
+ //
+ // [Chromium]: https://developers.google.com/web/updates/2017/04/headless-chrome
+ // [Firefox]: https://hacks.mozilla.org/2017/12/using-headless-mode-in-firefox/
+ Headless *bool `json:"headless"`
+ // If `true`, Playwright does not pass its own configurations args and only uses the ones from “[object Object]”.
+ // Dangerous option; use with care. Defaults to `false`.
+ IgnoreAllDefaultArgs *bool `json:"ignoreAllDefaultArgs"`
+ // If `true`, Playwright does not pass its own configurations args and only uses the ones from “[object Object]”.
+ // Dangerous option; use with care.
+ IgnoreDefaultArgs []string `json:"ignoreDefaultArgs"`
+ // Network proxy settings.
+ Proxy *Proxy `json:"proxy"`
+ // Slows down Playwright operations by the specified amount of milliseconds. Useful so that you can see what is going
+ // on.
+ SlowMo *float64 `json:"slowMo"`
+ // Maximum time in milliseconds to wait for the browser instance to start. Defaults to `30000` (30 seconds). Pass `0`
+ // to disable timeout.
+ Timeout *float64 `json:"timeout"`
+ // If specified, traces are saved into this directory.
+ TracesDir *string `json:"tracesDir"`
+}
+
+type BrowserTypeLaunchPersistentContextOptions struct {
+ // Whether to automatically download all the attachments. Defaults to `true` where all the downloads are accepted.
+ AcceptDownloads *bool `json:"acceptDownloads"`
+ // **NOTE** Use custom browser args at your own risk, as some of them may break Playwright functionality.
+ // Additional arguments to pass to the browser instance. The list of Chromium flags can be found
+ // [here].
+ //
+ // [here]: https://peter.sh/experiments/chromium-command-line-switches/
+ Args []string `json:"args"`
+ // When using [Page.Goto], [Page.Route], [Page.WaitForURL], [Page.ExpectRequest], or [Page.ExpectResponse] it takes
+ // the base URL in consideration by using the [`URL()`]
+ // constructor for building the corresponding URL. Unset by default. Examples:
+ // - baseURL: `http://localhost:3000` and navigating to `/bar.html` results in `http://localhost:3000/bar.html`
+ // - baseURL: `http://localhost:3000/foo/` and navigating to `./bar.html` results in
+ // `http://localhost:3000/foo/bar.html`
+ // - baseURL: `http://localhost:3000/foo` (without trailing slash) and navigating to `./bar.html` results in
+ // `http://localhost:3000/bar.html`
+ //
+ // [`URL()`]: https://developer.mozilla.org/en-US/docs/Web/API/URL/URL
+ BaseURL *string `json:"baseURL"`
+ // Toggles bypassing page's Content-Security-Policy. Defaults to `false`.
+ BypassCSP *bool `json:"bypassCSP"`
+ // Browser distribution channel.
+ // Use "chromium" to [opt in to new headless mode].
+ // Use "chrome", "chrome-beta", "chrome-dev", "chrome-canary", "msedge", "msedge-beta", "msedge-dev", or
+ // "msedge-canary" to use branded [Google Chrome and Microsoft Edge].
+ //
+ // [opt in to new headless mode]: https://playwright.dev/docs/browsers#chromium-new-headless-mode
+ // [Google Chrome and Microsoft Edge]: https://playwright.dev/docs/browsers#google-chrome--microsoft-edge
+ Channel *string `json:"channel"`
+ // Enable Chromium sandboxing. Defaults to `false`.
+ ChromiumSandbox *bool `json:"chromiumSandbox"`
+ // TLS Client Authentication allows the server to request a client certificate and verify it.
+ //
+ // # Details
+ //
+ // An array of client certificates to be used. Each certificate object must have either both `certPath` and `keyPath`,
+ // a single `pfxPath`, or their corresponding direct value equivalents (`cert` and `key`, or `pfx`). Optionally,
+ // `passphrase` property should be provided if the certificate is encrypted. The `origin` property should be provided
+ // with an exact match to the request origin that the certificate is valid for.
+ // **NOTE** When using WebKit on macOS, accessing `localhost` will not pick up client certificates. You can make it
+ // work by replacing `localhost` with `local.playwright`.
+ ClientCertificates []ClientCertificate `json:"clientCertificates"`
+ // Emulates [prefers-colors-scheme]
+ // media feature, supported values are `light` and `dark`. See [Page.EmulateMedia] for more details. Passing
+ // `no-override` resets emulation to system defaults. Defaults to `light`.
+ //
+ // [prefers-colors-scheme]: https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme
+ ColorScheme *ColorScheme `json:"colorScheme"`
+ // Specify device scale factor (can be thought of as dpr). Defaults to `1`. Learn more about
+ // [emulating devices with device scale factor].
+ //
+ // [emulating devices with device scale factor]: https://playwright.dev/docs/emulation#devices
+ DeviceScaleFactor *float64 `json:"deviceScaleFactor"`
+ // **Chromium-only** Whether to auto-open a Developer Tools panel for each tab. If this option is `true`, the
+ // “[object Object]” option will be set `false`.
+ //
+ // Deprecated: Use [debugging tools] instead.
+ //
+ // [debugging tools]: https://playwright.dev/docs/debug
+ Devtools *bool `json:"devtools"`
+ // If specified, accepted downloads are downloaded into this directory. Otherwise, temporary directory is created and
+ // is deleted when browser is closed. In either case, the downloads are deleted when the browser context they were
+ // created in is closed.
+ DownloadsPath *string `json:"downloadsPath"`
+ // Specify environment variables that will be visible to the browser. Defaults to `process.env`.
+ Env map[string]string `json:"env"`
+ // Path to a browser executable to run instead of the bundled one. If “[object Object]” is a relative path, then it is
+ // resolved relative to the current working directory. Note that Playwright only works with the bundled Chromium,
+ // Firefox or WebKit, use at your own risk.
+ ExecutablePath *string `json:"executablePath"`
+ // An object containing additional HTTP headers to be sent with every request. Defaults to none.
+ ExtraHttpHeaders map[string]string `json:"extraHTTPHeaders"`
+ // Firefox user preferences. Learn more about the Firefox user preferences at
+ // [`about:config`].
+ //
+ // [`about:config`]: https://support.mozilla.org/en-US/kb/about-config-editor-firefox
+ FirefoxUserPrefs map[string]interface{} `json:"firefoxUserPrefs"`
+ // Emulates `forced-colors` media feature, supported values are `active`, `none`. See [Page.EmulateMedia] for
+ // more details. Passing `no-override` resets emulation to system defaults. Defaults to `none`.
+ ForcedColors *ForcedColors `json:"forcedColors"`
+ Geolocation *Geolocation `json:"geolocation"`
+ // Close the browser process on SIGHUP. Defaults to `true`.
+ HandleSIGHUP *bool `json:"handleSIGHUP"`
+ // Close the browser process on Ctrl-C. Defaults to `true`.
+ HandleSIGINT *bool `json:"handleSIGINT"`
+ // Close the browser process on SIGTERM. Defaults to `true`.
+ HandleSIGTERM *bool `json:"handleSIGTERM"`
+ // Specifies if viewport supports touch events. Defaults to false. Learn more about
+ // [mobile emulation].
+ //
+ // [mobile emulation]: https://playwright.dev/docs/emulation#devices
+ HasTouch *bool `json:"hasTouch"`
+ // Whether to run browser in headless mode. More details for
+ // [Chromium] and
+ // [Firefox]. Defaults to `true` unless the
+ // “[object Object]” option is `true`.
+ //
+ // [Chromium]: https://developers.google.com/web/updates/2017/04/headless-chrome
+ // [Firefox]: https://hacks.mozilla.org/2017/12/using-headless-mode-in-firefox/
+ Headless *bool `json:"headless"`
+ // Credentials for [HTTP authentication]. If no
+ // origin is specified, the username and password are sent to any servers upon unauthorized responses.
+ //
+ // [HTTP authentication]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication
+ HttpCredentials *HttpCredentials `json:"httpCredentials"`
+ // If `true`, Playwright does not pass its own configurations args and only uses the ones from “[object Object]”.
+ // Dangerous option; use with care. Defaults to `false`.
+ IgnoreAllDefaultArgs *bool `json:"ignoreAllDefaultArgs"`
+ // If `true`, Playwright does not pass its own configurations args and only uses the ones from “[object Object]”.
+ // Dangerous option; use with care.
+ IgnoreDefaultArgs []string `json:"ignoreDefaultArgs"`
+ // Whether to ignore HTTPS errors when sending network requests. Defaults to `false`.
+ IgnoreHttpsErrors *bool `json:"ignoreHTTPSErrors"`
+ // Whether the `meta viewport` tag is taken into account and touch events are enabled. isMobile is a part of device,
+ // so you don't actually need to set it manually. Defaults to `false` and is not supported in Firefox. Learn more
+ // about [mobile emulation].
+ //
+ // [mobile emulation]: https://playwright.dev/docs/emulation#ismobile
+ IsMobile *bool `json:"isMobile"`
+ // Whether or not to enable JavaScript in the context. Defaults to `true`. Learn more about
+ // [disabling JavaScript].
+ //
+ // [disabling JavaScript]: https://playwright.dev/docs/emulation#javascript-enabled
+ JavaScriptEnabled *bool `json:"javaScriptEnabled"`
+ // Specify user locale, for example `en-GB`, `de-DE`, etc. Locale will affect `navigator.language` value,
+ // `Accept-Language` request header value as well as number and date formatting rules. Defaults to the system default
+ // locale. Learn more about emulation in our [emulation guide].
+ //
+ // [emulation guide]: https://playwright.dev/docs/emulation#locale--timezone
+ Locale *string `json:"locale"`
+ // Does not enforce fixed viewport, allows resizing window in the headed mode.
+ NoViewport *bool `json:"noViewport"`
+ // Whether to emulate network being offline. Defaults to `false`. Learn more about
+ // [network emulation].
+ //
+ // [network emulation]: https://playwright.dev/docs/emulation#offline
+ Offline *bool `json:"offline"`
+ // A list of permissions to grant to all pages in this context. See [BrowserContext.GrantPermissions] for more
+ // details. Defaults to none.
+ Permissions []string `json:"permissions"`
+ // Network proxy settings.
+ Proxy *Proxy `json:"proxy"`
+ // Optional setting to control resource content management. If `omit` is specified, content is not persisted. If
+ // `attach` is specified, resources are persisted as separate files and all of these files are archived along with the
+ // HAR file. Defaults to `embed`, which stores content inline the HAR file as per HAR specification.
+ RecordHarContent *HarContentPolicy `json:"recordHarContent"`
+ // When set to `minimal`, only record information necessary for routing from HAR. This omits sizes, timing, page,
+ // cookies, security and other types of HAR information that are not used when replaying from HAR. Defaults to `full`.
+ RecordHarMode *HarMode `json:"recordHarMode"`
+ // Optional setting to control whether to omit request content from the HAR. Defaults to `false`.
+ RecordHarOmitContent *bool `json:"recordHarOmitContent"`
+ // Enables [HAR] recording for all pages into the specified HAR file
+ // on the filesystem. If not specified, the HAR is not recorded. Make sure to call [BrowserContext.Close] for the HAR
+ // to be saved.
+ //
+ // [HAR]: http://www.softwareishard.com/blog/har-12-spec
+ RecordHarPath *string `json:"recordHarPath"`
+ RecordHarURLFilter interface{} `json:"recordHarUrlFilter"`
+ // Enables video recording for all pages into `recordVideo.dir` directory. If not specified videos are not recorded.
+ // Make sure to await [BrowserContext.Close] for videos to be saved.
+ RecordVideo *RecordVideo `json:"recordVideo"`
+ // Emulates `prefers-reduced-motion` media feature, supported values are `reduce`, `no-preference`. See
+ // [Page.EmulateMedia] for more details. Passing `no-override` resets emulation to system defaults. Defaults to
+ // `no-preference`.
+ ReducedMotion *ReducedMotion `json:"reducedMotion"`
+ // Emulates consistent window screen size available inside web page via `window.screen`. Is only used when the
+ // “[object Object]” is set.
+ Screen *Size `json:"screen"`
+ // Whether to allow sites to register Service workers. Defaults to `allow`.
+ // - `allow`: [Service Workers] can be
+ // registered.
+ // - `block`: Playwright will block all registration of Service Workers.
+ //
+ // [Service Workers]: https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API
+ ServiceWorkers *ServiceWorkerPolicy `json:"serviceWorkers"`
+ // Slows down Playwright operations by the specified amount of milliseconds. Useful so that you can see what is going
+ // on.
+ SlowMo *float64 `json:"slowMo"`
+ // If set to true, enables strict selectors mode for this context. In the strict selectors mode all operations on
+ // selectors that imply single target DOM element will throw when more than one element matches the selector. This
+ // option does not affect any Locator APIs (Locators are always strict). Defaults to `false`. See [Locator] to learn
+ // more about the strict mode.
+ StrictSelectors *bool `json:"strictSelectors"`
+ // Maximum time in milliseconds to wait for the browser instance to start. Defaults to `30000` (30 seconds). Pass `0`
+ // to disable timeout.
+ Timeout *float64 `json:"timeout"`
+ // Changes the timezone of the context. See
+ // [ICU's metaZones.txt]
+ // for a list of supported timezone IDs. Defaults to the system timezone.
+ //
+ // [ICU's metaZones.txt]: https://cs.chromium.org/chromium/src/third_party/icu/source/data/misc/metaZones.txt?rcl=faee8bc70570192d82d2978a71e2a615788597d1
+ TimezoneId *string `json:"timezoneId"`
+ // If specified, traces are saved into this directory.
+ TracesDir *string `json:"tracesDir"`
+ // Specific user agent to use in this context.
+ UserAgent *string `json:"userAgent"`
+ // Sets a consistent viewport for each page. Defaults to an 1280x720 viewport. `no_viewport` disables the fixed
+ // viewport. Learn more about [viewport emulation].
+ //
+ // [viewport emulation]: https://playwright.dev/docs/emulation#viewport
+ Viewport *Size `json:"viewport"`
+}
+
+type ClockInstallOptions struct {
+ // Time to initialize with, current system time by default.
+ Time interface{} `json:"time"`
+}
+
+type ConsoleMessageLocation struct {
+ // URL of the resource.
+ URL string `json:"url"`
+ // 0-based line number in the resource.
+ LineNumber int `json:"lineNumber"`
+ // 0-based column number in the resource.
+ ColumnNumber int `json:"columnNumber"`
+}
+
+type Rect struct {
+ // the x coordinate of the element in pixels.
+ X float64 `json:"x"`
+ // the y coordinate of the element in pixels.
+ Y float64 `json:"y"`
+ // the width of the element in pixels.
+ Width float64 `json:"width"`
+ // the height of the element in pixels.
+ Height float64 `json:"height"`
+}
+
+type ElementHandleCheckOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type ElementHandleClickOptions struct {
+ // Defaults to `left`.
+ Button *MouseButton `json:"button"`
+ // defaults to 1. See [UIEvent.Detail].
+ ClickCount *int `json:"clickCount"`
+ // Time to wait between `mousedown` and `mouseup` in milliseconds. Defaults to 0.
+ Delay *float64 `json:"delay"`
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // Modifier keys to press. Ensures that only these modifiers are pressed during the operation, and then restores
+ // current modifiers back. If not specified, currently pressed modifiers are used. "ControlOrMeta" resolves to
+ // "Control" on Windows and Linux and to "Meta" on macOS.
+ Modifiers []KeyboardModifier `json:"modifiers"`
+ // Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You
+ // can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as
+ // navigating to inaccessible pages. Defaults to `false`.
+ //
+ // Deprecated: This option will default to `true` in the future.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type ElementHandleDblclickOptions struct {
+ // Defaults to `left`.
+ Button *MouseButton `json:"button"`
+ // Time to wait between `mousedown` and `mouseup` in milliseconds. Defaults to 0.
+ Delay *float64 `json:"delay"`
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // Modifier keys to press. Ensures that only these modifiers are pressed during the operation, and then restores
+ // current modifiers back. If not specified, currently pressed modifiers are used. "ControlOrMeta" resolves to
+ // "Control" on Windows and Linux and to "Meta" on macOS.
+ Modifiers []KeyboardModifier `json:"modifiers"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type ElementHandleFillOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type ElementHandleHoverOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // Modifier keys to press. Ensures that only these modifiers are pressed during the operation, and then restores
+ // current modifiers back. If not specified, currently pressed modifiers are used. "ControlOrMeta" resolves to
+ // "Control" on Windows and Linux and to "Meta" on macOS.
+ Modifiers []KeyboardModifier `json:"modifiers"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type ElementHandleInputValueOptions struct {
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type ElementHandlePressOptions struct {
+ // Time to wait between `keydown` and `keyup` in milliseconds. Defaults to 0.
+ Delay *float64 `json:"delay"`
+ // Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You
+ // can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as
+ // navigating to inaccessible pages. Defaults to `false`.
+ //
+ // Deprecated: This option will default to `true` in the future.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type ElementHandleScreenshotOptions struct {
+ // When set to `"disabled"`, stops CSS animations, CSS transitions and Web Animations. Animations get different
+ // treatment depending on their duration:
+ // - finite animations are fast-forwarded to completion, so they'll fire `transitionend` event.
+ // - infinite animations are canceled to initial state, and then played over after the screenshot.
+ // Defaults to `"allow"` that leaves animations untouched.
+ Animations *ScreenshotAnimations `json:"animations"`
+ // When set to `"hide"`, screenshot will hide text caret. When set to `"initial"`, text caret behavior will not be
+ // changed. Defaults to `"hide"`.
+ Caret *ScreenshotCaret `json:"caret"`
+ // Specify locators that should be masked when the screenshot is taken. Masked elements will be overlaid with a pink
+ // box `#FF00FF` (customized by “[object Object]”) that completely covers its bounding box. The mask is also applied
+ // to invisible elements, see [Matching only visible elements] to
+ // disable that.
+ //
+ // [Matching only visible elements]: https://playwright.dev/docs/locators#matching-only-visible-elements
+ Mask []Locator `json:"mask"`
+ // Specify the color of the overlay box for masked elements, in
+ // [CSS color format]. Default color is pink `#FF00FF`.
+ //
+ // [CSS color format]: https://developer.mozilla.org/en-US/docs/Web/CSS/color_value
+ MaskColor *string `json:"maskColor"`
+ // Hides default white background and allows capturing screenshots with transparency. Not applicable to `jpeg` images.
+ // Defaults to `false`.
+ OmitBackground *bool `json:"omitBackground"`
+ // The file path to save the image to. The screenshot type will be inferred from file extension. If “[object Object]”
+ // is a relative path, then it is resolved relative to the current working directory. If no path is provided, the
+ // image won't be saved to the disk.
+ Path *string `json:"path"`
+ // The quality of the image, between 0-100. Not applicable to `png` images.
+ Quality *int `json:"quality"`
+ // When set to `"css"`, screenshot will have a single pixel per each css pixel on the page. For high-dpi devices, this
+ // will keep screenshots small. Using `"device"` option will produce a single pixel per each device pixel, so
+ // screenshots of high-dpi devices will be twice as large or even larger.
+ // Defaults to `"device"`.
+ Scale *ScreenshotScale `json:"scale"`
+ // Text of the stylesheet to apply while making the screenshot. This is where you can hide dynamic elements, make
+ // elements invisible or change their properties to help you creating repeatable screenshots. This stylesheet pierces
+ // the Shadow DOM and applies to the inner frames.
+ Style *string `json:"style"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // Specify screenshot type, defaults to `png`.
+ Type *ScreenshotType `json:"type"`
+}
+
+type ElementHandleScrollIntoViewIfNeededOptions struct {
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type ElementHandleSelectOptionOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type ElementHandleSelectTextOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type ElementHandleSetCheckedOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type ElementHandleSetInputFilesOptions struct {
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type ElementHandleTapOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // Modifier keys to press. Ensures that only these modifiers are pressed during the operation, and then restores
+ // current modifiers back. If not specified, currently pressed modifiers are used. "ControlOrMeta" resolves to
+ // "Control" on Windows and Linux and to "Meta" on macOS.
+ Modifiers []KeyboardModifier `json:"modifiers"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type ElementHandleTypeOptions struct {
+ // Time to wait between key presses in milliseconds. Defaults to 0.
+ Delay *float64 `json:"delay"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type ElementHandleUncheckOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type ElementHandleWaitForElementStateOptions struct {
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type ElementHandleWaitForSelectorOptions struct {
+ // Defaults to `visible`. Can be either:
+ // - `attached` - wait for element to be present in DOM.
+ // - `detached` - wait for element to not be present in DOM.
+ // - `visible` - wait for element to have non-empty bounding box and no `visibility:hidden`. Note that element
+ // without any content or with `display:none` has an empty bounding box and is not considered visible.
+ // - `hidden` - wait for element to be either detached from DOM, or have an empty bounding box or
+ // `visibility:hidden`. This is opposite to the `visible` option.
+ State *WaitForSelectorState `json:"state"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type FileChooserSetFilesOptions struct {
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type FrameAddScriptTagOptions struct {
+ // Raw JavaScript content to be injected into frame.
+ Content *string `json:"content"`
+ // Path to the JavaScript file to be injected into frame. If `path` is a relative path, then it is resolved relative
+ // to the current working directory.
+ Path *string `json:"path"`
+ // Script type. Use 'module' in order to load a JavaScript ES6 module. See
+ // [script] for more details.
+ //
+ // [script]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script
+ Type *string `json:"type"`
+ // URL of a script to be added.
+ URL *string `json:"url"`
+}
+
+type FrameAddStyleTagOptions struct {
+ // Raw CSS content to be injected into frame.
+ Content *string `json:"content"`
+ // Path to the CSS file to be injected into frame. If `path` is a relative path, then it is resolved relative to the
+ // current working directory.
+ Path *string `json:"path"`
+ // URL of the `<link>` tag.
+ URL *string `json:"url"`
+}
+
+type FrameCheckOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type FrameClickOptions struct {
+ // Defaults to `left`.
+ Button *MouseButton `json:"button"`
+ // defaults to 1. See [UIEvent.Detail].
+ ClickCount *int `json:"clickCount"`
+ // Time to wait between `mousedown` and `mouseup` in milliseconds. Defaults to 0.
+ Delay *float64 `json:"delay"`
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // Modifier keys to press. Ensures that only these modifiers are pressed during the operation, and then restores
+ // current modifiers back. If not specified, currently pressed modifiers are used. "ControlOrMeta" resolves to
+ // "Control" on Windows and Linux and to "Meta" on macOS.
+ Modifiers []KeyboardModifier `json:"modifiers"`
+ // Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You
+ // can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as
+ // navigating to inaccessible pages. Defaults to `false`.
+ //
+ // Deprecated: This option will default to `true` in the future.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it. Note that keyboard
+ // `modifiers` will be pressed regardless of `trial` to allow testing elements which are only visible when those keys
+ // are pressed.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type FrameDblclickOptions struct {
+ // Defaults to `left`.
+ Button *MouseButton `json:"button"`
+ // Time to wait between `mousedown` and `mouseup` in milliseconds. Defaults to 0.
+ Delay *float64 `json:"delay"`
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // Modifier keys to press. Ensures that only these modifiers are pressed during the operation, and then restores
+ // current modifiers back. If not specified, currently pressed modifiers are used. "ControlOrMeta" resolves to
+ // "Control" on Windows and Linux and to "Meta" on macOS.
+ Modifiers []KeyboardModifier `json:"modifiers"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it. Note that keyboard
+ // `modifiers` will be pressed regardless of `trial` to allow testing elements which are only visible when those keys
+ // are pressed.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type FrameDispatchEventOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type FrameDragAndDropOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // Clicks on the source element at this point relative to the top-left corner of the element's padding box. If not
+ // specified, some visible point of the element is used.
+ SourcePosition *Position `json:"sourcePosition"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Drops on the target element at this point relative to the top-left corner of the element's padding box. If not
+ // specified, some visible point of the element is used.
+ TargetPosition *Position `json:"targetPosition"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type FrameEvalOnSelectorOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+}
+
+type FrameFillOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type FrameFocusOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type FrameGetAttributeOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type FrameGetByAltTextOptions struct {
+ // Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a
+ // regular expression. Note that exact match still trims whitespace.
+ Exact *bool `json:"exact"`
+}
+
+type FrameGetByLabelOptions struct {
+ // Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a
+ // regular expression. Note that exact match still trims whitespace.
+ Exact *bool `json:"exact"`
+}
+
+type FrameGetByPlaceholderOptions struct {
+ // Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a
+ // regular expression. Note that exact match still trims whitespace.
+ Exact *bool `json:"exact"`
+}
+
+type FrameGetByRoleOptions struct {
+ // An attribute that is usually set by `aria-checked` or native `<input type=checkbox>` controls.
+ // Learn more about [`aria-checked`].
+ //
+ // [`aria-checked`]: https://www.w3.org/TR/wai-aria-1.2/#aria-checked
+ Checked *bool `json:"checked"`
+ // An attribute that is usually set by `aria-disabled` or `disabled`.
+ // **NOTE** Unlike most other attributes, `disabled` is inherited through the DOM hierarchy. Learn more about
+ // [`aria-disabled`].
+ //
+ // [`aria-disabled`]: https://www.w3.org/TR/wai-aria-1.2/#aria-disabled
+ Disabled *bool `json:"disabled"`
+ // Whether “[object Object]” is matched exactly: case-sensitive and whole-string. Defaults to false. Ignored when
+ // “[object Object]” is a regular expression. Note that exact match still trims whitespace.
+ Exact *bool `json:"exact"`
+ // An attribute that is usually set by `aria-expanded`.
+ // Learn more about [`aria-expanded`].
+ //
+ // [`aria-expanded`]: https://www.w3.org/TR/wai-aria-1.2/#aria-expanded
+ Expanded *bool `json:"expanded"`
+ // Option that controls whether hidden elements are matched. By default, only non-hidden elements, as
+ // [defined by ARIA], are matched by role selector.
+ // Learn more about [`aria-hidden`].
+ //
+ // [defined by ARIA]: https://www.w3.org/TR/wai-aria-1.2/#tree_exclusion
+ // [`aria-hidden`]: https://www.w3.org/TR/wai-aria-1.2/#aria-hidden
+ IncludeHidden *bool `json:"includeHidden"`
+ // A number attribute that is usually present for roles `heading`, `listitem`, `row`, `treeitem`, with default values
+ // for `<h1>-<h6>` elements.
+ // Learn more about [`aria-level`].
+ //
+ // [`aria-level`]: https://www.w3.org/TR/wai-aria-1.2/#aria-level
+ Level *int `json:"level"`
+ // Option to match the [accessible name]. By default, matching is
+ // case-insensitive and searches for a substring, use “[object Object]” to control this behavior.
+ // Learn more about [accessible name].
+ //
+ // [accessible name]: https://w3c.github.io/accname/#dfn-accessible-name
+ // [accessible name]: https://w3c.github.io/accname/#dfn-accessible-name
+ Name interface{} `json:"name"`
+ // An attribute that is usually set by `aria-pressed`.
+ // Learn more about [`aria-pressed`].
+ //
+ // [`aria-pressed`]: https://www.w3.org/TR/wai-aria-1.2/#aria-pressed
+ Pressed *bool `json:"pressed"`
+ // An attribute that is usually set by `aria-selected`.
+ // Learn more about [`aria-selected`].
+ //
+ // [`aria-selected`]: https://www.w3.org/TR/wai-aria-1.2/#aria-selected
+ Selected *bool `json:"selected"`
+}
+
+type FrameGetByTextOptions struct {
+ // Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a
+ // regular expression. Note that exact match still trims whitespace.
+ Exact *bool `json:"exact"`
+}
+
+type FrameGetByTitleOptions struct {
+ // Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a
+ // regular expression. Note that exact match still trims whitespace.
+ Exact *bool `json:"exact"`
+}
+
+type FrameGotoOptions struct {
+ // Referer header value. If provided it will take preference over the referer header value set by
+ // [Page.SetExtraHTTPHeaders].
+ Referer *string `json:"referer"`
+ // Maximum operation time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultNavigationTimeout], [BrowserContext.SetDefaultTimeout],
+ // [Page.SetDefaultNavigationTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When to consider operation succeeded, defaults to `load`. Events can be either:
+ // - `domcontentloaded` - consider operation to be finished when the `DOMContentLoaded` event is fired.
+ // - `load` - consider operation to be finished when the `load` event is fired.
+ // - `networkidle` - **DISCOURAGED** consider operation to be finished when there are no network connections for
+ // at least `500` ms. Don't use this method for testing, rely on web assertions to assess readiness instead.
+ // - `commit` - consider operation to be finished when network response is received and the document started
+ // loading.
+ WaitUntil *WaitUntilState `json:"waitUntil"`
+}
+
+type FrameHoverOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // Modifier keys to press. Ensures that only these modifiers are pressed during the operation, and then restores
+ // current modifiers back. If not specified, currently pressed modifiers are used. "ControlOrMeta" resolves to
+ // "Control" on Windows and Linux and to "Meta" on macOS.
+ Modifiers []KeyboardModifier `json:"modifiers"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it. Note that keyboard
+ // `modifiers` will be pressed regardless of `trial` to allow testing elements which are only visible when those keys
+ // are pressed.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type FrameInnerHTMLOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type FrameInnerTextOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type FrameInputValueOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type FrameIsCheckedOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type FrameIsDisabledOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type FrameIsEditableOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type FrameIsEnabledOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type FrameIsHiddenOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ //
+ // Deprecated: This option is ignored. [Frame.IsHidden] does not wait for the element to become hidden and returns immediately.
+ Timeout *float64 `json:"timeout"`
+}
+
+type FrameIsVisibleOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ //
+ // Deprecated: This option is ignored. [Frame.IsVisible] does not wait for the element to become visible and returns immediately.
+ Timeout *float64 `json:"timeout"`
+}
+
+type FrameLocatorOptions struct {
+ // Narrows down the results of the method to those which contain elements matching this relative locator. For example,
+ // `article` that has `text=Playwright` matches `<article><div>Playwright</div></article>`.
+ // Inner locator **must be relative** to the outer locator and is queried starting with the outer locator match, not
+ // the document root. For example, you can find `content` that has `div` in
+ // `<article><content><div>Playwright</div></content></article>`. However, looking for `content` that has `article
+ // div` will fail, because the inner locator must be relative and should not use any elements outside the `content`.
+ // Note that outer and inner locators must belong to the same frame. Inner locator must not contain [FrameLocator]s.
+ Has Locator `json:"has"`
+ // Matches elements that do not contain an element that matches an inner locator. Inner locator is queried against the
+ // outer one. For example, `article` that does not have `div` matches `<article><span>Playwright</span></article>`.
+ // Note that outer and inner locators must belong to the same frame. Inner locator must not contain [FrameLocator]s.
+ HasNot Locator `json:"hasNot"`
+ // Matches elements that do not contain specified text somewhere inside, possibly in a child or a descendant element.
+ // When passed a [string], matching is case-insensitive and searches for a substring.
+ HasNotText interface{} `json:"hasNotText"`
+ // Matches elements containing specified text somewhere inside, possibly in a child or a descendant element. When
+ // passed a [string], matching is case-insensitive and searches for a substring. For example, `"Playwright"` matches
+ // `<article><div>Playwright</div></article>`.
+ HasText interface{} `json:"hasText"`
+}
+
+type FramePressOptions struct {
+ // Time to wait between `keydown` and `keyup` in milliseconds. Defaults to 0.
+ Delay *float64 `json:"delay"`
+ // Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You
+ // can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as
+ // navigating to inaccessible pages. Defaults to `false`.
+ //
+ // Deprecated: This option will default to `true` in the future.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type FrameQuerySelectorOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+}
+
+type FrameSelectOptionOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type FrameSetCheckedOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type FrameSetContentOptions struct {
+ // Maximum operation time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultNavigationTimeout], [BrowserContext.SetDefaultTimeout],
+ // [Page.SetDefaultNavigationTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When to consider operation succeeded, defaults to `load`. Events can be either:
+ // - `domcontentloaded` - consider operation to be finished when the `DOMContentLoaded` event is fired.
+ // - `load` - consider operation to be finished when the `load` event is fired.
+ // - `networkidle` - **DISCOURAGED** consider operation to be finished when there are no network connections for
+ // at least `500` ms. Don't use this method for testing, rely on web assertions to assess readiness instead.
+ // - `commit` - consider operation to be finished when network response is received and the document started
+ // loading.
+ WaitUntil *WaitUntilState `json:"waitUntil"`
+}
+
+type FrameSetInputFilesOptions struct {
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type FrameTapOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // Modifier keys to press. Ensures that only these modifiers are pressed during the operation, and then restores
+ // current modifiers back. If not specified, currently pressed modifiers are used. "ControlOrMeta" resolves to
+ // "Control" on Windows and Linux and to "Meta" on macOS.
+ Modifiers []KeyboardModifier `json:"modifiers"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it. Note that keyboard
+ // `modifiers` will be pressed regardless of `trial` to allow testing elements which are only visible when those keys
+ // are pressed.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type FrameTextContentOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type FrameTypeOptions struct {
+ // Time to wait between key presses in milliseconds. Defaults to 0.
+ Delay *float64 `json:"delay"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type FrameUncheckOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type FrameWaitForFunctionOptions struct {
+ // If “[object Object]” is `raf`, then “[object Object]” is constantly executed in `requestAnimationFrame` callback.
+ // If “[object Object]” is a number, then it is treated as an interval in milliseconds at which the function would be
+ // executed. Defaults to `raf`.
+ Polling interface{} `json:"polling"`
+ // Maximum time to wait for in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The
+ // default value can be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type FrameWaitForLoadStateOptions struct {
+ // Optional load state to wait for, defaults to `load`. If the state has been already reached while loading current
+ // document, the method resolves immediately. Can be one of:
+ // - `load` - wait for the `load` event to be fired.
+ // - `domcontentloaded` - wait for the `DOMContentLoaded` event to be fired.
+ // - `networkidle` - **DISCOURAGED** wait until there are no network connections for at least `500` ms. Don't use
+ // this method for testing, rely on web assertions to assess readiness instead.
+ State *LoadState `json:"state"`
+ // Maximum operation time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultNavigationTimeout], [BrowserContext.SetDefaultTimeout],
+ // [Page.SetDefaultNavigationTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type FrameExpectNavigationOptions struct {
+ // Maximum operation time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultNavigationTimeout], [BrowserContext.SetDefaultTimeout],
+ // [Page.SetDefaultNavigationTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation. Note that if
+ // the parameter is a string without wildcard characters, the method will wait for navigation to URL that is exactly
+ // equal to the string.
+ URL interface{} `json:"url"`
+ // When to consider operation succeeded, defaults to `load`. Events can be either:
+ // - `domcontentloaded` - consider operation to be finished when the `DOMContentLoaded` event is fired.
+ // - `load` - consider operation to be finished when the `load` event is fired.
+ // - `networkidle` - **DISCOURAGED** consider operation to be finished when there are no network connections for
+ // at least `500` ms. Don't use this method for testing, rely on web assertions to assess readiness instead.
+ // - `commit` - consider operation to be finished when network response is received and the document started
+ // loading.
+ WaitUntil *WaitUntilState `json:"waitUntil"`
+}
+
+type FrameWaitForSelectorOptions struct {
+ // Defaults to `visible`. Can be either:
+ // - `attached` - wait for element to be present in DOM.
+ // - `detached` - wait for element to not be present in DOM.
+ // - `visible` - wait for element to have non-empty bounding box and no `visibility:hidden`. Note that element
+ // without any content or with `display:none` has an empty bounding box and is not considered visible.
+ // - `hidden` - wait for element to be either detached from DOM, or have an empty bounding box or
+ // `visibility:hidden`. This is opposite to the `visible` option.
+ State *WaitForSelectorState `json:"state"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type FrameWaitForURLOptions struct {
+ // Maximum operation time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultNavigationTimeout], [BrowserContext.SetDefaultTimeout],
+ // [Page.SetDefaultNavigationTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When to consider operation succeeded, defaults to `load`. Events can be either:
+ // - `domcontentloaded` - consider operation to be finished when the `DOMContentLoaded` event is fired.
+ // - `load` - consider operation to be finished when the `load` event is fired.
+ // - `networkidle` - **DISCOURAGED** consider operation to be finished when there are no network connections for
+ // at least `500` ms. Don't use this method for testing, rely on web assertions to assess readiness instead.
+ // - `commit` - consider operation to be finished when network response is received and the document started
+ // loading.
+ WaitUntil *WaitUntilState `json:"waitUntil"`
+}
+
+type FrameLocatorGetByAltTextOptions struct {
+ // Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a
+ // regular expression. Note that exact match still trims whitespace.
+ Exact *bool `json:"exact"`
+}
+
+type FrameLocatorGetByLabelOptions struct {
+ // Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a
+ // regular expression. Note that exact match still trims whitespace.
+ Exact *bool `json:"exact"`
+}
+
+type FrameLocatorGetByPlaceholderOptions struct {
+ // Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a
+ // regular expression. Note that exact match still trims whitespace.
+ Exact *bool `json:"exact"`
+}
+
+type FrameLocatorGetByRoleOptions struct {
+ // An attribute that is usually set by `aria-checked` or native `<input type=checkbox>` controls.
+ // Learn more about [`aria-checked`].
+ //
+ // [`aria-checked`]: https://www.w3.org/TR/wai-aria-1.2/#aria-checked
+ Checked *bool `json:"checked"`
+ // An attribute that is usually set by `aria-disabled` or `disabled`.
+ // **NOTE** Unlike most other attributes, `disabled` is inherited through the DOM hierarchy. Learn more about
+ // [`aria-disabled`].
+ //
+ // [`aria-disabled`]: https://www.w3.org/TR/wai-aria-1.2/#aria-disabled
+ Disabled *bool `json:"disabled"`
+ // Whether “[object Object]” is matched exactly: case-sensitive and whole-string. Defaults to false. Ignored when
+ // “[object Object]” is a regular expression. Note that exact match still trims whitespace.
+ Exact *bool `json:"exact"`
+ // An attribute that is usually set by `aria-expanded`.
+ // Learn more about [`aria-expanded`].
+ //
+ // [`aria-expanded`]: https://www.w3.org/TR/wai-aria-1.2/#aria-expanded
+ Expanded *bool `json:"expanded"`
+ // Option that controls whether hidden elements are matched. By default, only non-hidden elements, as
+ // [defined by ARIA], are matched by role selector.
+ // Learn more about [`aria-hidden`].
+ //
+ // [defined by ARIA]: https://www.w3.org/TR/wai-aria-1.2/#tree_exclusion
+ // [`aria-hidden`]: https://www.w3.org/TR/wai-aria-1.2/#aria-hidden
+ IncludeHidden *bool `json:"includeHidden"`
+ // A number attribute that is usually present for roles `heading`, `listitem`, `row`, `treeitem`, with default values
+ // for `<h1>-<h6>` elements.
+ // Learn more about [`aria-level`].
+ //
+ // [`aria-level`]: https://www.w3.org/TR/wai-aria-1.2/#aria-level
+ Level *int `json:"level"`
+ // Option to match the [accessible name]. By default, matching is
+ // case-insensitive and searches for a substring, use “[object Object]” to control this behavior.
+ // Learn more about [accessible name].
+ //
+ // [accessible name]: https://w3c.github.io/accname/#dfn-accessible-name
+ // [accessible name]: https://w3c.github.io/accname/#dfn-accessible-name
+ Name interface{} `json:"name"`
+ // An attribute that is usually set by `aria-pressed`.
+ // Learn more about [`aria-pressed`].
+ //
+ // [`aria-pressed`]: https://www.w3.org/TR/wai-aria-1.2/#aria-pressed
+ Pressed *bool `json:"pressed"`
+ // An attribute that is usually set by `aria-selected`.
+ // Learn more about [`aria-selected`].
+ //
+ // [`aria-selected`]: https://www.w3.org/TR/wai-aria-1.2/#aria-selected
+ Selected *bool `json:"selected"`
+}
+
+type FrameLocatorGetByTextOptions struct {
+ // Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a
+ // regular expression. Note that exact match still trims whitespace.
+ Exact *bool `json:"exact"`
+}
+
+type FrameLocatorGetByTitleOptions struct {
+ // Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a
+ // regular expression. Note that exact match still trims whitespace.
+ Exact *bool `json:"exact"`
+}
+
+type FrameLocatorLocatorOptions struct {
+ // Narrows down the results of the method to those which contain elements matching this relative locator. For example,
+ // `article` that has `text=Playwright` matches `<article><div>Playwright</div></article>`.
+ // Inner locator **must be relative** to the outer locator and is queried starting with the outer locator match, not
+ // the document root. For example, you can find `content` that has `div` in
+ // `<article><content><div>Playwright</div></content></article>`. However, looking for `content` that has `article
+ // div` will fail, because the inner locator must be relative and should not use any elements outside the `content`.
+ // Note that outer and inner locators must belong to the same frame. Inner locator must not contain [FrameLocator]s.
+ Has Locator `json:"has"`
+ // Matches elements that do not contain an element that matches an inner locator. Inner locator is queried against the
+ // outer one. For example, `article` that does not have `div` matches `<article><span>Playwright</span></article>`.
+ // Note that outer and inner locators must belong to the same frame. Inner locator must not contain [FrameLocator]s.
+ HasNot Locator `json:"hasNot"`
+ // Matches elements that do not contain specified text somewhere inside, possibly in a child or a descendant element.
+ // When passed a [string], matching is case-insensitive and searches for a substring.
+ HasNotText interface{} `json:"hasNotText"`
+ // Matches elements containing specified text somewhere inside, possibly in a child or a descendant element. When
+ // passed a [string], matching is case-insensitive and searches for a substring. For example, `"Playwright"` matches
+ // `<article><div>Playwright</div></article>`.
+ HasText interface{} `json:"hasText"`
+}
+
+type KeyboardPressOptions struct {
+ // Time to wait between `keydown` and `keyup` in milliseconds. Defaults to 0.
+ Delay *float64 `json:"delay"`
+}
+
+type KeyboardTypeOptions struct {
+ // Time to wait between key presses in milliseconds. Defaults to 0.
+ Delay *float64 `json:"delay"`
+}
+
+type LocatorAriaSnapshotOptions struct {
+ // Generate symbolic reference for each element. One can use `aria-ref=<ref>` locator immediately after capturing the
+ // snapshot to perform actions on the element.
+ Ref *bool `json:"ref"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorBlurOptions struct {
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorBoundingBoxOptions struct {
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorCheckOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type LocatorClearOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorClickOptions struct {
+ // Defaults to `left`.
+ Button *MouseButton `json:"button"`
+ // defaults to 1. See [UIEvent.Detail].
+ ClickCount *int `json:"clickCount"`
+ // Time to wait between `mousedown` and `mouseup` in milliseconds. Defaults to 0.
+ Delay *float64 `json:"delay"`
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // Modifier keys to press. Ensures that only these modifiers are pressed during the operation, and then restores
+ // current modifiers back. If not specified, currently pressed modifiers are used. "ControlOrMeta" resolves to
+ // "Control" on Windows and Linux and to "Meta" on macOS.
+ Modifiers []KeyboardModifier `json:"modifiers"`
+ // Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You
+ // can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as
+ // navigating to inaccessible pages. Defaults to `false`.
+ //
+ // Deprecated: This option will default to `true` in the future.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it. Note that keyboard
+ // `modifiers` will be pressed regardless of `trial` to allow testing elements which are only visible when those keys
+ // are pressed.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type LocatorDblclickOptions struct {
+ // Defaults to `left`.
+ Button *MouseButton `json:"button"`
+ // Time to wait between `mousedown` and `mouseup` in milliseconds. Defaults to 0.
+ Delay *float64 `json:"delay"`
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // Modifier keys to press. Ensures that only these modifiers are pressed during the operation, and then restores
+ // current modifiers back. If not specified, currently pressed modifiers are used. "ControlOrMeta" resolves to
+ // "Control" on Windows and Linux and to "Meta" on macOS.
+ Modifiers []KeyboardModifier `json:"modifiers"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it. Note that keyboard
+ // `modifiers` will be pressed regardless of `trial` to allow testing elements which are only visible when those keys
+ // are pressed.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type LocatorDispatchEventOptions struct {
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorDragToOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // Clicks on the source element at this point relative to the top-left corner of the element's padding box. If not
+ // specified, some visible point of the element is used.
+ SourcePosition *Position `json:"sourcePosition"`
+ // Drops on the target element at this point relative to the top-left corner of the element's padding box. If not
+ // specified, some visible point of the element is used.
+ TargetPosition *Position `json:"targetPosition"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type LocatorElementHandleOptions struct {
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorEvaluateOptions struct {
+ // Maximum time in milliseconds to wait for the locator before evaluating. Note that after locator is resolved,
+ // evaluation itself is not limited by the timeout. Defaults to `30000` (30 seconds). Pass `0` to disable timeout.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorEvaluateHandleOptions struct {
+ // Maximum time in milliseconds to wait for the locator before evaluating. Note that after locator is resolved,
+ // evaluation itself is not limited by the timeout. Defaults to `30000` (30 seconds). Pass `0` to disable timeout.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorFillOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorFilterOptions struct {
+ // Narrows down the results of the method to those which contain elements matching this relative locator. For example,
+ // `article` that has `text=Playwright` matches `<article><div>Playwright</div></article>`.
+ // Inner locator **must be relative** to the outer locator and is queried starting with the outer locator match, not
+ // the document root. For example, you can find `content` that has `div` in
+ // `<article><content><div>Playwright</div></content></article>`. However, looking for `content` that has `article
+ // div` will fail, because the inner locator must be relative and should not use any elements outside the `content`.
+ // Note that outer and inner locators must belong to the same frame. Inner locator must not contain [FrameLocator]s.
+ Has Locator `json:"has"`
+ // Matches elements that do not contain an element that matches an inner locator. Inner locator is queried against the
+ // outer one. For example, `article` that does not have `div` matches `<article><span>Playwright</span></article>`.
+ // Note that outer and inner locators must belong to the same frame. Inner locator must not contain [FrameLocator]s.
+ HasNot Locator `json:"hasNot"`
+ // Matches elements that do not contain specified text somewhere inside, possibly in a child or a descendant element.
+ // When passed a [string], matching is case-insensitive and searches for a substring.
+ HasNotText interface{} `json:"hasNotText"`
+ // Matches elements containing specified text somewhere inside, possibly in a child or a descendant element. When
+ // passed a [string], matching is case-insensitive and searches for a substring. For example, `"Playwright"` matches
+ // `<article><div>Playwright</div></article>`.
+ HasText interface{} `json:"hasText"`
+ // Only matches visible or invisible elements.
+ Visible *bool `json:"visible"`
+}
+
+type LocatorFocusOptions struct {
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorGetAttributeOptions struct {
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorGetByAltTextOptions struct {
+ // Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a
+ // regular expression. Note that exact match still trims whitespace.
+ Exact *bool `json:"exact"`
+}
+
+type LocatorGetByLabelOptions struct {
+ // Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a
+ // regular expression. Note that exact match still trims whitespace.
+ Exact *bool `json:"exact"`
+}
+
+type LocatorGetByPlaceholderOptions struct {
+ // Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a
+ // regular expression. Note that exact match still trims whitespace.
+ Exact *bool `json:"exact"`
+}
+
+type LocatorGetByRoleOptions struct {
+ // An attribute that is usually set by `aria-checked` or native `<input type=checkbox>` controls.
+ // Learn more about [`aria-checked`].
+ //
+ // [`aria-checked`]: https://www.w3.org/TR/wai-aria-1.2/#aria-checked
+ Checked *bool `json:"checked"`
+ // An attribute that is usually set by `aria-disabled` or `disabled`.
+ // **NOTE** Unlike most other attributes, `disabled` is inherited through the DOM hierarchy. Learn more about
+ // [`aria-disabled`].
+ //
+ // [`aria-disabled`]: https://www.w3.org/TR/wai-aria-1.2/#aria-disabled
+ Disabled *bool `json:"disabled"`
+ // Whether “[object Object]” is matched exactly: case-sensitive and whole-string. Defaults to false. Ignored when
+ // “[object Object]” is a regular expression. Note that exact match still trims whitespace.
+ Exact *bool `json:"exact"`
+ // An attribute that is usually set by `aria-expanded`.
+ // Learn more about [`aria-expanded`].
+ //
+ // [`aria-expanded`]: https://www.w3.org/TR/wai-aria-1.2/#aria-expanded
+ Expanded *bool `json:"expanded"`
+ // Option that controls whether hidden elements are matched. By default, only non-hidden elements, as
+ // [defined by ARIA], are matched by role selector.
+ // Learn more about [`aria-hidden`].
+ //
+ // [defined by ARIA]: https://www.w3.org/TR/wai-aria-1.2/#tree_exclusion
+ // [`aria-hidden`]: https://www.w3.org/TR/wai-aria-1.2/#aria-hidden
+ IncludeHidden *bool `json:"includeHidden"`
+ // A number attribute that is usually present for roles `heading`, `listitem`, `row`, `treeitem`, with default values
+ // for `<h1>-<h6>` elements.
+ // Learn more about [`aria-level`].
+ //
+ // [`aria-level`]: https://www.w3.org/TR/wai-aria-1.2/#aria-level
+ Level *int `json:"level"`
+ // Option to match the [accessible name]. By default, matching is
+ // case-insensitive and searches for a substring, use “[object Object]” to control this behavior.
+ // Learn more about [accessible name].
+ //
+ // [accessible name]: https://w3c.github.io/accname/#dfn-accessible-name
+ // [accessible name]: https://w3c.github.io/accname/#dfn-accessible-name
+ Name interface{} `json:"name"`
+ // An attribute that is usually set by `aria-pressed`.
+ // Learn more about [`aria-pressed`].
+ //
+ // [`aria-pressed`]: https://www.w3.org/TR/wai-aria-1.2/#aria-pressed
+ Pressed *bool `json:"pressed"`
+ // An attribute that is usually set by `aria-selected`.
+ // Learn more about [`aria-selected`].
+ //
+ // [`aria-selected`]: https://www.w3.org/TR/wai-aria-1.2/#aria-selected
+ Selected *bool `json:"selected"`
+}
+
+type LocatorGetByTextOptions struct {
+ // Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a
+ // regular expression. Note that exact match still trims whitespace.
+ Exact *bool `json:"exact"`
+}
+
+type LocatorGetByTitleOptions struct {
+ // Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a
+ // regular expression. Note that exact match still trims whitespace.
+ Exact *bool `json:"exact"`
+}
+
+type LocatorHoverOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // Modifier keys to press. Ensures that only these modifiers are pressed during the operation, and then restores
+ // current modifiers back. If not specified, currently pressed modifiers are used. "ControlOrMeta" resolves to
+ // "Control" on Windows and Linux and to "Meta" on macOS.
+ Modifiers []KeyboardModifier `json:"modifiers"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it. Note that keyboard
+ // `modifiers` will be pressed regardless of `trial` to allow testing elements which are only visible when those keys
+ // are pressed.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type LocatorInnerHTMLOptions struct {
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorInnerTextOptions struct {
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorInputValueOptions struct {
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorIsCheckedOptions struct {
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorIsDisabledOptions struct {
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorIsEditableOptions struct {
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorIsEnabledOptions struct {
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorIsHiddenOptions struct {
+ //
+ // Deprecated: This option is ignored. [Locator.IsHidden] does not wait for the element to become hidden and returns immediately.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorIsVisibleOptions struct {
+ //
+ // Deprecated: This option is ignored. [Locator.IsVisible] does not wait for the element to become visible and returns immediately.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorLocatorOptions struct {
+ // Narrows down the results of the method to those which contain elements matching this relative locator. For example,
+ // `article` that has `text=Playwright` matches `<article><div>Playwright</div></article>`.
+ // Inner locator **must be relative** to the outer locator and is queried starting with the outer locator match, not
+ // the document root. For example, you can find `content` that has `div` in
+ // `<article><content><div>Playwright</div></content></article>`. However, looking for `content` that has `article
+ // div` will fail, because the inner locator must be relative and should not use any elements outside the `content`.
+ // Note that outer and inner locators must belong to the same frame. Inner locator must not contain [FrameLocator]s.
+ Has Locator `json:"has"`
+ // Matches elements that do not contain an element that matches an inner locator. Inner locator is queried against the
+ // outer one. For example, `article` that does not have `div` matches `<article><span>Playwright</span></article>`.
+ // Note that outer and inner locators must belong to the same frame. Inner locator must not contain [FrameLocator]s.
+ HasNot Locator `json:"hasNot"`
+ // Matches elements that do not contain specified text somewhere inside, possibly in a child or a descendant element.
+ // When passed a [string], matching is case-insensitive and searches for a substring.
+ HasNotText interface{} `json:"hasNotText"`
+ // Matches elements containing specified text somewhere inside, possibly in a child or a descendant element. When
+ // passed a [string], matching is case-insensitive and searches for a substring. For example, `"Playwright"` matches
+ // `<article><div>Playwright</div></article>`.
+ HasText interface{} `json:"hasText"`
+}
+
+type LocatorPressOptions struct {
+ // Time to wait between `keydown` and `keyup` in milliseconds. Defaults to 0.
+ Delay *float64 `json:"delay"`
+ // Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You
+ // can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as
+ // navigating to inaccessible pages. Defaults to `false`.
+ //
+ // Deprecated: This option will default to `true` in the future.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorPressSequentiallyOptions struct {
+ // Time to wait between key presses in milliseconds. Defaults to 0.
+ Delay *float64 `json:"delay"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorScreenshotOptions struct {
+ // When set to `"disabled"`, stops CSS animations, CSS transitions and Web Animations. Animations get different
+ // treatment depending on their duration:
+ // - finite animations are fast-forwarded to completion, so they'll fire `transitionend` event.
+ // - infinite animations are canceled to initial state, and then played over after the screenshot.
+ // Defaults to `"allow"` that leaves animations untouched.
+ Animations *ScreenshotAnimations `json:"animations"`
+ // When set to `"hide"`, screenshot will hide text caret. When set to `"initial"`, text caret behavior will not be
+ // changed. Defaults to `"hide"`.
+ Caret *ScreenshotCaret `json:"caret"`
+ // Specify locators that should be masked when the screenshot is taken. Masked elements will be overlaid with a pink
+ // box `#FF00FF` (customized by “[object Object]”) that completely covers its bounding box. The mask is also applied
+ // to invisible elements, see [Matching only visible elements] to
+ // disable that.
+ //
+ // [Matching only visible elements]: https://playwright.dev/docs/locators#matching-only-visible-elements
+ Mask []Locator `json:"mask"`
+ // Specify the color of the overlay box for masked elements, in
+ // [CSS color format]. Default color is pink `#FF00FF`.
+ //
+ // [CSS color format]: https://developer.mozilla.org/en-US/docs/Web/CSS/color_value
+ MaskColor *string `json:"maskColor"`
+ // Hides default white background and allows capturing screenshots with transparency. Not applicable to `jpeg` images.
+ // Defaults to `false`.
+ OmitBackground *bool `json:"omitBackground"`
+ // The file path to save the image to. The screenshot type will be inferred from file extension. If “[object Object]”
+ // is a relative path, then it is resolved relative to the current working directory. If no path is provided, the
+ // image won't be saved to the disk.
+ Path *string `json:"path"`
+ // The quality of the image, between 0-100. Not applicable to `png` images.
+ Quality *int `json:"quality"`
+ // When set to `"css"`, screenshot will have a single pixel per each css pixel on the page. For high-dpi devices, this
+ // will keep screenshots small. Using `"device"` option will produce a single pixel per each device pixel, so
+ // screenshots of high-dpi devices will be twice as large or even larger.
+ // Defaults to `"device"`.
+ Scale *ScreenshotScale `json:"scale"`
+ // Text of the stylesheet to apply while making the screenshot. This is where you can hide dynamic elements, make
+ // elements invisible or change their properties to help you creating repeatable screenshots. This stylesheet pierces
+ // the Shadow DOM and applies to the inner frames.
+ Style *string `json:"style"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // Specify screenshot type, defaults to `png`.
+ Type *ScreenshotType `json:"type"`
+}
+
+type LocatorScrollIntoViewIfNeededOptions struct {
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorSelectOptionOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorSelectTextOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorSetCheckedOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type LocatorSetInputFilesOptions struct {
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorTapOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // Modifier keys to press. Ensures that only these modifiers are pressed during the operation, and then restores
+ // current modifiers back. If not specified, currently pressed modifiers are used. "ControlOrMeta" resolves to
+ // "Control" on Windows and Linux and to "Meta" on macOS.
+ Modifiers []KeyboardModifier `json:"modifiers"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it. Note that keyboard
+ // `modifiers` will be pressed regardless of `trial` to allow testing elements which are only visible when those keys
+ // are pressed.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type LocatorTextContentOptions struct {
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorTypeOptions struct {
+ // Time to wait between key presses in milliseconds. Defaults to 0.
+ Delay *float64 `json:"delay"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorUncheckOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type LocatorWaitForOptions struct {
+ // Defaults to `visible`. Can be either:
+ // - `attached` - wait for element to be present in DOM.
+ // - `detached` - wait for element to not be present in DOM.
+ // - `visible` - wait for element to have non-empty bounding box and no `visibility:hidden`. Note that element
+ // without any content or with `display:none` has an empty bounding box and is not considered visible.
+ // - `hidden` - wait for element to be either detached from DOM, or have an empty bounding box or
+ // `visibility:hidden`. This is opposite to the `visible` option.
+ State *WaitForSelectorState `json:"state"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorAssertionsToBeAttachedOptions struct {
+ Attached *bool `json:"attached"`
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorAssertionsToBeCheckedOptions struct {
+ // Provides state to assert for. Asserts for input to be checked by default. This option can't be used when
+ // “[object Object]” is set to true.
+ Checked *bool `json:"checked"`
+ // Asserts that the element is in the indeterminate (mixed) state. Only supported for checkboxes and radio buttons.
+ // This option can't be true when “[object Object]” is provided.
+ Indeterminate *bool `json:"indeterminate"`
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorAssertionsToBeDisabledOptions struct {
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorAssertionsToBeEditableOptions struct {
+ Editable *bool `json:"editable"`
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorAssertionsToBeEmptyOptions struct {
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorAssertionsToBeEnabledOptions struct {
+ Enabled *bool `json:"enabled"`
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorAssertionsToBeFocusedOptions struct {
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorAssertionsToBeHiddenOptions struct {
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorAssertionsToBeInViewportOptions struct {
+ // The minimal ratio of the element to intersect viewport. If equals to `0`, then element should intersect viewport at
+ // any positive ratio. Defaults to `0`.
+ Ratio *float64 `json:"ratio"`
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorAssertionsToBeVisibleOptions struct {
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+ Visible *bool `json:"visible"`
+}
+
+type LocatorAssertionsToContainClassOptions struct {
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorAssertionsToContainTextOptions struct {
+ // Whether to perform case-insensitive match. “[object Object]” option takes precedence over the corresponding regular
+ // expression flag if specified.
+ IgnoreCase *bool `json:"ignoreCase"`
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+ // Whether to use `element.innerText` instead of `element.textContent` when retrieving DOM node text.
+ UseInnerText *bool `json:"useInnerText"`
+}
+
+type LocatorAssertionsToHaveAccessibleDescriptionOptions struct {
+ // Whether to perform case-insensitive match. “[object Object]” option takes precedence over the corresponding regular
+ // expression flag if specified.
+ IgnoreCase *bool `json:"ignoreCase"`
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorAssertionsToHaveAccessibleErrorMessageOptions struct {
+ // Whether to perform case-insensitive match. “[object Object]” option takes precedence over the corresponding regular
+ // expression flag if specified.
+ IgnoreCase *bool `json:"ignoreCase"`
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorAssertionsToHaveAccessibleNameOptions struct {
+ // Whether to perform case-insensitive match. “[object Object]” option takes precedence over the corresponding regular
+ // expression flag if specified.
+ IgnoreCase *bool `json:"ignoreCase"`
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorAssertionsToHaveAttributeOptions struct {
+ // Whether to perform case-insensitive match. “[object Object]” option takes precedence over the corresponding regular
+ // expression flag if specified.
+ IgnoreCase *bool `json:"ignoreCase"`
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorAssertionsToHaveClassOptions struct {
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorAssertionsToHaveCountOptions struct {
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorAssertionsToHaveCSSOptions struct {
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorAssertionsToHaveIdOptions struct {
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorAssertionsToHaveJSPropertyOptions struct {
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorAssertionsToHaveRoleOptions struct {
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorAssertionsToHaveTextOptions struct {
+ // Whether to perform case-insensitive match. “[object Object]” option takes precedence over the corresponding regular
+ // expression flag if specified.
+ IgnoreCase *bool `json:"ignoreCase"`
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+ // Whether to use `element.innerText` instead of `element.textContent` when retrieving DOM node text.
+ UseInnerText *bool `json:"useInnerText"`
+}
+
+type LocatorAssertionsToHaveValueOptions struct {
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorAssertionsToHaveValuesOptions struct {
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+}
+
+type LocatorAssertionsToMatchAriaSnapshotOptions struct {
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+}
+
+type MouseClickOptions struct {
+ // Defaults to `left`.
+ Button *MouseButton `json:"button"`
+ // defaults to 1. See [UIEvent.Detail].
+ ClickCount *int `json:"clickCount"`
+ // Time to wait between `mousedown` and `mouseup` in milliseconds. Defaults to 0.
+ Delay *float64 `json:"delay"`
+}
+
+type MouseDblclickOptions struct {
+ // Defaults to `left`.
+ Button *MouseButton `json:"button"`
+ // Time to wait between `mousedown` and `mouseup` in milliseconds. Defaults to 0.
+ Delay *float64 `json:"delay"`
+}
+
+type MouseDownOptions struct {
+ // Defaults to `left`.
+ Button *MouseButton `json:"button"`
+ // defaults to 1. See [UIEvent.Detail].
+ ClickCount *int `json:"clickCount"`
+}
+
+type MouseMoveOptions struct {
+ // Defaults to 1. Sends intermediate `mousemove` events.
+ Steps *int `json:"steps"`
+}
+
+type MouseUpOptions struct {
+ // Defaults to `left`.
+ Button *MouseButton `json:"button"`
+ // defaults to 1. See [UIEvent.Detail].
+ ClickCount *int `json:"clickCount"`
+}
+
+type PageAddScriptTagOptions struct {
+ // Raw JavaScript content to be injected into frame.
+ Content *string `json:"content"`
+ // Path to the JavaScript file to be injected into frame. If `path` is a relative path, then it is resolved relative
+ // to the current working directory.
+ Path *string `json:"path"`
+ // Script type. Use 'module' in order to load a JavaScript ES6 module. See
+ // [script] for more details.
+ //
+ // [script]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script
+ Type *string `json:"type"`
+ // URL of a script to be added.
+ URL *string `json:"url"`
+}
+
+type PageAddStyleTagOptions struct {
+ // Raw CSS content to be injected into frame.
+ Content *string `json:"content"`
+ // Path to the CSS file to be injected into frame. If `path` is a relative path, then it is resolved relative to the
+ // current working directory.
+ Path *string `json:"path"`
+ // URL of the `<link>` tag.
+ URL *string `json:"url"`
+}
+
+type PageCheckOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type PageClickOptions struct {
+ // Defaults to `left`.
+ Button *MouseButton `json:"button"`
+ // defaults to 1. See [UIEvent.Detail].
+ ClickCount *int `json:"clickCount"`
+ // Time to wait between `mousedown` and `mouseup` in milliseconds. Defaults to 0.
+ Delay *float64 `json:"delay"`
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // Modifier keys to press. Ensures that only these modifiers are pressed during the operation, and then restores
+ // current modifiers back. If not specified, currently pressed modifiers are used. "ControlOrMeta" resolves to
+ // "Control" on Windows and Linux and to "Meta" on macOS.
+ Modifiers []KeyboardModifier `json:"modifiers"`
+ // Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You
+ // can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as
+ // navigating to inaccessible pages. Defaults to `false`.
+ //
+ // Deprecated: This option will default to `true` in the future.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it. Note that keyboard
+ // `modifiers` will be pressed regardless of `trial` to allow testing elements which are only visible when those keys
+ // are pressed.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type PageCloseOptions struct {
+ // The reason to be reported to the operations interrupted by the page closure.
+ Reason *string `json:"reason"`
+ // Defaults to `false`. Whether to run the
+ // [before unload] page handlers.
+ //
+ // [before unload]: https://developer.mozilla.org/en-US/docs/Web/Events/beforeunload
+ RunBeforeUnload *bool `json:"runBeforeUnload"`
+}
+
+type PageDblclickOptions struct {
+ // Defaults to `left`.
+ Button *MouseButton `json:"button"`
+ // Time to wait between `mousedown` and `mouseup` in milliseconds. Defaults to 0.
+ Delay *float64 `json:"delay"`
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // Modifier keys to press. Ensures that only these modifiers are pressed during the operation, and then restores
+ // current modifiers back. If not specified, currently pressed modifiers are used. "ControlOrMeta" resolves to
+ // "Control" on Windows and Linux and to "Meta" on macOS.
+ Modifiers []KeyboardModifier `json:"modifiers"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it. Note that keyboard
+ // `modifiers` will be pressed regardless of `trial` to allow testing elements which are only visible when those keys
+ // are pressed.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type PageDispatchEventOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageDragAndDropOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // Clicks on the source element at this point relative to the top-left corner of the element's padding box. If not
+ // specified, some visible point of the element is used.
+ SourcePosition *Position `json:"sourcePosition"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Drops on the target element at this point relative to the top-left corner of the element's padding box. If not
+ // specified, some visible point of the element is used.
+ TargetPosition *Position `json:"targetPosition"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type PageEmulateMediaOptions struct {
+ // Emulates [prefers-colors-scheme]
+ // media feature, supported values are `light` and `dark`. Passing `no-override` disables color scheme
+ // emulation. `no-preference` is deprecated.
+ //
+ // [prefers-colors-scheme]: https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme
+ ColorScheme *ColorScheme `json:"colorScheme"`
+ // Emulates `prefers-contrast` media feature, supported values are `no-preference`, `more`. Passing
+ // `no-override` disables contrast emulation.
+ Contrast *Contrast `json:"contrast"`
+ // Emulates `forced-colors` media feature, supported values are `active` and `none`. Passing `no-override`
+ // disables forced colors emulation.
+ ForcedColors *ForcedColors `json:"forcedColors"`
+ // Changes the CSS media type of the page. The only allowed values are `screen`, `print` and `no-override`.
+ // Passing `no-override` disables CSS media emulation.
+ Media *Media `json:"media"`
+ // Emulates `prefers-reduced-motion` media feature, supported values are `reduce`, `no-preference`. Passing
+ // `no-override` disables reduced motion emulation.
+ ReducedMotion *ReducedMotion `json:"reducedMotion"`
+}
+
+type PageEvalOnSelectorOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+}
+
+type PageFillOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageFocusOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageFrameOptions struct {
+ // Frame name specified in the `iframe`'s `name` attribute. Optional.
+ Name *string `json:"name"`
+ // A glob pattern, regex pattern or predicate receiving frame's `url` as a [URL] object. Optional.
+ URL interface{} `json:"url"`
+}
+
+type PageGetAttributeOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageGetByAltTextOptions struct {
+ // Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a
+ // regular expression. Note that exact match still trims whitespace.
+ Exact *bool `json:"exact"`
+}
+
+type PageGetByLabelOptions struct {
+ // Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a
+ // regular expression. Note that exact match still trims whitespace.
+ Exact *bool `json:"exact"`
+}
+
+type PageGetByPlaceholderOptions struct {
+ // Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a
+ // regular expression. Note that exact match still trims whitespace.
+ Exact *bool `json:"exact"`
+}
+
+type PageGetByRoleOptions struct {
+ // An attribute that is usually set by `aria-checked` or native `<input type=checkbox>` controls.
+ // Learn more about [`aria-checked`].
+ //
+ // [`aria-checked`]: https://www.w3.org/TR/wai-aria-1.2/#aria-checked
+ Checked *bool `json:"checked"`
+ // An attribute that is usually set by `aria-disabled` or `disabled`.
+ // **NOTE** Unlike most other attributes, `disabled` is inherited through the DOM hierarchy. Learn more about
+ // [`aria-disabled`].
+ //
+ // [`aria-disabled`]: https://www.w3.org/TR/wai-aria-1.2/#aria-disabled
+ Disabled *bool `json:"disabled"`
+ // Whether “[object Object]” is matched exactly: case-sensitive and whole-string. Defaults to false. Ignored when
+ // “[object Object]” is a regular expression. Note that exact match still trims whitespace.
+ Exact *bool `json:"exact"`
+ // An attribute that is usually set by `aria-expanded`.
+ // Learn more about [`aria-expanded`].
+ //
+ // [`aria-expanded`]: https://www.w3.org/TR/wai-aria-1.2/#aria-expanded
+ Expanded *bool `json:"expanded"`
+ // Option that controls whether hidden elements are matched. By default, only non-hidden elements, as
+ // [defined by ARIA], are matched by role selector.
+ // Learn more about [`aria-hidden`].
+ //
+ // [defined by ARIA]: https://www.w3.org/TR/wai-aria-1.2/#tree_exclusion
+ // [`aria-hidden`]: https://www.w3.org/TR/wai-aria-1.2/#aria-hidden
+ IncludeHidden *bool `json:"includeHidden"`
+ // A number attribute that is usually present for roles `heading`, `listitem`, `row`, `treeitem`, with default values
+ // for `<h1>-<h6>` elements.
+ // Learn more about [`aria-level`].
+ //
+ // [`aria-level`]: https://www.w3.org/TR/wai-aria-1.2/#aria-level
+ Level *int `json:"level"`
+ // Option to match the [accessible name]. By default, matching is
+ // case-insensitive and searches for a substring, use “[object Object]” to control this behavior.
+ // Learn more about [accessible name].
+ //
+ // [accessible name]: https://w3c.github.io/accname/#dfn-accessible-name
+ // [accessible name]: https://w3c.github.io/accname/#dfn-accessible-name
+ Name interface{} `json:"name"`
+ // An attribute that is usually set by `aria-pressed`.
+ // Learn more about [`aria-pressed`].
+ //
+ // [`aria-pressed`]: https://www.w3.org/TR/wai-aria-1.2/#aria-pressed
+ Pressed *bool `json:"pressed"`
+ // An attribute that is usually set by `aria-selected`.
+ // Learn more about [`aria-selected`].
+ //
+ // [`aria-selected`]: https://www.w3.org/TR/wai-aria-1.2/#aria-selected
+ Selected *bool `json:"selected"`
+}
+
+type PageGetByTextOptions struct {
+ // Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a
+ // regular expression. Note that exact match still trims whitespace.
+ Exact *bool `json:"exact"`
+}
+
+type PageGetByTitleOptions struct {
+ // Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a
+ // regular expression. Note that exact match still trims whitespace.
+ Exact *bool `json:"exact"`
+}
+
+type PageGoBackOptions struct {
+ // Maximum operation time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultNavigationTimeout], [BrowserContext.SetDefaultTimeout],
+ // [Page.SetDefaultNavigationTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When to consider operation succeeded, defaults to `load`. Events can be either:
+ // - `domcontentloaded` - consider operation to be finished when the `DOMContentLoaded` event is fired.
+ // - `load` - consider operation to be finished when the `load` event is fired.
+ // - `networkidle` - **DISCOURAGED** consider operation to be finished when there are no network connections for
+ // at least `500` ms. Don't use this method for testing, rely on web assertions to assess readiness instead.
+ // - `commit` - consider operation to be finished when network response is received and the document started
+ // loading.
+ WaitUntil *WaitUntilState `json:"waitUntil"`
+}
+
+type PageGoForwardOptions struct {
+ // Maximum operation time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultNavigationTimeout], [BrowserContext.SetDefaultTimeout],
+ // [Page.SetDefaultNavigationTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When to consider operation succeeded, defaults to `load`. Events can be either:
+ // - `domcontentloaded` - consider operation to be finished when the `DOMContentLoaded` event is fired.
+ // - `load` - consider operation to be finished when the `load` event is fired.
+ // - `networkidle` - **DISCOURAGED** consider operation to be finished when there are no network connections for
+ // at least `500` ms. Don't use this method for testing, rely on web assertions to assess readiness instead.
+ // - `commit` - consider operation to be finished when network response is received and the document started
+ // loading.
+ WaitUntil *WaitUntilState `json:"waitUntil"`
+}
+
+type PageGotoOptions struct {
+ // Referer header value. If provided it will take preference over the referer header value set by
+ // [Page.SetExtraHTTPHeaders].
+ Referer *string `json:"referer"`
+ // Maximum operation time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultNavigationTimeout], [BrowserContext.SetDefaultTimeout],
+ // [Page.SetDefaultNavigationTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When to consider operation succeeded, defaults to `load`. Events can be either:
+ // - `domcontentloaded` - consider operation to be finished when the `DOMContentLoaded` event is fired.
+ // - `load` - consider operation to be finished when the `load` event is fired.
+ // - `networkidle` - **DISCOURAGED** consider operation to be finished when there are no network connections for
+ // at least `500` ms. Don't use this method for testing, rely on web assertions to assess readiness instead.
+ // - `commit` - consider operation to be finished when network response is received and the document started
+ // loading.
+ WaitUntil *WaitUntilState `json:"waitUntil"`
+}
+
+type PageHoverOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // Modifier keys to press. Ensures that only these modifiers are pressed during the operation, and then restores
+ // current modifiers back. If not specified, currently pressed modifiers are used. "ControlOrMeta" resolves to
+ // "Control" on Windows and Linux and to "Meta" on macOS.
+ Modifiers []KeyboardModifier `json:"modifiers"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it. Note that keyboard
+ // `modifiers` will be pressed regardless of `trial` to allow testing elements which are only visible when those keys
+ // are pressed.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type PageInnerHTMLOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageInnerTextOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageInputValueOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageIsCheckedOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageIsDisabledOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageIsEditableOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageIsEnabledOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageIsHiddenOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ //
+ // Deprecated: This option is ignored. [Page.IsHidden] does not wait for the element to become hidden and returns immediately.
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageIsVisibleOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ //
+ // Deprecated: This option is ignored. [Page.IsVisible] does not wait for the element to become visible and returns immediately.
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageLocatorOptions struct {
+ // Narrows down the results of the method to those which contain elements matching this relative locator. For example,
+ // `article` that has `text=Playwright` matches `<article><div>Playwright</div></article>`.
+ // Inner locator **must be relative** to the outer locator and is queried starting with the outer locator match, not
+ // the document root. For example, you can find `content` that has `div` in
+ // `<article><content><div>Playwright</div></content></article>`. However, looking for `content` that has `article
+ // div` will fail, because the inner locator must be relative and should not use any elements outside the `content`.
+ // Note that outer and inner locators must belong to the same frame. Inner locator must not contain [FrameLocator]s.
+ Has Locator `json:"has"`
+ // Matches elements that do not contain an element that matches an inner locator. Inner locator is queried against the
+ // outer one. For example, `article` that does not have `div` matches `<article><span>Playwright</span></article>`.
+ // Note that outer and inner locators must belong to the same frame. Inner locator must not contain [FrameLocator]s.
+ HasNot Locator `json:"hasNot"`
+ // Matches elements that do not contain specified text somewhere inside, possibly in a child or a descendant element.
+ // When passed a [string], matching is case-insensitive and searches for a substring.
+ HasNotText interface{} `json:"hasNotText"`
+ // Matches elements containing specified text somewhere inside, possibly in a child or a descendant element. When
+ // passed a [string], matching is case-insensitive and searches for a substring. For example, `"Playwright"` matches
+ // `<article><div>Playwright</div></article>`.
+ HasText interface{} `json:"hasText"`
+}
+
+type PagePdfOptions struct {
+ // Display header and footer. Defaults to `false`.
+ DisplayHeaderFooter *bool `json:"displayHeaderFooter"`
+ // HTML template for the print footer. Should use the same format as the “[object Object]”.
+ FooterTemplate *string `json:"footerTemplate"`
+ // Paper format. If set, takes priority over “[object Object]” or “[object Object]” options. Defaults to 'Letter'.
+ Format *string `json:"format"`
+ // HTML template for the print header. Should be valid HTML markup with following classes used to inject printing
+ // values into them:
+ // - `date` formatted print date
+ // - `title` document title
+ // - `url` document location
+ // - `pageNumber` current page number
+ // - `totalPages` total pages in the document
+ HeaderTemplate *string `json:"headerTemplate"`
+ // Paper height, accepts values labeled with units.
+ Height *string `json:"height"`
+ // Paper orientation. Defaults to `false`.
+ Landscape *bool `json:"landscape"`
+ // Paper margins, defaults to none.
+ Margin *Margin `json:"margin"`
+ // Whether or not to embed the document outline into the PDF. Defaults to `false`.
+ Outline *bool `json:"outline"`
+ // Paper ranges to print, e.g., '1-5, 8, 11-13'. Defaults to the empty string, which means print all pages.
+ PageRanges *string `json:"pageRanges"`
+ // The file path to save the PDF to. If “[object Object]” is a relative path, then it is resolved relative to the
+ // current working directory. If no path is provided, the PDF won't be saved to the disk.
+ Path *string `json:"path"`
+ // Give any CSS `@page` size declared in the page priority over what is declared in “[object Object]” and
+ // “[object Object]” or “[object Object]” options. Defaults to `false`, which will scale the content to fit the paper
+ // size.
+ PreferCSSPageSize *bool `json:"preferCSSPageSize"`
+ // Print background graphics. Defaults to `false`.
+ PrintBackground *bool `json:"printBackground"`
+ // Scale of the webpage rendering. Defaults to `1`. Scale amount must be between 0.1 and 2.
+ Scale *float64 `json:"scale"`
+ // Whether or not to generate tagged (accessible) PDF. Defaults to `false`.
+ Tagged *bool `json:"tagged"`
+ // Paper width, accepts values labeled with units.
+ Width *string `json:"width"`
+}
+
+type PagePressOptions struct {
+ // Time to wait between `keydown` and `keyup` in milliseconds. Defaults to 0.
+ Delay *float64 `json:"delay"`
+ // Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You
+ // can opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as
+ // navigating to inaccessible pages. Defaults to `false`.
+ //
+ // Deprecated: This option will default to `true` in the future.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageQuerySelectorOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+}
+
+type PageAddLocatorHandlerOptions struct {
+ // By default, after calling the handler Playwright will wait until the overlay becomes hidden, and only then
+ // Playwright will continue with the action/assertion that triggered the handler. This option allows to opt-out of
+ // this behavior, so that overlay can stay visible after the handler has run.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // Specifies the maximum number of times this handler should be called. Unlimited by default.
+ Times *int `json:"times"`
+}
+
+type PageReloadOptions struct {
+ // Maximum operation time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultNavigationTimeout], [BrowserContext.SetDefaultTimeout],
+ // [Page.SetDefaultNavigationTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When to consider operation succeeded, defaults to `load`. Events can be either:
+ // - `domcontentloaded` - consider operation to be finished when the `DOMContentLoaded` event is fired.
+ // - `load` - consider operation to be finished when the `load` event is fired.
+ // - `networkidle` - **DISCOURAGED** consider operation to be finished when there are no network connections for
+ // at least `500` ms. Don't use this method for testing, rely on web assertions to assess readiness instead.
+ // - `commit` - consider operation to be finished when network response is received and the document started
+ // loading.
+ WaitUntil *WaitUntilState `json:"waitUntil"`
+}
+
+type PageRouteFromHAROptions struct {
+ // - If set to 'abort' any request not found in the HAR file will be aborted.
+ // - If set to 'fallback' missing requests will be sent to the network.
+ // Defaults to abort.
+ NotFound *HarNotFound `json:"notFound"`
+ // If specified, updates the given HAR with the actual network information instead of serving from file. The file is
+ // written to disk when [BrowserContext.Close] is called.
+ Update *bool `json:"update"`
+ // Optional setting to control resource content management. If `attach` is specified, resources are persisted as
+ // separate files or entries in the ZIP archive. If `embed` is specified, content is stored inline the HAR file.
+ UpdateContent *RouteFromHarUpdateContentPolicy `json:"updateContent"`
+ // When set to `minimal`, only record information necessary for routing from HAR. This omits sizes, timing, page,
+ // cookies, security and other types of HAR information that are not used when replaying from HAR. Defaults to
+ // `minimal`.
+ UpdateMode *HarMode `json:"updateMode"`
+ // A glob pattern, regular expression or predicate to match the request URL. Only requests with URL matching the
+ // pattern will be served from the HAR file. If not specified, all requests are served from the HAR file.
+ URL interface{} `json:"url"`
+}
+
+type PageScreenshotOptions struct {
+ // When set to `"disabled"`, stops CSS animations, CSS transitions and Web Animations. Animations get different
+ // treatment depending on their duration:
+ // - finite animations are fast-forwarded to completion, so they'll fire `transitionend` event.
+ // - infinite animations are canceled to initial state, and then played over after the screenshot.
+ // Defaults to `"allow"` that leaves animations untouched.
+ Animations *ScreenshotAnimations `json:"animations"`
+ // When set to `"hide"`, screenshot will hide text caret. When set to `"initial"`, text caret behavior will not be
+ // changed. Defaults to `"hide"`.
+ Caret *ScreenshotCaret `json:"caret"`
+ // An object which specifies clipping of the resulting image.
+ Clip *Rect `json:"clip"`
+ // When true, takes a screenshot of the full scrollable page, instead of the currently visible viewport. Defaults to
+ // `false`.
+ FullPage *bool `json:"fullPage"`
+ // Specify locators that should be masked when the screenshot is taken. Masked elements will be overlaid with a pink
+ // box `#FF00FF` (customized by “[object Object]”) that completely covers its bounding box. The mask is also applied
+ // to invisible elements, see [Matching only visible elements] to
+ // disable that.
+ //
+ // [Matching only visible elements]: https://playwright.dev/docs/locators#matching-only-visible-elements
+ Mask []Locator `json:"mask"`
+ // Specify the color of the overlay box for masked elements, in
+ // [CSS color format]. Default color is pink `#FF00FF`.
+ //
+ // [CSS color format]: https://developer.mozilla.org/en-US/docs/Web/CSS/color_value
+ MaskColor *string `json:"maskColor"`
+ // Hides default white background and allows capturing screenshots with transparency. Not applicable to `jpeg` images.
+ // Defaults to `false`.
+ OmitBackground *bool `json:"omitBackground"`
+ // The file path to save the image to. The screenshot type will be inferred from file extension. If “[object Object]”
+ // is a relative path, then it is resolved relative to the current working directory. If no path is provided, the
+ // image won't be saved to the disk.
+ Path *string `json:"path"`
+ // The quality of the image, between 0-100. Not applicable to `png` images.
+ Quality *int `json:"quality"`
+ // When set to `"css"`, screenshot will have a single pixel per each css pixel on the page. For high-dpi devices, this
+ // will keep screenshots small. Using `"device"` option will produce a single pixel per each device pixel, so
+ // screenshots of high-dpi devices will be twice as large or even larger.
+ // Defaults to `"device"`.
+ Scale *ScreenshotScale `json:"scale"`
+ // Text of the stylesheet to apply while making the screenshot. This is where you can hide dynamic elements, make
+ // elements invisible or change their properties to help you creating repeatable screenshots. This stylesheet pierces
+ // the Shadow DOM and applies to the inner frames.
+ Style *string `json:"style"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // Specify screenshot type, defaults to `png`.
+ Type *ScreenshotType `json:"type"`
+}
+
+type PageSelectOptionOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageSetCheckedOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type PageSetContentOptions struct {
+ // Maximum operation time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultNavigationTimeout], [BrowserContext.SetDefaultTimeout],
+ // [Page.SetDefaultNavigationTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When to consider operation succeeded, defaults to `load`. Events can be either:
+ // - `domcontentloaded` - consider operation to be finished when the `DOMContentLoaded` event is fired.
+ // - `load` - consider operation to be finished when the `load` event is fired.
+ // - `networkidle` - **DISCOURAGED** consider operation to be finished when there are no network connections for
+ // at least `500` ms. Don't use this method for testing, rely on web assertions to assess readiness instead.
+ // - `commit` - consider operation to be finished when network response is received and the document started
+ // loading.
+ WaitUntil *WaitUntilState `json:"waitUntil"`
+}
+
+type PageSetInputFilesOptions struct {
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageTapOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // Modifier keys to press. Ensures that only these modifiers are pressed during the operation, and then restores
+ // current modifiers back. If not specified, currently pressed modifiers are used. "ControlOrMeta" resolves to
+ // "Control" on Windows and Linux and to "Meta" on macOS.
+ Modifiers []KeyboardModifier `json:"modifiers"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it. Note that keyboard
+ // `modifiers` will be pressed regardless of `trial` to allow testing elements which are only visible when those keys
+ // are pressed.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type PageTextContentOptions struct {
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageTypeOptions struct {
+ // Time to wait between key presses in milliseconds. Defaults to 0.
+ Delay *float64 `json:"delay"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageUncheckOptions struct {
+ // Whether to bypass the [actionability] checks. Defaults to `false`.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Force *bool `json:"force"`
+ // This option has no effect.
+ //
+ // Deprecated: This option has no effect.
+ NoWaitAfter *bool `json:"noWaitAfter"`
+ // A point to use relative to the top-left corner of element padding box. If not specified, uses some visible point of
+ // the element.
+ Position *Position `json:"position"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When set, this method only performs the [actionability] checks and skips the action. Defaults
+ // to `false`. Useful to wait until the element is ready for the action without performing it.
+ //
+ // [actionability]: https://playwright.dev/docs/actionability
+ Trial *bool `json:"trial"`
+}
+
+type PageUnrouteAllOptions struct {
+ // Specifies whether to wait for already running handlers and what to do if they throw errors:
+ // - `default` - do not wait for current handler calls (if any) to finish, if unrouted handler throws, it may
+ // result in unhandled error
+ // - `wait` - wait for current handler calls (if any) to finish
+ // - `ignoreErrors` - do not wait for current handler calls (if any) to finish, all errors thrown by the handlers
+ // after unrouting are silently caught
+ Behavior *UnrouteBehavior `json:"behavior"`
+}
+
+type Size struct {
+ // page width in pixels.
+ Width int `json:"width"`
+ // page height in pixels.
+ Height int `json:"height"`
+}
+
+type PageExpectConsoleMessageOptions struct {
+ // Receives the [ConsoleMessage] object and resolves to truthy value when the waiting should resolve.
+ Predicate func(ConsoleMessage) bool `json:"predicate"`
+ // Maximum time to wait for in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The
+ // default value can be changed by using the [BrowserContext.SetDefaultTimeout].
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageExpectDownloadOptions struct {
+ // Receives the [Download] object and resolves to truthy value when the waiting should resolve.
+ Predicate func(Download) bool `json:"predicate"`
+ // Maximum time to wait for in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The
+ // default value can be changed by using the [BrowserContext.SetDefaultTimeout].
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageExpectEventOptions struct {
+ // Receives the event data and resolves to truthy value when the waiting should resolve.
+ Predicate interface{} `json:"predicate"`
+ // Maximum time to wait for in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The
+ // default value can be changed by using the [BrowserContext.SetDefaultTimeout].
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageExpectFileChooserOptions struct {
+ // Receives the [FileChooser] object and resolves to truthy value when the waiting should resolve.
+ Predicate func(FileChooser) bool `json:"predicate"`
+ // Maximum time to wait for in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The
+ // default value can be changed by using the [BrowserContext.SetDefaultTimeout].
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageWaitForFunctionOptions struct {
+ // If “[object Object]” is `raf`, then “[object Object]” is constantly executed in `requestAnimationFrame` callback.
+ // If “[object Object]” is a number, then it is treated as an interval in milliseconds at which the function would be
+ // executed. Defaults to `raf`.
+ Polling interface{} `json:"polling"`
+ // Maximum time to wait for in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The
+ // default value can be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageWaitForLoadStateOptions struct {
+ // Optional load state to wait for, defaults to `load`. If the state has been already reached while loading current
+ // document, the method resolves immediately. Can be one of:
+ // - `load` - wait for the `load` event to be fired.
+ // - `domcontentloaded` - wait for the `DOMContentLoaded` event to be fired.
+ // - `networkidle` - **DISCOURAGED** wait until there are no network connections for at least `500` ms. Don't use
+ // this method for testing, rely on web assertions to assess readiness instead.
+ State *LoadState `json:"state"`
+ // Maximum operation time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultNavigationTimeout], [BrowserContext.SetDefaultTimeout],
+ // [Page.SetDefaultNavigationTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageExpectNavigationOptions struct {
+ // Maximum operation time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultNavigationTimeout], [BrowserContext.SetDefaultTimeout],
+ // [Page.SetDefaultNavigationTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation. Note that if
+ // the parameter is a string without wildcard characters, the method will wait for navigation to URL that is exactly
+ // equal to the string.
+ URL interface{} `json:"url"`
+ // When to consider operation succeeded, defaults to `load`. Events can be either:
+ // - `domcontentloaded` - consider operation to be finished when the `DOMContentLoaded` event is fired.
+ // - `load` - consider operation to be finished when the `load` event is fired.
+ // - `networkidle` - **DISCOURAGED** consider operation to be finished when there are no network connections for
+ // at least `500` ms. Don't use this method for testing, rely on web assertions to assess readiness instead.
+ // - `commit` - consider operation to be finished when network response is received and the document started
+ // loading.
+ WaitUntil *WaitUntilState `json:"waitUntil"`
+}
+
+type PageExpectPopupOptions struct {
+ // Receives the [Page] object and resolves to truthy value when the waiting should resolve.
+ Predicate func(Page) bool `json:"predicate"`
+ // Maximum time to wait for in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The
+ // default value can be changed by using the [BrowserContext.SetDefaultTimeout].
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageExpectRequestOptions struct {
+ // Maximum wait time in milliseconds, defaults to 30 seconds, pass `0` to disable the timeout. The default value can
+ // be changed by using the [Page.SetDefaultTimeout] method.
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageExpectRequestFinishedOptions struct {
+ // Receives the [Request] object and resolves to truthy value when the waiting should resolve.
+ Predicate func(Request) bool `json:"predicate"`
+ // Maximum time to wait for in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The
+ // default value can be changed by using the [BrowserContext.SetDefaultTimeout].
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageExpectResponseOptions struct {
+ // Maximum wait time in milliseconds, defaults to 30 seconds, pass `0` to disable the timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageWaitForSelectorOptions struct {
+ // Defaults to `visible`. Can be either:
+ // - `attached` - wait for element to be present in DOM.
+ // - `detached` - wait for element to not be present in DOM.
+ // - `visible` - wait for element to have non-empty bounding box and no `visibility:hidden`. Note that element
+ // without any content or with `display:none` has an empty bounding box and is not considered visible.
+ // - `hidden` - wait for element to be either detached from DOM, or have an empty bounding box or
+ // `visibility:hidden`. This is opposite to the `visible` option.
+ State *WaitForSelectorState `json:"state"`
+ // When true, the call requires selector to resolve to a single element. If given selector resolves to more than one
+ // element, the call throws an exception.
+ Strict *bool `json:"strict"`
+ // Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageWaitForURLOptions struct {
+ // Maximum operation time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can
+ // be changed by using the [BrowserContext.SetDefaultNavigationTimeout], [BrowserContext.SetDefaultTimeout],
+ // [Page.SetDefaultNavigationTimeout] or [Page.SetDefaultTimeout] methods.
+ Timeout *float64 `json:"timeout"`
+ // When to consider operation succeeded, defaults to `load`. Events can be either:
+ // - `domcontentloaded` - consider operation to be finished when the `DOMContentLoaded` event is fired.
+ // - `load` - consider operation to be finished when the `load` event is fired.
+ // - `networkidle` - **DISCOURAGED** consider operation to be finished when there are no network connections for
+ // at least `500` ms. Don't use this method for testing, rely on web assertions to assess readiness instead.
+ // - `commit` - consider operation to be finished when network response is received and the document started
+ // loading.
+ WaitUntil *WaitUntilState `json:"waitUntil"`
+}
+
+type PageExpectWebSocketOptions struct {
+ // Receives the [WebSocket] object and resolves to truthy value when the waiting should resolve.
+ Predicate func(WebSocket) bool `json:"predicate"`
+ // Maximum time to wait for in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The
+ // default value can be changed by using the [BrowserContext.SetDefaultTimeout].
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageExpectWorkerOptions struct {
+ // Receives the [Worker] object and resolves to truthy value when the waiting should resolve.
+ Predicate func(Worker) bool `json:"predicate"`
+ // Maximum time to wait for in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The
+ // default value can be changed by using the [BrowserContext.SetDefaultTimeout].
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageWaitForEventOptions struct {
+ // Receives the event data and resolves to truthy value when the waiting should resolve.
+ Predicate interface{} `json:"predicate"`
+ // Maximum time to wait for in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The
+ // default value can be changed by using the [BrowserContext.SetDefaultTimeout].
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageAssertionsToHaveTitleOptions struct {
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+}
+
+type PageAssertionsToHaveURLOptions struct {
+ // Whether to perform case-insensitive match. “[object Object]” option takes precedence over the corresponding regular
+ // expression parameter if specified. A provided predicate ignores this flag.
+ IgnoreCase *bool `json:"ignoreCase"`
+ // Time to retry the assertion for in milliseconds. Defaults to `5000`.
+ Timeout *float64 `json:"timeout"`
+}
+
+type RequestSizesResult struct {
+ // Size of the request body (POST data payload) in bytes. Set to 0 if there was no body.
+ RequestBodySize int `json:"requestBodySize"`
+ // Total number of bytes from the start of the HTTP request message until (and including) the double CRLF before the
+ // body.
+ RequestHeadersSize int `json:"requestHeadersSize"`
+ // Size of the received response body (encoded) in bytes.
+ ResponseBodySize int `json:"responseBodySize"`
+ // Total number of bytes from the start of the HTTP response message until (and including) the double CRLF before the
+ // body.
+ ResponseHeadersSize int `json:"responseHeadersSize"`
+}
+
+type RequestTiming struct {
+ // Request start time in milliseconds elapsed since January 1, 1970 00:00:00 UTC
+ StartTime float64 `json:"startTime"`
+ // Time immediately before the browser starts the domain name lookup for the resource. The value is given in
+ // milliseconds relative to `startTime`, -1 if not available.
+ DomainLookupStart float64 `json:"domainLookupStart"`
+ // Time immediately after the browser starts the domain name lookup for the resource. The value is given in
+ // milliseconds relative to `startTime`, -1 if not available.
+ DomainLookupEnd float64 `json:"domainLookupEnd"`
+ // Time immediately before the user agent starts establishing the connection to the server to retrieve the resource.
+ // The value is given in milliseconds relative to `startTime`, -1 if not available.
+ ConnectStart float64 `json:"connectStart"`
+ // Time immediately before the browser starts the handshake process to secure the current connection. The value is
+ // given in milliseconds relative to `startTime`, -1 if not available.
+ SecureConnectionStart float64 `json:"secureConnectionStart"`
+ // Time immediately before the user agent starts establishing the connection to the server to retrieve the resource.
+ // The value is given in milliseconds relative to `startTime`, -1 if not available.
+ ConnectEnd float64 `json:"connectEnd"`
+ // Time immediately before the browser starts requesting the resource from the server, cache, or local resource. The
+ // value is given in milliseconds relative to `startTime`, -1 if not available.
+ RequestStart float64 `json:"requestStart"`
+ // Time immediately after the browser receives the first byte of the response from the server, cache, or local
+ // resource. The value is given in milliseconds relative to `startTime`, -1 if not available.
+ ResponseStart float64 `json:"responseStart"`
+ // Time immediately after the browser receives the last byte of the resource or immediately before the transport
+ // connection is closed, whichever comes first. The value is given in milliseconds relative to `startTime`, -1 if not
+ // available.
+ ResponseEnd float64 `json:"responseEnd"`
+}
+
+type ResponseSecurityDetailsResult struct {
+ // Common Name component of the Issuer field. from the certificate. This should only be used for informational
+ // purposes. Optional.
+ Issuer *string `json:"issuer"`
+ // The specific TLS protocol used. (e.g. `TLS 1.3`). Optional.
+ Protocol *string `json:"protocol"`
+ // Common Name component of the Subject field from the certificate. This should only be used for informational
+ // purposes. Optional.
+ SubjectName *string `json:"subjectName"`
+ // Unix timestamp (in seconds) specifying when this cert becomes valid. Optional.
+ ValidFrom *float64 `json:"validFrom"`
+ // Unix timestamp (in seconds) specifying when this cert becomes invalid. Optional.
+ ValidTo *float64 `json:"validTo"`
+}
+
+type ResponseServerAddrResult struct {
+ // IPv4 or IPV6 address of the server.
+ IpAddress string `json:"ipAddress"`
+ Port int `json:"port"`
+}
+
+type RouteContinueOptions struct {
+ // If set changes the request HTTP headers. Header values will be converted to a string.
+ Headers map[string]string `json:"headers"`
+ // If set changes the request method (e.g. GET or POST).
+ Method *string `json:"method"`
+ // If set changes the post data of request.
+ PostData interface{} `json:"postData"`
+ // If set changes the request URL. New URL must have same protocol as original one.
+ URL *string `json:"url"`
+}
+
+type RouteFallbackOptions struct {
+ // If set changes the request HTTP headers. Header values will be converted to a string.
+ Headers map[string]string `json:"headers"`
+ // If set changes the request method (e.g. GET or POST).
+ Method *string `json:"method"`
+ // If set changes the post data of request.
+ PostData interface{} `json:"postData"`
+ // If set changes the request URL. New URL must have same protocol as original one. Changing the URL won't affect the
+ // route matching, all the routes are matched using the original request URL.
+ URL *string `json:"url"`
+}
+
+type RouteFetchOptions struct {
+ // If set changes the request HTTP headers. Header values will be converted to a string.
+ Headers map[string]string `json:"headers"`
+ // Maximum number of request redirects that will be followed automatically. An error will be thrown if the number is
+ // exceeded. Defaults to `20`. Pass `0` to not follow redirects.
+ MaxRedirects *int `json:"maxRedirects"`
+ // Maximum number of times network errors should be retried. Currently only `ECONNRESET` error is retried. Does not
+ // retry based on HTTP response codes. An error will be thrown if the limit is exceeded. Defaults to `0` - no retries.
+ MaxRetries *int `json:"maxRetries"`
+ // If set changes the request method (e.g. GET or POST).
+ Method *string `json:"method"`
+ // If set changes the post data of request.
+ PostData interface{} `json:"postData"`
+ // Request timeout in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout.
+ Timeout *float64 `json:"timeout"`
+ // If set changes the request URL. New URL must have same protocol as original one.
+ URL *string `json:"url"`
+}
+
+type RouteFulfillOptions struct {
+ // Response body.
+ Body interface{} `json:"body"`
+ // If set, equals to setting `Content-Type` response header.
+ ContentType *string `json:"contentType"`
+ // Response headers. Header values will be converted to a string.
+ Headers map[string]string `json:"headers"`
+ // File path to respond with. The content type will be inferred from file extension. If `path` is a relative path,
+ // then it is resolved relative to the current working directory.
+ Path *string `json:"path"`
+ // [APIResponse] to fulfill route's request with. Individual fields of the response (such as headers) can be
+ // overridden using fulfill options.
+ Response APIResponse `json:"response"`
+ // Response status code, defaults to `200`.
+ Status *int `json:"status"`
+}
+
+type SelectorsRegisterOptions struct {
+ // Whether to run this selector engine in isolated JavaScript environment. This environment has access to the same
+ // DOM, but not any JavaScript objects from the frame's scripts. Defaults to `false`. Note that running as a content
+ // script is not guaranteed when this engine is used together with other registered engines.
+ ContentScript *bool `json:"contentScript"`
+}
+
+type TracingStartOptions struct {
+ // If specified, intermediate trace files are going to be saved into the files with the given name prefix inside the
+ // “[object Object]” directory specified in [BrowserType.Launch]. To specify the final trace zip file name, you need
+ // to pass `path` option to [Tracing.Stop] instead.
+ Name *string `json:"name"`
+ // Whether to capture screenshots during tracing. Screenshots are used to build a timeline preview.
+ Screenshots *bool `json:"screenshots"`
+ // If this option is true tracing will
+ // - capture DOM snapshot on every action
+ // - record network activity
+ Snapshots *bool `json:"snapshots"`
+ // Whether to include source files for trace actions.
+ Sources *bool `json:"sources"`
+ // Trace name to be shown in the Trace Viewer.
+ Title *string `json:"title"`
+}
+
+type TracingStartChunkOptions struct {
+ // If specified, intermediate trace files are going to be saved into the files with the given name prefix inside the
+ // “[object Object]” directory specified in [BrowserType.Launch]. To specify the final trace zip file name, you need
+ // to pass `path` option to [Tracing.StopChunk] instead.
+ Name *string `json:"name"`
+ // Trace name to be shown in the Trace Viewer.
+ Title *string `json:"title"`
+}
+
+type TracingGroupOptions struct {
+ // Specifies a custom location for the group to be shown in the trace viewer. Defaults to the location of the
+ // [Tracing.Group] call.
+ Location *TracingGroupOptionsLocation `json:"location"`
+}
+
+type WebSocketExpectEventOptions struct {
+ // Receives the event data and resolves to truthy value when the waiting should resolve.
+ Predicate interface{} `json:"predicate"`
+ // Maximum time to wait for in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The
+ // default value can be changed by using the [BrowserContext.SetDefaultTimeout].
+ Timeout *float64 `json:"timeout"`
+}
+
+type WebSocketWaitForEventOptions struct {
+ // Receives the event data and resolves to truthy value when the waiting should resolve.
+ Predicate interface{} `json:"predicate"`
+ // Maximum time to wait for in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The
+ // default value can be changed by using the [BrowserContext.SetDefaultTimeout].
+ Timeout *float64 `json:"timeout"`
+}
+
+type WebSocketRouteCloseOptions struct {
+ // Optional [close code].
+ //
+ // [close code]: https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/close#code
+ Code *int `json:"code"`
+ // Optional [close reason].
+ //
+ // [close reason]: https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/close#reason
+ Reason *string `json:"reason"`
+}
+
+type ClientCertificate struct {
+ // Exact origin that the certificate is valid for. Origin includes `https` protocol, a hostname and optionally a port.
+ Origin string `json:"origin"`
+ // Path to the file with the certificate in PEM format.
+ CertPath *string `json:"certPath"`
+ // Direct value of the certificate in PEM format.
+ Cert []byte `json:"cert"`
+ // Path to the file with the private key in PEM format.
+ KeyPath *string `json:"keyPath"`
+ // Direct value of the private key in PEM format.
+ Key []byte `json:"key"`
+ // Path to the PFX or PKCS12 encoded private key and certificate chain.
+ PfxPath *string `json:"pfxPath"`
+ // Direct value of the PFX or PKCS12 encoded private key and certificate chain.
+ Pfx []byte `json:"pfx"`
+ // Passphrase for the private key (PEM or PFX).
+ Passphrase *string `json:"passphrase"`
+}
+
+type HttpCredentials struct {
+ Username string `json:"username"`
+ Password string `json:"password"`
+ // Restrain sending http credentials on specific origin (scheme://host:port).
+ Origin *string `json:"origin"`
+ // This option only applies to the requests sent from corresponding [APIRequestContext] and does not affect requests
+ // sent from the browser. `always` - `Authorization` header with basic authentication credentials will be sent with
+ // the each API request. `'unauthorized` - the credentials are only sent when 401 (Unauthorized) response with
+ // `WWW-Authenticate` header is received. Defaults to `unauthorized`.
+ Send *HttpCredentialsSend `json:"send"`
+}
+
+type Proxy struct {
+ // Proxy to be used for all requests. HTTP and SOCKS proxies are supported, for example `http://myproxy.com:3128` or
+ // `socks5://myproxy.com:3128`. Short form `myproxy.com:3128` is considered an HTTP proxy.
+ Server string `json:"server"`
+ // Optional comma-separated domains to bypass proxy, for example `".com, chromium.org, .domain.com"`.
+ Bypass *string `json:"bypass"`
+ // Optional username to use if HTTP proxy requires authentication.
+ Username *string `json:"username"`
+ // Optional password to use if HTTP proxy requires authentication.
+ Password *string `json:"password"`
+}
+
+type Origin struct {
+ Origin string `json:"origin"`
+ LocalStorage []NameValue `json:"localStorage"`
+}
+
+type RecordVideo struct {
+ // Path to the directory to put videos into.
+ Dir string `json:"dir"`
+ // Optional dimensions of the recorded videos. If not specified the size will be equal to `viewport` scaled down to
+ // fit into 800x800. If `viewport` is not configured explicitly the video size defaults to 800x450. Actual picture of
+ // each page will be scaled down if necessary to fit the specified size.
+ Size *Size `json:"size"`
+}
+
+type OptionalStorageState struct {
+ // Cookies to set for context
+ Cookies []OptionalCookie `json:"cookies"`
+ // localStorage to set for context
+ Origins []Origin `json:"origins"`
+}
+
+type Position struct {
+ X float64 `json:"x"`
+ Y float64 `json:"y"`
+}
+
+type Margin struct {
+ // Top margin, accepts values labeled with units. Defaults to `0`.
+ Top *string `json:"top"`
+ // Right margin, accepts values labeled with units. Defaults to `0`.
+ Right *string `json:"right"`
+ // Bottom margin, accepts values labeled with units. Defaults to `0`.
+ Bottom *string `json:"bottom"`
+ // Left margin, accepts values labeled with units. Defaults to `0`.
+ Left *string `json:"left"`
+}
+
+type TracingGroupOptionsLocation struct {
+ File string `json:"file"`
+ Line *int `json:"line"`
+ Column *int `json:"column"`
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/glob.go b/vendor/github.com/playwright-community/playwright-go/glob.go
new file mode 100644
index 0000000..77deba3
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/glob.go
@@ -0,0 +1,170 @@
+package playwright
+
+import (
+ "net/url"
+ "regexp"
+ "strconv"
+ "strings"
+)
+
+var escapedChars = map[rune]bool{
+ '$': true,
+ '^': true,
+ '+': true,
+ '.': true,
+ '*': true,
+ '(': true,
+ ')': true,
+ '|': true,
+ '\\': true,
+ '?': true,
+ '{': true,
+ '}': true,
+ '[': true,
+ ']': true,
+}
+
+func globMustToRegex(glob string) *regexp.Regexp {
+ tokens := []string{"^"}
+ inGroup := false
+
+ for i := 0; i < len(glob); i++ {
+ c := rune(glob[i])
+ if c == '\\' && i+1 < len(glob) {
+ char := rune(glob[i+1])
+ if _, ok := escapedChars[char]; ok {
+ tokens = append(tokens, "\\"+string(char))
+ } else {
+ tokens = append(tokens, string(char))
+ }
+ i++
+ } else if c == '*' {
+ beforeDeep := rune(0)
+ if i > 0 {
+ beforeDeep = rune(glob[i-1])
+ }
+ starCount := 1
+ for i+1 < len(glob) && glob[i+1] == '*' {
+ starCount++
+ i++
+ }
+ afterDeep := rune(0)
+ if i+1 < len(glob) {
+ afterDeep = rune(glob[i+1])
+ }
+ isDeep := starCount > 1 && (beforeDeep == '/' || beforeDeep == 0) && (afterDeep == '/' || afterDeep == 0)
+ if isDeep {
+ tokens = append(tokens, "((?:[^/]*(?:/|$))*)")
+ i++
+ } else {
+ tokens = append(tokens, "([^/]*)")
+ }
+ } else {
+ switch c {
+ case '{':
+ inGroup = true
+ tokens = append(tokens, "(")
+ case '}':
+ inGroup = false
+ tokens = append(tokens, ")")
+ case ',':
+ if inGroup {
+ tokens = append(tokens, "|")
+ } else {
+ tokens = append(tokens, "\\"+string(c))
+ }
+ default:
+ if _, ok := escapedChars[c]; ok {
+ tokens = append(tokens, "\\"+string(c))
+ } else {
+ tokens = append(tokens, string(c))
+ }
+ }
+ }
+ }
+
+ tokens = append(tokens, "$")
+ return regexp.MustCompile(strings.Join(tokens, ""))
+}
+
+func resolveGlobToRegex(baseURL *string, glob string, isWebSocketUrl bool) *regexp.Regexp {
+ if isWebSocketUrl {
+ baseURL = toWebSocketBaseURL(baseURL)
+ }
+ glob = resolveGlobBase(baseURL, glob)
+ return globMustToRegex(glob)
+}
+
+func resolveGlobBase(baseURL *string, match string) string {
+ if strings.HasPrefix(match, "*") {
+ return match
+ }
+
+ tokenMap := make(map[string]string)
+ mapToken := func(original string, replacement string) string {
+ if len(original) == 0 {
+ return ""
+ }
+ tokenMap[replacement] = original
+ return replacement
+ }
+ // Escaped `\\?` behaves the same as `?` in our glob patterns.
+ match = strings.ReplaceAll(match, `\\?`, "?")
+ // Glob symbols may be escaped in the URL and some of them such as ? affect resolution,
+ // so we replace them with safe components first.
+ relativePath := strings.Split(match, "/")
+ for i, token := range relativePath {
+ if token == "." || token == ".." || token == "" {
+ continue
+ }
+ // Handle special case of http*://, note that the new schema has to be
+ // a web schema so that slashes are properly inserted after domain.
+ if i == 0 && strings.HasSuffix(token, ":") {
+ relativePath[i] = mapToken(token, "http:")
+ } else {
+ questionIndex := strings.Index(token, "?")
+ if questionIndex == -1 {
+ relativePath[i] = mapToken(token, "$_"+strconv.Itoa(i)+"_$")
+ } else {
+ newPrefix := mapToken(token[:questionIndex], "$_"+strconv.Itoa(i)+"_$")
+ newSuffix := mapToken(token[questionIndex:], "?$"+strconv.Itoa(i)+"_$")
+ relativePath[i] = newPrefix + newSuffix
+ }
+ }
+ }
+ resolved := constructURLBasedOnBaseURL(baseURL, strings.Join(relativePath, "/"))
+ for token, original := range tokenMap {
+ resolved = strings.ReplaceAll(resolved, token, original)
+ }
+ return resolved
+}
+
+func constructURLBasedOnBaseURL(baseURL *string, givenURL string) string {
+ u, err := url.Parse(givenURL)
+ if err != nil {
+ return givenURL
+ }
+ if baseURL != nil {
+ base, err := url.Parse(*baseURL)
+ if err != nil {
+ return givenURL
+ }
+ u = base.ResolveReference(u)
+ }
+ if u.Path == "" { // In Node.js, new URL('http://localhost') returns 'http://localhost/'.
+ u.Path = "/"
+ }
+ return u.String()
+}
+
+func toWebSocketBaseURL(baseURL *string) *string {
+ if baseURL == nil {
+ return nil
+ }
+
+ // Allow http(s) baseURL to match ws(s) urls.
+ re := regexp.MustCompile(`(?m)^http(s?://)`)
+ wsBaseURL := re.ReplaceAllString(*baseURL, "ws$1")
+
+ return &wsBaseURL
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/har_router.go b/vendor/github.com/playwright-community/playwright-go/har_router.go
new file mode 100644
index 0000000..0c95d53
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/har_router.go
@@ -0,0 +1,110 @@
+package playwright
+
+import (
+ "errors"
+)
+
+type harRouter struct {
+ localUtils *localUtilsImpl
+ harId string
+ notFoundAction HarNotFound
+ urlOrPredicate interface{}
+ err error
+}
+
+func (r *harRouter) addContextRoute(context BrowserContext) error {
+ if r.err != nil {
+ return r.err
+ }
+ err := context.Route(r.urlOrPredicate, func(route Route) {
+ err := r.handle(route)
+ if err != nil {
+ logger.Error("Error handling context route", "error", err)
+ }
+ })
+ if err != nil {
+ return err
+ }
+ return r.err
+}
+
+func (r *harRouter) addPageRoute(page Page) error {
+ if r.err != nil {
+ return r.err
+ }
+ err := page.Route(r.urlOrPredicate, func(route Route) {
+ err := r.handle(route)
+ if err != nil {
+ logger.Error("Error handling page route", "error", err)
+ }
+ })
+ if err != nil {
+ return err
+ }
+ return r.err
+}
+
+func (r *harRouter) dispose() {
+ go r.localUtils.HarClose(r.harId)
+}
+
+func (r *harRouter) handle(route Route) error {
+ if r.err != nil {
+ return r.err
+ }
+ request := route.Request()
+ postData, err := request.PostDataBuffer()
+ if err != nil {
+ return err
+ }
+ response, err := r.localUtils.HarLookup(harLookupOptions{
+ HarId: r.harId,
+ URL: request.URL(),
+ Method: request.Method(),
+ Headers: request.Headers(),
+ IsNavigationRequest: request.IsNavigationRequest(),
+ PostData: postData,
+ })
+ if err != nil {
+ return err
+ }
+ switch response.Action {
+ case "redirect":
+ if response.RedirectURL == nil {
+ return errors.New("redirect url is null")
+ }
+ return route.(*routeImpl).redirectedNavigationRequest(*response.RedirectURL)
+ case "fulfill":
+ if response.Body == nil {
+ return errors.New("fulfill body is null")
+ }
+ return route.Fulfill(RouteFulfillOptions{
+ Body: *response.Body,
+ Status: response.Status,
+ Headers: deserializeNameAndValueToMap(response.Headers),
+ })
+ case "error":
+ logger.Error("har action error", "error", *response.Message)
+ fallthrough
+ case "noentry":
+ }
+ if r.notFoundAction == *HarNotFoundAbort {
+ return route.Abort()
+ }
+ return route.Fallback()
+}
+
+func newHarRouter(localUtils *localUtilsImpl, file string, notFoundAction HarNotFound, urlOrPredicate interface{}) *harRouter {
+ harId, err := localUtils.HarOpen(file)
+ var url interface{} = "**/*"
+ if urlOrPredicate != nil {
+ url = urlOrPredicate
+ }
+ return &harRouter{
+ localUtils: localUtils,
+ harId: harId,
+ notFoundAction: notFoundAction,
+ urlOrPredicate: url,
+ err: err,
+ }
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/helpers.go b/vendor/github.com/playwright-community/playwright-go/helpers.go
new file mode 100644
index 0000000..b2244f1
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/helpers.go
@@ -0,0 +1,628 @@
+package playwright
+
+import (
+ "errors"
+ "fmt"
+ "reflect"
+ "regexp"
+ "strings"
+ "sync"
+ "sync/atomic"
+
+ mapset "github.com/deckarep/golang-set/v2"
+)
+
+type (
+ routeHandler = func(Route)
+)
+
+func skipFieldSerialization(val reflect.Value) bool {
+ typ := val.Type()
+ return (typ.Kind() == reflect.Ptr ||
+ typ.Kind() == reflect.Interface ||
+ typ.Kind() == reflect.Map ||
+ typ.Kind() == reflect.Slice) && val.IsNil() || (val.Kind() == reflect.Interface && val.Elem().Kind() == reflect.Ptr && val.Elem().IsNil())
+}
+
+func transformStructValues(in interface{}) interface{} {
+ v := reflect.ValueOf(in)
+ if v.Kind() == reflect.Ptr {
+ v = v.Elem()
+ }
+ if _, ok := in.(*channel); ok {
+ return in
+ }
+ if v.Kind() == reflect.Map || v.Kind() == reflect.Struct {
+ return transformStructIntoMapIfNeeded(in)
+ }
+ if v.Kind() == reflect.Slice {
+ outSlice := []interface{}{}
+ for i := 0; i < v.Len(); i++ {
+ if !skipFieldSerialization(v.Index(i)) {
+ outSlice = append(outSlice, transformStructValues(v.Index(i).Interface()))
+ }
+ }
+ return outSlice
+ }
+ if v.Interface() == Null() || (v.Kind() == reflect.String && v.String() == Null().(string)) {
+ return "null"
+ }
+ return in
+}
+
+func transformStructIntoMapIfNeeded(inStruct interface{}) map[string]interface{} {
+ out := make(map[string]interface{})
+ v := reflect.ValueOf(inStruct)
+ if v.Kind() == reflect.Ptr {
+ v = v.Elem()
+ }
+ typ := v.Type()
+ if v.Kind() == reflect.Struct {
+ // Merge into the base map by the JSON struct tag
+ for i := 0; i < v.NumField(); i++ {
+ fi := typ.Field(i)
+ // Skip the values when the field is a pointer (like *string) and nil.
+ if fi.IsExported() && !skipFieldSerialization(v.Field(i)) {
+ // We use the JSON struct fields for getting the original names
+ // out of the field.
+ tagv := fi.Tag.Get("json")
+ key := strings.Split(tagv, ",")[0]
+ if key == "" {
+ key = fi.Name
+ }
+ out[key] = transformStructValues(v.Field(i).Interface())
+ }
+ }
+ } else if v.Kind() == reflect.Map {
+ // Merge into the base map
+ for _, key := range v.MapKeys() {
+ if !skipFieldSerialization(v.MapIndex(key)) {
+ out[key.String()] = transformStructValues(v.MapIndex(key).Interface())
+ }
+ }
+ }
+ return out
+}
+
+// transformOptions handles the parameter data transformation
+func transformOptions(options ...interface{}) map[string]interface{} {
+ var base map[string]interface{}
+ var option interface{}
+ // Case 1: No options are given
+ if len(options) == 0 {
+ return make(map[string]interface{})
+ }
+ if len(options) == 1 {
+ // Case 2: a single value (either struct or map) is given.
+ base = make(map[string]interface{})
+ option = options[0]
+ } else if len(options) == 2 {
+ // Case 3: two values are given. The first one needs to be transformed
+ // to a map, the sencond one will be then get merged into the first
+ // base map.
+ if reflect.ValueOf(options[0]).Kind() != reflect.Map {
+ base = transformOptions(options[0])
+ } else {
+ base = transformStructIntoMapIfNeeded(options[0])
+ }
+ option = options[1]
+ }
+ v := reflect.ValueOf(option)
+ if v.Kind() == reflect.Slice {
+ if v.Len() == 0 {
+ return base
+ }
+ option = v.Index(0).Interface()
+ }
+
+ if option == nil {
+ return base
+ }
+ v = reflect.ValueOf(option)
+
+ if v.Kind() == reflect.Ptr {
+ v = v.Elem()
+ }
+
+ optionMap := transformStructIntoMapIfNeeded(v.Interface())
+ for key, value := range optionMap {
+ base[key] = value
+ }
+ return base
+}
+
+func remapValue(inMapValue reflect.Value, outStructValue reflect.Value) {
+ switch outStructValue.Type().Kind() {
+ case reflect.Bool:
+ outStructValue.SetBool(inMapValue.Bool())
+ case reflect.String:
+ outStructValue.SetString(inMapValue.String())
+ case reflect.Float64:
+ outStructValue.SetFloat(inMapValue.Float())
+ case reflect.Int:
+ outStructValue.SetInt(int64(inMapValue.Float()))
+ case reflect.Slice:
+ outStructValue.Set(reflect.MakeSlice(outStructValue.Type(), inMapValue.Len(), inMapValue.Cap()))
+ for i := 0; i < inMapValue.Len(); i++ {
+ remapValue(inMapValue.Index(i).Elem(), outStructValue.Index(i))
+ }
+ case reflect.Struct:
+ structTyp := outStructValue.Type()
+ for i := 0; i < outStructValue.NumField(); i++ {
+ fi := structTyp.Field(i)
+ key := strings.Split(fi.Tag.Get("json"), ",")[0]
+ structField := outStructValue.Field(i)
+ structFieldDeref := outStructValue.Field(i)
+ if structField.Type().Kind() == reflect.Ptr {
+ structField.Set(reflect.New(structField.Type().Elem()))
+ structFieldDeref = structField.Elem()
+ }
+ for _, e := range inMapValue.MapKeys() {
+ if key == e.String() {
+ value := inMapValue.MapIndex(e)
+ remapValue(value.Elem(), structFieldDeref)
+ }
+ }
+ }
+ default:
+ panic(inMapValue.Interface())
+ }
+}
+
+func remapMapToStruct(inputMap interface{}, outStruct interface{}) {
+ remapValue(reflect.ValueOf(inputMap), reflect.ValueOf(outStruct).Elem())
+}
+
+type urlMatcher struct {
+ raw interface{}
+ pattern *regexp.Regexp
+ matchFn func(url string) bool
+}
+
+func newURLMatcher(urlOrPredicate interface{}, baseURL *string, isWsUrl ...bool) *urlMatcher {
+ switch v := urlOrPredicate.(type) {
+ case *regexp.Regexp:
+ return &urlMatcher{pattern: v, raw: urlOrPredicate}
+ case string:
+ return &urlMatcher{
+ pattern: resolveGlobToRegex(baseURL, v, len(isWsUrl) > 0 && isWsUrl[0]),
+ raw: urlOrPredicate,
+ }
+ }
+ fn, ok := urlOrPredicate.(func(string) bool)
+ if ok {
+ return &urlMatcher{
+ matchFn: fn,
+ raw: urlOrPredicate,
+ }
+ }
+ panic(fmt.Errorf("invalid urlOrPredicate: %v", urlOrPredicate))
+}
+
+func (u *urlMatcher) Matches(url string) bool {
+ if u.matchFn != nil {
+ return u.matchFn(url)
+ }
+ if u.pattern != nil {
+ return u.pattern.MatchString(url)
+ }
+ return false
+}
+
+// SameWith compares String() if urlOrPredicate is *regexp.Regexp
+func (u *urlMatcher) SameWith(urlOrPredicate interface{}) bool {
+ switch v := urlOrPredicate.(type) {
+ case *regexp.Regexp:
+ return u.pattern.String() == v.String()
+ default:
+ return u.raw == urlOrPredicate
+ }
+}
+
+type routeHandlerInvocation struct {
+ route Route
+ complete chan bool
+}
+
+type routeHandlerEntry struct {
+ matcher *urlMatcher
+ handler routeHandler
+ times int
+ count int32
+ ignoreErrors *atomic.Bool
+ activeInvocations mapset.Set[*routeHandlerInvocation]
+}
+
+func (r *routeHandlerEntry) Matches(url string) bool {
+ return r.matcher.Matches(url)
+}
+
+func (r *routeHandlerEntry) Handle(route Route) chan bool {
+ handlerInvocation := &routeHandlerInvocation{
+ route: route,
+ complete: make(chan bool, 1),
+ }
+ r.activeInvocations.Add(handlerInvocation)
+
+ defer func() {
+ handlerInvocation.complete <- true
+ r.activeInvocations.Remove(handlerInvocation)
+ }()
+ defer func() {
+ // If the handler was stopped (without waiting for completion), we ignore all exceptions.
+ if r.ignoreErrors.Load() {
+ _ = recover()
+ route.(*routeImpl).reportHandled(false)
+ } else {
+ e := recover()
+ if e != nil {
+ err, ok := e.(error)
+ if ok && errors.Is(err, ErrTargetClosed) {
+ panic(fmt.Errorf("\"%w\" while running route callback.\nConsider awaiting `page.UnrouteAll(playwright.PageUnrouteAllOptions{Behavior: playwright.UnrouteBehaviorIgnoreErrors})`\nbefore the end of the test to ignore remaining routes in flight.", err))
+ }
+ panic(e)
+ }
+ }
+ }()
+
+ return r.handleInternal(route)
+}
+
+func (r *routeHandlerEntry) Stop(behavior string) {
+ // When a handler is manually unrouted or its page/context is closed we either
+ // - wait for the current handler invocations to finish
+ // - or do not wait, if the user opted out of it, but swallow all exceptions
+ // that happen after the unroute/close.
+ if behavior == string(*UnrouteBehaviorIgnoreErrors) {
+ r.ignoreErrors.Store(true)
+ } else {
+ wg := &sync.WaitGroup{}
+ r.activeInvocations.Each(func(activation *routeHandlerInvocation) bool {
+ if !activation.route.(*routeImpl).didThrow {
+ wg.Add(1)
+ go func(complete chan bool) {
+ <-complete
+ wg.Done()
+ }(activation.complete)
+ }
+ return false
+ })
+ wg.Wait()
+ }
+}
+
+func (r *routeHandlerEntry) handleInternal(route Route) chan bool {
+ handled := route.(*routeImpl).startHandling()
+ atomic.AddInt32(&r.count, 1)
+ r.handler(route)
+ return handled
+}
+
+func (r *routeHandlerEntry) WillExceed() bool {
+ if r.times == 0 {
+ return false
+ }
+ return int(atomic.LoadInt32(&r.count)+1) >= r.times
+}
+
+func newRouteHandlerEntry(matcher *urlMatcher, handler routeHandler, times ...int) *routeHandlerEntry {
+ n := 0
+ if len(times) > 0 {
+ n = times[0]
+ }
+ return &routeHandlerEntry{
+ matcher: matcher,
+ handler: handler,
+ times: n,
+ count: 0,
+ ignoreErrors: &atomic.Bool{},
+ activeInvocations: mapset.NewSet[*routeHandlerInvocation](),
+ }
+}
+
+func prepareInterceptionPatterns(handlers []*routeHandlerEntry) []map[string]interface{} {
+ patterns := []map[string]interface{}{}
+ all := false
+ for _, h := range handlers {
+ switch h.matcher.raw.(type) {
+ case *regexp.Regexp:
+ pattern, flags := convertRegexp(h.matcher.raw.(*regexp.Regexp))
+ patterns = append(patterns, map[string]interface{}{
+ "regexSource": pattern,
+ "regexFlags": flags,
+ })
+ case string:
+ patterns = append(patterns, map[string]interface{}{
+ "glob": h.matcher.raw.(string),
+ })
+ default:
+ all = true
+ }
+ }
+ if all {
+ return []map[string]interface{}{
+ {
+ "glob": "**/*",
+ },
+ }
+ }
+ return patterns
+}
+
+const defaultTimeout = 30 * 1000
+
+type timeoutSettings struct {
+ sync.RWMutex
+ parent *timeoutSettings
+ defaultTimeout *float64
+ defaultNavigationTimeout *float64
+}
+
+func (t *timeoutSettings) SetDefaultTimeout(timeout *float64) {
+ t.Lock()
+ defer t.Unlock()
+ t.defaultTimeout = timeout
+}
+
+func (t *timeoutSettings) DefaultTimeout() *float64 {
+ t.RLock()
+ defer t.RUnlock()
+ return t.defaultTimeout
+}
+
+func (t *timeoutSettings) Timeout(timeout ...float64) float64 {
+ t.RLock()
+ defer t.RUnlock()
+ if len(timeout) == 1 {
+ return timeout[0]
+ }
+ if t.defaultTimeout != nil {
+ return *t.defaultTimeout
+ }
+ if t.parent != nil {
+ return t.parent.Timeout()
+ }
+ return defaultTimeout
+}
+
+func (t *timeoutSettings) DefaultNavigationTimeout() *float64 {
+ t.RLock()
+ defer t.RUnlock()
+ return t.defaultNavigationTimeout
+}
+
+func (t *timeoutSettings) SetDefaultNavigationTimeout(navigationTimeout *float64) {
+ t.Lock()
+ defer t.Unlock()
+ t.defaultNavigationTimeout = navigationTimeout
+}
+
+func (t *timeoutSettings) NavigationTimeout() float64 {
+ t.RLock()
+ defer t.RUnlock()
+ if t.defaultNavigationTimeout != nil {
+ return *t.defaultNavigationTimeout
+ }
+ if t.parent != nil {
+ return t.parent.NavigationTimeout()
+ }
+ return defaultTimeout
+}
+
+func newTimeoutSettings(parent *timeoutSettings) *timeoutSettings {
+ return &timeoutSettings{
+ parent: parent,
+ defaultTimeout: nil,
+ defaultNavigationTimeout: nil,
+ }
+}
+
+// SelectOptionValues is the option struct for ElementHandle.Select() etc.
+type SelectOptionValues struct {
+ ValuesOrLabels *[]string
+ Values *[]string
+ Indexes *[]int
+ Labels *[]string
+ Elements *[]ElementHandle
+}
+
+func convertSelectOptionSet(values SelectOptionValues) map[string]interface{} {
+ out := make(map[string]interface{})
+ if values == (SelectOptionValues{}) {
+ return out
+ }
+
+ var o []map[string]interface{}
+ if values.ValuesOrLabels != nil {
+ for _, v := range *values.ValuesOrLabels {
+ m := map[string]interface{}{"valueOrLabel": v}
+ o = append(o, m)
+ }
+ }
+ if values.Values != nil {
+ for _, v := range *values.Values {
+ m := map[string]interface{}{"value": v}
+ o = append(o, m)
+ }
+ }
+ if values.Indexes != nil {
+ for _, i := range *values.Indexes {
+ m := map[string]interface{}{"index": i}
+ o = append(o, m)
+ }
+ }
+ if values.Labels != nil {
+ for _, l := range *values.Labels {
+ m := map[string]interface{}{"label": l}
+ o = append(o, m)
+ }
+ }
+ if o != nil {
+ out["options"] = o
+ }
+
+ var e []*channel
+ if values.Elements != nil {
+ for _, eh := range *values.Elements {
+ e = append(e, eh.(*elementHandleImpl).channel)
+ }
+ }
+ if e != nil {
+ out["elements"] = e
+ }
+
+ return out
+}
+
+func unroute(inRoutes []*routeHandlerEntry, url interface{}, handlers ...routeHandler) ([]*routeHandlerEntry, []*routeHandlerEntry, error) {
+ var handler routeHandler
+ if len(handlers) == 1 {
+ handler = handlers[0]
+ }
+ handlerPtr := reflect.ValueOf(handler).Pointer()
+
+ removed := make([]*routeHandlerEntry, 0)
+ remaining := make([]*routeHandlerEntry, 0)
+
+ for _, route := range inRoutes {
+ routeHandlerPtr := reflect.ValueOf(route.handler).Pointer()
+ // note: compare regex expression if url is a regexp, not pointer
+ if !route.matcher.SameWith(url) ||
+ (handler != nil && routeHandlerPtr != handlerPtr) {
+ remaining = append(remaining, route)
+ } else {
+ removed = append(removed, route)
+ }
+ }
+
+ return removed, remaining, nil
+}
+
+func serializeMapToNameAndValue(headers map[string]string) []map[string]string {
+ serialized := make([]map[string]string, 0)
+ for name, value := range headers {
+ serialized = append(serialized, map[string]string{
+ "name": name,
+ "value": value,
+ })
+ }
+ return serialized
+}
+
+// assignStructFields assigns fields from src to dest,
+//
+// omitExtra determines whether to omit src's extra fields
+func assignStructFields(dest, src interface{}, omitExtra bool) error {
+ destValue := reflect.ValueOf(dest)
+ if destValue.Kind() != reflect.Ptr || destValue.IsNil() {
+ return fmt.Errorf("dest must be a non-nil pointer")
+ }
+ destValue = destValue.Elem()
+ if destValue.Kind() != reflect.Struct {
+ return fmt.Errorf("dest must be a struct")
+ }
+
+ srcValue := reflect.ValueOf(src)
+ if srcValue.Kind() == reflect.Ptr {
+ srcValue = srcValue.Elem()
+ }
+ if srcValue.Kind() != reflect.Struct {
+ return fmt.Errorf("src must be a struct")
+ }
+
+ for i := 0; i < destValue.NumField(); i++ {
+ destField := destValue.Field(i)
+ destFieldType := destField.Type()
+ destFieldName := destValue.Type().Field(i).Name
+
+ if srcField := srcValue.FieldByName(destFieldName); srcField.IsValid() && srcField.Type() != destFieldType {
+ return fmt.Errorf("mismatched field type for field %s", destFieldName)
+ } else if srcField.IsValid() {
+ destField.Set(srcField)
+ }
+ }
+
+ if !omitExtra {
+ for i := 0; i < srcValue.NumField(); i++ {
+ srcFieldName := srcValue.Type().Field(i).Name
+
+ if destField := destValue.FieldByName(srcFieldName); !destField.IsValid() {
+ return fmt.Errorf("extra field %s in src", srcFieldName)
+ }
+ }
+ }
+
+ return nil
+}
+
+func deserializeNameAndValueToMap(headersArray []map[string]string) map[string]string {
+ unserialized := make(map[string]string)
+ for _, item := range headersArray {
+ unserialized[item["name"]] = item["value"]
+ }
+ return unserialized
+}
+
+type recordHarOptions struct {
+ Path string `json:"path"`
+ Content *HarContentPolicy `json:"content,omitempty"`
+ Mode *HarMode `json:"mode,omitempty"`
+ UrlGlob *string `json:"urlGlob,omitempty"`
+ UrlRegexSource *string `json:"urlRegexSource,omitempty"`
+ UrlRegexFlags *string `json:"urlRegexFlags,omitempty"`
+}
+
+type recordHarInputOptions struct {
+ Path string
+ URL interface{}
+ Mode *HarMode
+ Content *HarContentPolicy
+ OmitContent *bool
+}
+
+type harRecordingMetadata struct {
+ Path string
+ Content *HarContentPolicy
+}
+
+func prepareRecordHarOptions(option recordHarInputOptions) recordHarOptions {
+ out := recordHarOptions{
+ Path: option.Path,
+ }
+ if option.URL != nil {
+ switch option.URL.(type) {
+ case *regexp.Regexp:
+ pattern, flags := convertRegexp(option.URL.(*regexp.Regexp))
+ out.UrlRegexSource = String(pattern)
+ out.UrlRegexFlags = String(flags)
+ case string:
+ out.UrlGlob = String(option.URL.(string))
+ }
+ }
+ if option.Mode != nil {
+ out.Mode = option.Mode
+ }
+ if option.Content != nil {
+ out.Content = option.Content
+ } else if option.OmitContent != nil && *option.OmitContent {
+ out.Content = HarContentPolicyOmit
+ }
+ return out
+}
+
+type safeValue[T any] struct {
+ sync.Mutex
+ v T
+}
+
+func (s *safeValue[T]) Set(v T) {
+ s.Lock()
+ defer s.Unlock()
+ s.v = v
+}
+
+func (s *safeValue[T]) Get() T {
+ s.Lock()
+ defer s.Unlock()
+ return s.v
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/input.go b/vendor/github.com/playwright-community/playwright-go/input.go
new file mode 100644
index 0000000..d6e4ba4
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/input.go
@@ -0,0 +1,117 @@
+package playwright
+
+type mouseImpl struct {
+ channel *channel
+}
+
+func newMouse(channel *channel) *mouseImpl {
+ return &mouseImpl{
+ channel: channel,
+ }
+}
+
+func (m *mouseImpl) Move(x float64, y float64, options ...MouseMoveOptions) error {
+ _, err := m.channel.Send("mouseMove", map[string]interface{}{
+ "x": x,
+ "y": y,
+ }, options)
+ return err
+}
+
+func (m *mouseImpl) Down(options ...MouseDownOptions) error {
+ _, err := m.channel.Send("mouseDown", options)
+ return err
+}
+
+func (m *mouseImpl) Up(options ...MouseUpOptions) error {
+ _, err := m.channel.Send("mouseUp", options)
+ return err
+}
+
+func (m *mouseImpl) Click(x, y float64, options ...MouseClickOptions) error {
+ _, err := m.channel.Send("mouseClick", map[string]interface{}{
+ "x": x,
+ "y": y,
+ }, options)
+ return err
+}
+
+func (m *mouseImpl) Dblclick(x, y float64, options ...MouseDblclickOptions) error {
+ var option MouseDblclickOptions
+ if len(options) == 1 {
+ option = options[0]
+ }
+ return m.Click(x, y, MouseClickOptions{
+ ClickCount: Int(2),
+ Button: option.Button,
+ Delay: option.Delay,
+ })
+}
+
+func (m *mouseImpl) Wheel(deltaX, deltaY float64) error {
+ _, err := m.channel.Send("mouseWheel", map[string]interface{}{
+ "deltaX": deltaX,
+ "deltaY": deltaY,
+ })
+ return err
+}
+
+type keyboardImpl struct {
+ channel *channel
+}
+
+func newKeyboard(channel *channel) *keyboardImpl {
+ return &keyboardImpl{
+ channel: channel,
+ }
+}
+
+func (m *keyboardImpl) Down(key string) error {
+ _, err := m.channel.Send("keyboardDown", map[string]interface{}{
+ "key": key,
+ })
+ return err
+}
+
+func (m *keyboardImpl) Up(key string) error {
+ _, err := m.channel.Send("keyboardUp", map[string]interface{}{
+ "key": key,
+ })
+ return err
+}
+
+func (m *keyboardImpl) InsertText(text string) error {
+ _, err := m.channel.Send("keyboardInsertText", map[string]interface{}{
+ "text": text,
+ })
+ return err
+}
+
+func (m *keyboardImpl) Type(text string, options ...KeyboardTypeOptions) error {
+ _, err := m.channel.Send("keyboardInsertText", map[string]interface{}{
+ "text": text,
+ }, options)
+ return err
+}
+
+func (m *keyboardImpl) Press(key string, options ...KeyboardPressOptions) error {
+ _, err := m.channel.Send("keyboardPress", map[string]interface{}{
+ "key": key,
+ }, options)
+ return err
+}
+
+type touchscreenImpl struct {
+ channel *channel
+}
+
+func newTouchscreen(channel *channel) *touchscreenImpl {
+ return &touchscreenImpl{
+ channel: channel,
+ }
+}
+
+func (t *touchscreenImpl) Tap(x int, y int) error {
+ _, err := t.channel.Send("touchscreenTap", map[string]interface{}{"x": x, "y": y})
+ return err
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/input_files_helper.go b/vendor/github.com/playwright-community/playwright-go/input_files_helper.go
new file mode 100644
index 0000000..3318cb5
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/input_files_helper.go
@@ -0,0 +1,202 @@
+package playwright
+
+import (
+ "encoding/base64"
+ "errors"
+ "fmt"
+ "os"
+ "path/filepath"
+)
+
+const fileSizeLimitInBytes = 50 * 1024 * 1024
+
+var ErrInputFilesSizeExceeded = errors.New("Cannot set buffer larger than 50Mb, please write it to a file and pass its path instead.")
+
+type inputFiles struct {
+ Selector *string `json:"selector,omitempty"`
+ Streams []*channel `json:"streams,omitempty"` // writableStream
+ LocalPaths []string `json:"localPaths,omitempty"`
+ Payloads []map[string]string `json:"payloads,omitempty"`
+ LocalDirectory *string `json:"localDirectory,omitempty"`
+ DirectoryStream *channel `json:"directoryStream,omitempty"`
+}
+
+type fileItem struct {
+ LastModifiedMs *int64 `json:"lastModifiedMs,omitempty"`
+ Name string `json:"name"`
+}
+
+// convertInputFiles converts files to proper format for Playwright
+//
+// - files should be one of: string, []string, InputFile, []InputFile,
+// string: local file path
+func convertInputFiles(files interface{}, context *browserContextImpl) (*inputFiles, error) {
+ var (
+ converted = &inputFiles{}
+ paths []string
+ )
+ switch items := files.(type) {
+ case InputFile:
+ if sizeOfInputFiles([]InputFile{items}) > fileSizeLimitInBytes {
+ return nil, ErrInputFilesSizeExceeded
+ }
+ converted.Payloads = normalizeFilePayloads([]InputFile{items})
+ case []InputFile:
+ if sizeOfInputFiles(items) > fileSizeLimitInBytes {
+ return nil, ErrInputFilesSizeExceeded
+ }
+ converted.Payloads = normalizeFilePayloads(items)
+ case string: // local file path
+ paths = []string{items}
+ case []string:
+ paths = items
+ default:
+ return nil, errors.New("files should be one of: string, []string, InputFile, []InputFile")
+ }
+
+ localPaths, localDir, err := resolvePathsAndDirectoryForInputFiles(paths)
+ if err != nil {
+ return nil, err
+ }
+
+ if !context.connection.isRemote {
+ converted.LocalPaths = localPaths
+ converted.LocalDirectory = localDir
+ return converted, nil
+ }
+
+ // remote
+ params := map[string]interface{}{
+ "items": []fileItem{},
+ }
+ allFiles := localPaths
+ if localDir != nil {
+ params["rootDirName"] = filepath.Base(*localDir)
+ allFiles, err = listFiles(*localDir)
+ if err != nil {
+ return nil, err
+ }
+ }
+ for _, file := range allFiles {
+ lastModifiedMs, err := getFileLastModifiedMs(file)
+ if err != nil {
+ return nil, fmt.Errorf("failed to get last modified time of %s: %w", file, err)
+ }
+ filename := filepath.Base(file)
+ if localDir != nil {
+ var err error
+ filename, err = filepath.Rel(*localDir, file)
+ if err != nil {
+ return nil, err
+ }
+ }
+ params["items"] = append(params["items"].([]fileItem), fileItem{
+ LastModifiedMs: &lastModifiedMs,
+ Name: filename,
+ })
+ }
+
+ ret, err := context.connection.WrapAPICall(func() (interface{}, error) {
+ return context.channel.SendReturnAsDict("createTempFiles", params)
+ }, true)
+ if err != nil {
+ return nil, err
+ }
+ result := ret.(map[string]interface{})
+
+ streams := make([]*channel, 0)
+ items := result["writableStreams"].([]interface{})
+ for i := 0; i < len(allFiles); i++ {
+ stream := fromChannel(items[i]).(*writableStream)
+ if err := stream.Copy(allFiles[i]); err != nil {
+ return nil, err
+ }
+ streams = append(streams, stream.channel)
+ }
+
+ if result["rootDir"] != nil {
+ converted.DirectoryStream = result["rootDir"].(*channel)
+ } else {
+ converted.Streams = streams
+ }
+
+ return converted, nil
+}
+
+func getFileLastModifiedMs(path string) (int64, error) {
+ info, err := os.Stat(path)
+ if err != nil {
+ return 0, err
+ }
+ if info.IsDir() {
+ return 0, fmt.Errorf("%s is a directory", path)
+ }
+ return info.ModTime().UnixMilli(), nil
+}
+
+func sizeOfInputFiles(files []InputFile) int {
+ size := 0
+ for _, file := range files {
+ size += len(file.Buffer)
+ }
+ return size
+}
+
+func normalizeFilePayloads(files []InputFile) []map[string]string {
+ out := make([]map[string]string, 0)
+ for _, file := range files {
+ out = append(out, map[string]string{
+ "name": file.Name,
+ "mimeType": file.MimeType,
+ "buffer": base64.StdEncoding.EncodeToString(file.Buffer),
+ })
+ }
+ return out
+}
+
+func resolvePathsAndDirectoryForInputFiles(items []string) (localPaths []string, localDirectory *string, e error) {
+ for _, item := range items {
+ abspath, err := filepath.Abs(item)
+ if err != nil {
+ e = err
+ return
+ }
+ // if the path is a directory
+ if info, err := os.Stat(abspath); err == nil {
+ if info.IsDir() {
+ if localDirectory != nil {
+ e = errors.New("Multiple directories are not supported")
+ return
+ }
+ localDirectory = &abspath
+ } else {
+ if localPaths == nil {
+ localPaths = []string{abspath}
+ } else {
+ localPaths = append(localPaths, abspath)
+ }
+ }
+ } else {
+ e = err
+ return
+ }
+ }
+ if localPaths != nil && localDirectory != nil {
+ e = errors.New("File paths must be all files or a single directory")
+ }
+ return
+}
+
+func listFiles(dir string) ([]string, error) {
+ var files []string
+ err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
+ if err != nil {
+ return err
+ }
+ if !info.IsDir() {
+ files = append(files, path)
+ }
+ return nil
+ })
+ return files, err
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/internal/safe/map.go b/vendor/github.com/playwright-community/playwright-go/internal/safe/map.go
new file mode 100644
index 0000000..93a8800
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/internal/safe/map.go
@@ -0,0 +1,90 @@
+package safe
+
+import (
+ "maps"
+ "sync"
+)
+
+// SyncMap is a thread-safe map
+type SyncMap[K comparable, V any] struct {
+ sync.RWMutex
+ m map[K]V
+}
+
+// NewSyncMap creates a new thread-safe map
+func NewSyncMap[K comparable, V any]() *SyncMap[K, V] {
+ return &SyncMap[K, V]{
+ m: make(map[K]V),
+ }
+}
+
+func (m *SyncMap[K, V]) Store(k K, v V) {
+ m.Lock()
+ defer m.Unlock()
+ m.m[k] = v
+}
+
+func (m *SyncMap[K, V]) Load(k K) (v V, ok bool) {
+ m.RLock()
+ defer m.RUnlock()
+ v, ok = m.m[k]
+ return
+}
+
+// LoadOrStore returns the existing value for the key if present. Otherwise, it stores and returns the given value.
+func (m *SyncMap[K, V]) LoadOrStore(k K, v V) (actual V, loaded bool) {
+ m.Lock()
+ defer m.Unlock()
+ actual, loaded = m.m[k]
+ if loaded {
+ return
+ }
+ m.m[k] = v
+ return v, false
+}
+
+// LoadAndDelete deletes the value for a key, and returns the previous value if any.
+func (m *SyncMap[K, V]) LoadAndDelete(k K) (v V, loaded bool) {
+ m.Lock()
+ defer m.Unlock()
+ v, loaded = m.m[k]
+ if loaded {
+ delete(m.m, k)
+ }
+ return
+}
+
+func (m *SyncMap[K, V]) Delete(k K) {
+ m.Lock()
+ defer m.Unlock()
+ delete(m.m, k)
+}
+
+func (m *SyncMap[K, V]) Clear() {
+ m.Lock()
+ defer m.Unlock()
+ clear(m.m)
+}
+
+func (m *SyncMap[K, V]) Len() int {
+ m.RLock()
+ defer m.RUnlock()
+ return len(m.m)
+}
+
+func (m *SyncMap[K, V]) Clone() map[K]V {
+ m.RLock()
+ defer m.RUnlock()
+ return maps.Clone(m.m)
+}
+
+func (m *SyncMap[K, V]) Range(f func(k K, v V) bool) {
+ m.RLock()
+ defer m.RUnlock()
+
+ for k, v := range m.m {
+ if !f(k, v) {
+ break
+ }
+ }
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/js_handle.go b/vendor/github.com/playwright-community/playwright-go/js_handle.go
new file mode 100644
index 0000000..6aaa68d
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/js_handle.go
@@ -0,0 +1,421 @@
+package playwright
+
+import (
+ "bytes"
+ "encoding/base64"
+ "encoding/binary"
+ "errors"
+ "fmt"
+ "math"
+ "math/big"
+ "net/url"
+ "reflect"
+ "time"
+)
+
+type jsHandleImpl struct {
+ channelOwner
+ preview string
+}
+
+func (j *jsHandleImpl) Evaluate(expression string, options ...interface{}) (interface{}, error) {
+ var arg interface{}
+ if len(options) == 1 {
+ arg = options[0]
+ }
+ result, err := j.channel.Send("evaluateExpression", map[string]interface{}{
+ "expression": expression,
+ "arg": serializeArgument(arg),
+ })
+ if err != nil {
+ return nil, err
+ }
+ return parseResult(result), nil
+}
+
+func (j *jsHandleImpl) EvaluateHandle(expression string, options ...interface{}) (JSHandle, error) {
+ var arg interface{}
+ if len(options) == 1 {
+ arg = options[0]
+ }
+ result, err := j.channel.Send("evaluateExpressionHandle", map[string]interface{}{
+ "expression": expression,
+ "arg": serializeArgument(arg),
+ })
+ if err != nil {
+ return nil, err
+ }
+ channelOwner := fromChannel(result)
+ if channelOwner == nil {
+ return nil, nil
+ }
+ return channelOwner.(*jsHandleImpl), nil
+}
+
+func (j *jsHandleImpl) GetProperty(name string) (JSHandle, error) {
+ channel, err := j.channel.Send("getProperty", map[string]interface{}{
+ "name": name,
+ })
+ if err != nil {
+ return nil, err
+ }
+ return fromChannel(channel).(*jsHandleImpl), nil
+}
+
+func (j *jsHandleImpl) GetProperties() (map[string]JSHandle, error) {
+ properties, err := j.channel.Send("getPropertyList")
+ if err != nil {
+ return nil, err
+ }
+ propertiesMap := make(map[string]JSHandle)
+ for _, property := range properties.([]interface{}) {
+ item := property.(map[string]interface{})
+ propertiesMap[item["name"].(string)] = fromChannel(item["value"]).(*jsHandleImpl)
+ }
+ return propertiesMap, nil
+}
+
+func (j *jsHandleImpl) AsElement() ElementHandle {
+ return nil
+}
+
+func (j *jsHandleImpl) Dispose() error {
+ _, err := j.channel.Send("dispose")
+ if errors.Is(err, ErrTargetClosed) {
+ return nil
+ }
+ return err
+}
+
+func (j *jsHandleImpl) String() string {
+ return j.preview
+}
+
+func (j *jsHandleImpl) JSONValue() (interface{}, error) {
+ v, err := j.channel.Send("jsonValue")
+ if err != nil {
+ return nil, err
+ }
+ return parseResult(v), nil
+}
+
+func parseValue(result interface{}, refs map[float64]interface{}) interface{} {
+ vMap, ok := result.(map[string]interface{})
+ if !ok {
+ return result
+ }
+ if v, ok := vMap["n"]; ok {
+ if math.Ceil(v.(float64))-v.(float64) == 0 {
+ return int(v.(float64))
+ }
+ return v.(float64)
+ }
+
+ if v, ok := vMap["u"]; ok {
+ u, _ := url.Parse(v.(string))
+ return u
+ }
+
+ if v, ok := vMap["bi"]; ok {
+ n := new(big.Int)
+ n.SetString(v.(string), 0)
+ return n
+ }
+
+ if v, ok := vMap["ref"]; ok {
+ if vV, ok := refs[v.(float64)]; ok {
+ return vV
+ }
+ return nil
+ }
+
+ if v, ok := vMap["s"]; ok {
+ return v.(string)
+ }
+ if v, ok := vMap["b"]; ok {
+ return v.(bool)
+ }
+ if v, ok := vMap["v"]; ok {
+ if v == "undefined" || v == "null" {
+ return nil
+ }
+ if v == "NaN" {
+ return math.NaN()
+ }
+ if v == "Infinity" {
+ return math.Inf(1)
+ }
+ if v == "-Infinity" {
+ return math.Inf(-1)
+ }
+ if v == "-0" {
+ return math.Copysign(0, -1)
+ }
+ return v
+ }
+ if v, ok := vMap["d"]; ok {
+ t, _ := time.Parse(time.RFC3339Nano, v.(string))
+ return t
+ }
+ if v, ok := vMap["a"]; ok {
+ aV := v.([]interface{})
+ refs[vMap["id"].(float64)] = aV
+ for i := range aV {
+ aV[i] = parseValue(aV[i], refs)
+ }
+ return aV
+ }
+ if v, ok := vMap["o"]; ok {
+ aV := v.([]interface{})
+ out := map[string]interface{}{}
+ refs[vMap["id"].(float64)] = out
+ for key := range aV {
+ entry := aV[key].(map[string]interface{})
+ out[entry["k"].(string)] = parseValue(entry["v"], refs)
+ }
+ return out
+ }
+
+ if v, ok := vMap["e"]; ok {
+ return parseError(Error{
+ Name: v.(map[string]interface{})["n"].(string),
+ Message: v.(map[string]interface{})["m"].(string),
+ Stack: v.(map[string]interface{})["s"].(string),
+ })
+ }
+ if v, ok := vMap["ta"]; ok {
+ b, b_ok := v.(map[string]interface{})["b"].(string)
+ k, k_ok := v.(map[string]interface{})["k"].(string)
+ if b_ok && k_ok {
+ decoded, err := base64.StdEncoding.DecodeString(b)
+ if err != nil {
+ panic(fmt.Errorf("Unexpected value: %v", vMap))
+ }
+ r := bytes.NewReader(decoded)
+ switch k {
+ case "i8":
+ result := make([]int8, len(decoded))
+ return mustReadArray(r, &result)
+ case "ui8", "ui8c":
+ result := make([]uint8, len(decoded))
+ return mustReadArray(r, &result)
+ case "i16":
+ size := mustBeDivisible(len(decoded), 2)
+ result := make([]int16, size)
+ return mustReadArray(r, &result)
+ case "ui16":
+ size := mustBeDivisible(len(decoded), 2)
+ result := make([]uint16, size)
+ return mustReadArray(r, &result)
+ case "i32":
+ size := mustBeDivisible(len(decoded), 4)
+ result := make([]int32, size)
+ return mustReadArray(r, &result)
+ case "ui32":
+ size := mustBeDivisible(len(decoded), 4)
+ result := make([]uint32, size)
+ return mustReadArray(r, &result)
+ case "f32":
+ size := mustBeDivisible(len(decoded), 4)
+ result := make([]float32, size)
+ return mustReadArray(r, &result)
+ case "f64":
+ size := mustBeDivisible(len(decoded), 8)
+ result := make([]float64, size)
+ return mustReadArray(r, &result)
+ case "bi64":
+ size := mustBeDivisible(len(decoded), 8)
+ result := make([]int64, size)
+ return mustReadArray(r, &result)
+ case "bui64":
+ size := mustBeDivisible(len(decoded), 8)
+ result := make([]uint64, size)
+ return mustReadArray(r, &result)
+ default:
+ panic(fmt.Errorf("Unsupported array type: %s", k))
+ }
+ }
+ }
+ panic(fmt.Errorf("Unexpected value: %v", vMap))
+}
+
+func serializeValue(value interface{}, handles *[]*channel, depth int) interface{} {
+ if handle, ok := value.(*elementHandleImpl); ok {
+ h := len(*handles)
+ *handles = append(*handles, handle.channel)
+ return map[string]interface{}{
+ "h": h,
+ }
+ }
+ if handle, ok := value.(*jsHandleImpl); ok {
+ h := len(*handles)
+ *handles = append(*handles, handle.channel)
+ return map[string]interface{}{
+ "h": h,
+ }
+ }
+ if u, ok := value.(*url.URL); ok {
+ return map[string]interface{}{
+ "u": u.String(),
+ }
+ }
+
+ if err, ok := value.(error); ok {
+ var e *Error
+ if errors.As(err, &e) {
+ return map[string]interface{}{
+ "e": map[string]interface{}{
+ "n": e.Name,
+ "m": e.Message,
+ "s": e.Stack,
+ },
+ }
+ }
+ return map[string]interface{}{
+ "e": map[string]interface{}{
+ "n": "",
+ "m": err.Error(),
+ "s": "",
+ },
+ }
+ }
+
+ if depth > 100 {
+ panic(errors.New("Maximum argument depth exceeded"))
+ }
+ if value == nil {
+ return map[string]interface{}{
+ "v": "undefined",
+ }
+ }
+ if n, ok := value.(*big.Int); ok {
+ return map[string]interface{}{
+ "bi": n.String(),
+ }
+ }
+
+ switch v := value.(type) {
+ case time.Time:
+ return map[string]interface{}{
+ "d": v.Format(time.RFC3339Nano),
+ }
+ case int:
+ return map[string]interface{}{
+ "n": v,
+ }
+ case string:
+ return map[string]interface{}{
+ "s": v,
+ }
+ case bool:
+ return map[string]interface{}{
+ "b": v,
+ }
+ }
+
+ refV := reflect.ValueOf(value)
+
+ switch refV.Kind() {
+ case reflect.Float32, reflect.Float64:
+ floatV := refV.Float()
+ if math.IsInf(floatV, 1) {
+ return map[string]interface{}{
+ "v": "Infinity",
+ }
+ }
+ if math.IsInf(floatV, -1) {
+ return map[string]interface{}{
+ "v": "-Infinity",
+ }
+ }
+ // https://github.com/golang/go/issues/2196
+ if floatV == math.Copysign(0, -1) {
+ return map[string]interface{}{
+ "v": "-0",
+ }
+ }
+ if math.IsNaN(floatV) {
+ return map[string]interface{}{
+ "v": "NaN",
+ }
+ }
+ return map[string]interface{}{
+ "n": floatV,
+ }
+ case reflect.Slice:
+ aV := make([]interface{}, refV.Len())
+ for i := 0; i < refV.Len(); i++ {
+ aV[i] = serializeValue(refV.Index(i).Interface(), handles, depth+1)
+ }
+ return map[string]interface{}{
+ "a": aV,
+ }
+ case reflect.Map:
+ out := []interface{}{}
+ vM := value.(map[string]interface{})
+ for key := range vM {
+ v := serializeValue(vM[key], handles, depth+1)
+ // had key, so convert "undefined" to "null"
+ if reflect.DeepEqual(v, map[string]interface{}{
+ "v": "undefined",
+ }) {
+ v = map[string]interface{}{
+ "v": "null",
+ }
+ }
+ out = append(out, map[string]interface{}{
+ "k": key,
+ "v": v,
+ })
+ }
+ return map[string]interface{}{
+ "o": out,
+ }
+ }
+ return map[string]interface{}{
+ "v": "undefined",
+ }
+}
+
+func parseResult(result interface{}) interface{} {
+ return parseValue(result, map[float64]interface{}{})
+}
+
+func serializeArgument(arg interface{}) interface{} {
+ handles := []*channel{}
+ value := serializeValue(arg, &handles, 0)
+ return map[string]interface{}{
+ "value": value,
+ "handles": handles,
+ }
+}
+
+func newJSHandle(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *jsHandleImpl {
+ bt := &jsHandleImpl{
+ preview: initializer["preview"].(string),
+ }
+ bt.createChannelOwner(bt, parent, objectType, guid, initializer)
+ bt.channel.On("previewUpdated", func(ev map[string]interface{}) {
+ bt.preview = ev["preview"].(string)
+ })
+ return bt
+}
+
+func mustBeDivisible(length int, wordSize int) int {
+ if length%wordSize != 0 {
+ panic(fmt.Errorf(`Decoded bytes length %d is not a multiple of word size %d`, length, wordSize))
+ }
+ return length / wordSize
+}
+
+func mustReadArray[T int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64 | float32 | float64](r *bytes.Reader, v *[]T) []float64 {
+ err := binary.Read(r, binary.LittleEndian, v)
+ if err != nil {
+ panic(err)
+ }
+ data := make([]float64, len(*v))
+ for i, v := range *v {
+ data[i] = float64(v)
+ }
+ return data
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/jsonPipe.go b/vendor/github.com/playwright-community/playwright-go/jsonPipe.go
new file mode 100644
index 0000000..e6c0e79
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/jsonPipe.go
@@ -0,0 +1,64 @@
+package playwright
+
+import (
+ "encoding/json"
+ "errors"
+ "fmt"
+)
+
+type jsonPipe struct {
+ channelOwner
+ msgChan chan *message
+}
+
+func (j *jsonPipe) Send(message map[string]interface{}) error {
+ _, err := j.channel.Send("send", map[string]interface{}{
+ "message": message,
+ })
+ return err
+}
+
+func (j *jsonPipe) Close() error {
+ _, err := j.channel.Send("close")
+ return err
+}
+
+func (j *jsonPipe) Poll() (*message, error) {
+ msg := <-j.msgChan
+ if msg == nil {
+ return nil, errors.New("jsonPipe closed")
+ }
+ return msg, nil
+}
+
+func newJsonPipe(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *jsonPipe {
+ j := &jsonPipe{
+ msgChan: make(chan *message, 2),
+ }
+ j.createChannelOwner(j, parent, objectType, guid, initializer)
+ j.channel.On("message", func(ev map[string]interface{}) {
+ var msg message
+ m, err := json.Marshal(ev["message"])
+ if err == nil {
+ err = json.Unmarshal(m, &msg)
+ }
+ if err != nil {
+ msg = message{
+ Error: &struct {
+ Error Error "json:\"error\""
+ }{
+ Error: Error{
+ Name: "Error",
+ Message: fmt.Sprintf("jsonPipe: could not decode message: %s", err.Error()),
+ },
+ },
+ }
+ }
+ j.msgChan <- &msg
+ })
+ j.channel.Once("closed", func() {
+ j.Emit("closed")
+ close(j.msgChan)
+ })
+ return j
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/local_utils.go b/vendor/github.com/playwright-community/playwright-go/local_utils.go
new file mode 100644
index 0000000..395c09a
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/local_utils.go
@@ -0,0 +1,165 @@
+package playwright
+
+import (
+ "encoding/base64"
+ "encoding/json"
+ "fmt"
+)
+
+type localUtilsImpl struct {
+ channelOwner
+ Devices map[string]*DeviceDescriptor
+}
+
+type (
+ localUtilsZipOptions struct {
+ ZipFile string `json:"zipFile"`
+ Entries []interface{} `json:"entries"`
+ StacksId string `json:"stacksId"`
+ Mode string `json:"mode"`
+ IncludeSources bool `json:"includeSources"`
+ }
+
+ harLookupOptions struct {
+ HarId string `json:"harId"`
+ URL string `json:"url"`
+ Method string `json:"method"`
+ Headers map[string]string `json:"headers"`
+ IsNavigationRequest bool `json:"isNavigationRequest"`
+ PostData interface{} `json:"postData,omitempty"`
+ }
+
+ harLookupResult struct {
+ Action string `json:"action"`
+ Message *string `json:"message,omitempty"`
+ RedirectURL *string `json:"redirectUrl,omitempty"`
+ Status *int `json:"status,omitempty"`
+ Headers []map[string]string `json:"headers,omitempty"`
+ Body *string `json:"body,omitempty"`
+ }
+)
+
+func (l *localUtilsImpl) Zip(options localUtilsZipOptions) (interface{}, error) {
+ return l.channel.Send("zip", options)
+}
+
+func (l *localUtilsImpl) HarOpen(file string) (string, error) {
+ result, err := l.channel.SendReturnAsDict("harOpen", []map[string]interface{}{
+ {
+ "file": file,
+ },
+ })
+ if err == nil {
+ if harId, ok := result["harId"]; ok {
+ return harId.(string), nil
+ }
+ if err, ok := result["error"]; ok {
+ return "", fmt.Errorf("%w:%v", ErrPlaywright, err)
+ }
+ }
+ return "", err
+}
+
+func (l *localUtilsImpl) HarLookup(option harLookupOptions) (*harLookupResult, error) {
+ overrides := make(map[string]interface{})
+ overrides["harId"] = option.HarId
+ overrides["url"] = option.URL
+ overrides["method"] = option.Method
+ if option.Headers != nil {
+ overrides["headers"] = serializeMapToNameAndValue(option.Headers)
+ }
+ overrides["isNavigationRequest"] = option.IsNavigationRequest
+ if option.PostData != nil {
+ switch v := option.PostData.(type) {
+ case string:
+ overrides["postData"] = base64.StdEncoding.EncodeToString([]byte(v))
+ case []byte:
+ overrides["postData"] = base64.StdEncoding.EncodeToString(v)
+ }
+ }
+ ret, err := l.channel.SendReturnAsDict("harLookup", overrides)
+ if ret == nil {
+ return nil, err
+ }
+ var result harLookupResult
+ mJson, err := json.Marshal(ret)
+ if err != nil {
+ return nil, err
+ }
+ err = json.Unmarshal(mJson, &result)
+ if err != nil {
+ return nil, err
+ }
+ if result.Body != nil {
+ body, err := base64.StdEncoding.DecodeString(*result.Body)
+ if err != nil {
+ return nil, err
+ }
+ result.Body = String(string(body))
+ }
+ return &result, err
+}
+
+func (l *localUtilsImpl) HarClose(harId string) error {
+ _, err := l.channel.Send("harClose", []map[string]interface{}{
+ {
+ "harId": harId,
+ },
+ })
+ return err
+}
+
+func (l *localUtilsImpl) HarUnzip(zipFile, harFile string) error {
+ _, err := l.channel.Send("harUnzip", []map[string]interface{}{
+ {
+ "zipFile": zipFile,
+ "harFile": harFile,
+ },
+ })
+ return err
+}
+
+func (l *localUtilsImpl) TracingStarted(traceName string, tracesDir ...string) (string, error) {
+ overrides := make(map[string]interface{})
+ overrides["traceName"] = traceName
+ if len(tracesDir) > 0 {
+ overrides["tracesDir"] = tracesDir[0]
+ }
+ stacksId, err := l.channel.Send("tracingStarted", overrides)
+ if stacksId == nil {
+ return "", err
+ }
+ return stacksId.(string), err
+}
+
+func (l *localUtilsImpl) TraceDiscarded(stacksId string) error {
+ _, err := l.channel.Send("traceDiscarded", map[string]interface{}{
+ "stacksId": stacksId,
+ })
+ return err
+}
+
+func (l *localUtilsImpl) AddStackToTracingNoReply(id uint32, stack []map[string]interface{}) {
+ l.channel.SendNoReply("addStackToTracingNoReply", map[string]interface{}{
+ "callData": map[string]interface{}{
+ "id": id,
+ "stack": stack,
+ },
+ })
+}
+
+func newLocalUtils(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *localUtilsImpl {
+ l := &localUtilsImpl{
+ Devices: make(map[string]*DeviceDescriptor),
+ }
+ l.createChannelOwner(l, parent, objectType, guid, initializer)
+ for _, dd := range initializer["deviceDescriptors"].([]interface{}) {
+ entry := dd.(map[string]interface{})
+ l.Devices[entry["name"].(string)] = &DeviceDescriptor{
+ Viewport: &Size{},
+ }
+ remapMapToStruct(entry["descriptor"], l.Devices[entry["name"].(string)])
+ }
+ l.markAsInternalType()
+ return l
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/locator.go b/vendor/github.com/playwright-community/playwright-go/locator.go
new file mode 100644
index 0000000..e6a49b7
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/locator.go
@@ -0,0 +1,914 @@
+package playwright
+
+import (
+ "errors"
+ "fmt"
+ "strconv"
+)
+
+var (
+ testIdAttributeName = "data-testid"
+ ErrLocatorNotSameFrame = errors.New("inner 'has' or 'hasNot' locator must belong to the same frame")
+)
+
+type locatorImpl struct {
+ frame *frameImpl
+ selector string
+ options *LocatorOptions
+ err error
+}
+
+type LocatorOptions LocatorFilterOptions
+
+func newLocator(frame *frameImpl, selector string, options ...LocatorOptions) *locatorImpl {
+ option := &LocatorOptions{}
+ if len(options) == 1 {
+ option = &options[0]
+ }
+ locator := &locatorImpl{frame: frame, selector: selector, options: option, err: nil}
+ if option.HasText != nil {
+ selector += fmt.Sprintf(` >> internal:has-text=%s`, escapeForTextSelector(option.HasText, false))
+ }
+ if option.HasNotText != nil {
+ selector += fmt.Sprintf(` >> internal:has-not-text=%s`, escapeForTextSelector(option.HasNotText, false))
+ }
+ if option.Has != nil {
+ has := option.Has.(*locatorImpl)
+ if frame != has.frame {
+ locator.err = errors.Join(locator.err, ErrLocatorNotSameFrame)
+ } else {
+ selector += fmt.Sprintf(` >> internal:has=%s`, escapeText(has.selector))
+ }
+ }
+ if option.HasNot != nil {
+ hasNot := option.HasNot.(*locatorImpl)
+ if frame != hasNot.frame {
+ locator.err = errors.Join(locator.err, ErrLocatorNotSameFrame)
+ } else {
+ selector += fmt.Sprintf(` >> internal:has-not=%s`, escapeText(hasNot.selector))
+ }
+ }
+ if option.Visible != nil {
+ selector += fmt.Sprintf(` >> visible=%s`, strconv.FormatBool(*option.Visible))
+ }
+
+ locator.selector = selector
+
+ return locator
+}
+
+func (l *locatorImpl) equals(locator Locator) bool {
+ return l.frame == locator.(*locatorImpl).frame && l.err == locator.(*locatorImpl).err && l.selector == locator.(*locatorImpl).selector
+}
+
+func (l *locatorImpl) Err() error {
+ return l.err
+}
+
+func (l *locatorImpl) All() ([]Locator, error) {
+ result := make([]Locator, 0)
+ count, err := l.Count()
+ if err != nil {
+ return nil, err
+ }
+ for i := 0; i < count; i++ {
+ result = append(result, l.Nth(i))
+ }
+ return result, nil
+}
+
+func (l *locatorImpl) AllInnerTexts() ([]string, error) {
+ if l.err != nil {
+ return nil, l.err
+ }
+ innerTexts, err := l.frame.EvalOnSelectorAll(l.selector, "ee => ee.map(e => e.innerText)")
+ if err != nil {
+ return nil, err
+ }
+ texts := innerTexts.([]interface{})
+ result := make([]string, len(texts))
+ for i := range texts {
+ result[i] = texts[i].(string)
+ }
+ return result, nil
+}
+
+func (l *locatorImpl) AllTextContents() ([]string, error) {
+ if l.err != nil {
+ return nil, l.err
+ }
+ textContents, err := l.frame.EvalOnSelectorAll(l.selector, "ee => ee.map(e => e.textContent || '')")
+ if err != nil {
+ return nil, err
+ }
+ texts := textContents.([]interface{})
+ result := make([]string, len(texts))
+ for i := range texts {
+ result[i] = texts[i].(string)
+ }
+ return result, nil
+}
+
+func (l *locatorImpl) And(locator Locator) Locator {
+ return newLocator(l.frame, l.selector+` >> internal:and=`+escapeText(locator.(*locatorImpl).selector))
+}
+
+func (l *locatorImpl) Or(locator Locator) Locator {
+ return newLocator(l.frame, l.selector+` >> internal:or=`+escapeText(locator.(*locatorImpl).selector))
+}
+
+func (l *locatorImpl) Blur(options ...LocatorBlurOptions) error {
+ if l.err != nil {
+ return l.err
+ }
+ params := map[string]interface{}{
+ "selector": l.selector,
+ "strict": true,
+ }
+ if len(options) == 1 {
+ if options[0].Timeout != nil {
+ params["timeout"] = options[0].Timeout
+ }
+ }
+ _, err := l.frame.channel.Send("blur", params)
+ return err
+}
+
+func (l *locatorImpl) AriaSnapshot(options ...LocatorAriaSnapshotOptions) (string, error) {
+ var option LocatorAriaSnapshotOptions
+ if len(options) == 1 {
+ option = options[0]
+ }
+ ret, err := l.frame.channel.Send("ariaSnapshot", option,
+ map[string]interface{}{"selector": l.selector})
+ if err != nil {
+ return "", err
+ }
+ return ret.(string), nil
+}
+
+func (l *locatorImpl) BoundingBox(options ...LocatorBoundingBoxOptions) (*Rect, error) {
+ if l.err != nil {
+ return nil, l.err
+ }
+ var option FrameWaitForSelectorOptions
+ if len(options) == 1 {
+ option.Timeout = options[0].Timeout
+ }
+
+ result, err := l.withElement(func(handle ElementHandle) (interface{}, error) {
+ return handle.BoundingBox()
+ }, option)
+ if err != nil {
+ return nil, err
+ }
+
+ return result.(*Rect), nil
+}
+
+func (l *locatorImpl) Check(options ...LocatorCheckOptions) error {
+ if l.err != nil {
+ return l.err
+ }
+ opt := FrameCheckOptions{
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&opt, options[0], false); err != nil {
+ return err
+ }
+ }
+ return l.frame.Check(l.selector, opt)
+}
+
+func (l *locatorImpl) Clear(options ...LocatorClearOptions) error {
+ if l.err != nil {
+ return l.err
+ }
+ if len(options) == 1 {
+ return l.Fill("", LocatorFillOptions{
+ Force: options[0].Force,
+ Timeout: options[0].Timeout,
+ })
+ } else {
+ return l.Fill("")
+ }
+}
+
+func (l *locatorImpl) Click(options ...LocatorClickOptions) error {
+ if l.err != nil {
+ return l.err
+ }
+ opt := FrameClickOptions{
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&opt, options[0], false); err != nil {
+ return err
+ }
+ }
+ return l.frame.Click(l.selector, opt)
+}
+
+func (l *locatorImpl) ContentFrame() FrameLocator {
+ return newFrameLocator(l.frame, l.selector)
+}
+
+func (l *locatorImpl) Count() (int, error) {
+ if l.err != nil {
+ return 0, l.err
+ }
+ return l.frame.queryCount(l.selector)
+}
+
+func (l *locatorImpl) Dblclick(options ...LocatorDblclickOptions) error {
+ if l.err != nil {
+ return l.err
+ }
+ opt := FrameDblclickOptions{
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&opt, options[0], false); err != nil {
+ return err
+ }
+ }
+ return l.frame.Dblclick(l.selector, opt)
+}
+
+func (l *locatorImpl) DispatchEvent(typ string, eventInit interface{}, options ...LocatorDispatchEventOptions) error {
+ if l.err != nil {
+ return l.err
+ }
+ opt := FrameDispatchEventOptions{
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&opt, options[0], false); err != nil {
+ return err
+ }
+ }
+ return l.frame.DispatchEvent(l.selector, typ, eventInit, opt)
+}
+
+func (l *locatorImpl) DragTo(target Locator, options ...LocatorDragToOptions) error {
+ if l.err != nil {
+ return l.err
+ }
+ opt := FrameDragAndDropOptions{
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&opt, options[0], false); err != nil {
+ return err
+ }
+ }
+ return l.frame.DragAndDrop(l.selector, target.(*locatorImpl).selector, opt)
+}
+
+func (l *locatorImpl) ElementHandle(options ...LocatorElementHandleOptions) (ElementHandle, error) {
+ if l.err != nil {
+ return nil, l.err
+ }
+ option := FrameWaitForSelectorOptions{
+ State: WaitForSelectorStateAttached,
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&option, options[0], false); err != nil {
+ return nil, err
+ }
+ }
+ return l.frame.WaitForSelector(l.selector, option)
+}
+
+func (l *locatorImpl) ElementHandles() ([]ElementHandle, error) {
+ if l.err != nil {
+ return nil, l.err
+ }
+ return l.frame.QuerySelectorAll(l.selector)
+}
+
+func (l *locatorImpl) Evaluate(expression string, arg interface{}, options ...LocatorEvaluateOptions) (interface{}, error) {
+ if l.err != nil {
+ return nil, l.err
+ }
+ var option FrameWaitForSelectorOptions
+ if len(options) == 1 {
+ option.Timeout = options[0].Timeout
+ }
+
+ return l.withElement(func(handle ElementHandle) (interface{}, error) {
+ return handle.Evaluate(expression, arg)
+ }, option)
+}
+
+func (l *locatorImpl) EvaluateAll(expression string, options ...interface{}) (interface{}, error) {
+ if l.err != nil {
+ return nil, l.err
+ }
+ return l.frame.EvalOnSelectorAll(l.selector, expression, options...)
+}
+
+func (l *locatorImpl) EvaluateHandle(expression string, arg interface{}, options ...LocatorEvaluateHandleOptions) (JSHandle, error) {
+ if l.err != nil {
+ return nil, l.err
+ }
+ var option FrameWaitForSelectorOptions
+ if len(options) == 1 {
+ option.Timeout = options[0].Timeout
+ }
+
+ h, err := l.withElement(func(handle ElementHandle) (interface{}, error) {
+ return handle.EvaluateHandle(expression, arg)
+ }, option)
+ if err != nil {
+ return nil, err
+ }
+ return h.(JSHandle), nil
+}
+
+func (l *locatorImpl) Fill(value string, options ...LocatorFillOptions) error {
+ if l.err != nil {
+ return l.err
+ }
+ opt := FrameFillOptions{
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&opt, options[0], false); err != nil {
+ return err
+ }
+ }
+ return l.frame.Fill(l.selector, value, opt)
+}
+
+func (l *locatorImpl) Filter(options ...LocatorFilterOptions) Locator {
+ if len(options) == 1 {
+ return newLocator(l.frame, l.selector, LocatorOptions(options[0]))
+ }
+ return newLocator(l.frame, l.selector)
+}
+
+func (l *locatorImpl) First() Locator {
+ return newLocator(l.frame, l.selector+" >> nth=0")
+}
+
+func (l *locatorImpl) Focus(options ...LocatorFocusOptions) error {
+ if l.err != nil {
+ return l.err
+ }
+ opt := FrameFocusOptions{
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&opt, options[0], false); err != nil {
+ return err
+ }
+ }
+ return l.frame.Focus(l.selector, opt)
+}
+
+func (l *locatorImpl) FrameLocator(selector string) FrameLocator {
+ return newFrameLocator(l.frame, l.selector+" >> "+selector)
+}
+
+func (l *locatorImpl) GetAttribute(name string, options ...LocatorGetAttributeOptions) (string, error) {
+ if l.err != nil {
+ return "", l.err
+ }
+ opt := FrameGetAttributeOptions{
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&opt, options[0], false); err != nil {
+ return "", err
+ }
+ }
+ return l.frame.GetAttribute(l.selector, name, opt)
+}
+
+func (l *locatorImpl) GetByAltText(text interface{}, options ...LocatorGetByAltTextOptions) Locator {
+ exact := false
+ if len(options) == 1 {
+ if *options[0].Exact {
+ exact = true
+ }
+ }
+ return l.Locator(getByAltTextSelector(text, exact))
+}
+
+func (l *locatorImpl) GetByLabel(text interface{}, options ...LocatorGetByLabelOptions) Locator {
+ exact := false
+ if len(options) == 1 {
+ if *options[0].Exact {
+ exact = true
+ }
+ }
+ return l.Locator(getByLabelSelector(text, exact))
+}
+
+func (l *locatorImpl) GetByPlaceholder(text interface{}, options ...LocatorGetByPlaceholderOptions) Locator {
+ exact := false
+ if len(options) == 1 {
+ if *options[0].Exact {
+ exact = true
+ }
+ }
+ return l.Locator(getByPlaceholderSelector(text, exact))
+}
+
+func (l *locatorImpl) GetByRole(role AriaRole, options ...LocatorGetByRoleOptions) Locator {
+ return l.Locator(getByRoleSelector(role, options...))
+}
+
+func (l *locatorImpl) GetByTestId(testId interface{}) Locator {
+ return l.Locator(getByTestIdSelector(getTestIdAttributeName(), testId))
+}
+
+func (l *locatorImpl) GetByText(text interface{}, options ...LocatorGetByTextOptions) Locator {
+ exact := false
+ if len(options) == 1 {
+ if *options[0].Exact {
+ exact = true
+ }
+ }
+ return l.Locator(getByTextSelector(text, exact))
+}
+
+func (l *locatorImpl) GetByTitle(text interface{}, options ...LocatorGetByTitleOptions) Locator {
+ exact := false
+ if len(options) == 1 {
+ if *options[0].Exact {
+ exact = true
+ }
+ }
+ return l.Locator(getByTitleSelector(text, exact))
+}
+
+func (l *locatorImpl) Highlight() error {
+ if l.err != nil {
+ return l.err
+ }
+ return l.frame.highlight(l.selector)
+}
+
+func (l *locatorImpl) Hover(options ...LocatorHoverOptions) error {
+ if l.err != nil {
+ return l.err
+ }
+ opt := FrameHoverOptions{
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&opt, options[0], false); err != nil {
+ return err
+ }
+ }
+ return l.frame.Hover(l.selector, opt)
+}
+
+func (l *locatorImpl) InnerHTML(options ...LocatorInnerHTMLOptions) (string, error) {
+ if l.err != nil {
+ return "", l.err
+ }
+ opt := FrameInnerHTMLOptions{
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&opt, options[0], false); err != nil {
+ return "", err
+ }
+ }
+ return l.frame.InnerHTML(l.selector, opt)
+}
+
+func (l *locatorImpl) InnerText(options ...LocatorInnerTextOptions) (string, error) {
+ if l.err != nil {
+ return "", l.err
+ }
+ opt := FrameInnerTextOptions{
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&opt, options[0], false); err != nil {
+ return "", err
+ }
+ }
+ return l.frame.InnerText(l.selector, opt)
+}
+
+func (l *locatorImpl) InputValue(options ...LocatorInputValueOptions) (string, error) {
+ if l.err != nil {
+ return "", l.err
+ }
+ opt := FrameInputValueOptions{
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&opt, options[0], false); err != nil {
+ return "", err
+ }
+ }
+ return l.frame.InputValue(l.selector, opt)
+}
+
+func (l *locatorImpl) IsChecked(options ...LocatorIsCheckedOptions) (bool, error) {
+ if l.err != nil {
+ return false, l.err
+ }
+ opt := FrameIsCheckedOptions{
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&opt, options[0], false); err != nil {
+ return false, err
+ }
+ }
+ return l.frame.IsChecked(l.selector, opt)
+}
+
+func (l *locatorImpl) IsDisabled(options ...LocatorIsDisabledOptions) (bool, error) {
+ if l.err != nil {
+ return false, l.err
+ }
+ opt := FrameIsDisabledOptions{
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&opt, options[0], false); err != nil {
+ return false, err
+ }
+ }
+ return l.frame.IsDisabled(l.selector, opt)
+}
+
+func (l *locatorImpl) IsEditable(options ...LocatorIsEditableOptions) (bool, error) {
+ if l.err != nil {
+ return false, l.err
+ }
+ opt := FrameIsEditableOptions{
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&opt, options[0], false); err != nil {
+ return false, err
+ }
+ }
+ return l.frame.IsEditable(l.selector, opt)
+}
+
+func (l *locatorImpl) IsEnabled(options ...LocatorIsEnabledOptions) (bool, error) {
+ if l.err != nil {
+ return false, l.err
+ }
+ opt := FrameIsEnabledOptions{
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&opt, options[0], false); err != nil {
+ return false, err
+ }
+ }
+ return l.frame.IsEnabled(l.selector, opt)
+}
+
+func (l *locatorImpl) IsHidden(options ...LocatorIsHiddenOptions) (bool, error) {
+ if l.err != nil {
+ return false, l.err
+ }
+ opt := FrameIsHiddenOptions{
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&opt, options[0], false); err != nil {
+ return false, err
+ }
+ }
+ return l.frame.IsHidden(l.selector, opt)
+}
+
+func (l *locatorImpl) IsVisible(options ...LocatorIsVisibleOptions) (bool, error) {
+ if l.err != nil {
+ return false, l.err
+ }
+ opt := FrameIsVisibleOptions{
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&opt, options[0], false); err != nil {
+ return false, err
+ }
+ }
+ return l.frame.IsVisible(l.selector, opt)
+}
+
+func (l *locatorImpl) Last() Locator {
+ return newLocator(l.frame, l.selector+" >> nth=-1")
+}
+
+func (l *locatorImpl) Locator(selectorOrLocator interface{}, options ...LocatorLocatorOptions) Locator {
+ var option LocatorOptions
+ if len(options) == 1 {
+ option = LocatorOptions{
+ Has: options[0].Has,
+ HasNot: options[0].HasNot,
+ HasText: options[0].HasText,
+ HasNotText: options[0].HasNotText,
+ }
+ }
+
+ selector, ok := selectorOrLocator.(string)
+ if ok {
+ return newLocator(l.frame, l.selector+" >> "+selector, option)
+ }
+ locator, ok := selectorOrLocator.(*locatorImpl)
+ if ok {
+ if l.frame != locator.frame {
+ l.err = errors.Join(l.err, ErrLocatorNotSameFrame)
+ return l
+ }
+ return newLocator(l.frame,
+ l.selector+" >> internal:chain="+escapeText(locator.selector),
+ option,
+ )
+ }
+ l.err = errors.Join(l.err, fmt.Errorf("invalid locator parameter: %v", selectorOrLocator))
+ return l
+}
+
+func (l *locatorImpl) Nth(index int) Locator {
+ return newLocator(l.frame, l.selector+" >> nth="+strconv.Itoa(index))
+}
+
+func (l *locatorImpl) Page() (Page, error) {
+ if l.err != nil {
+ return nil, l.err
+ }
+ return l.frame.Page(), nil
+}
+
+func (l *locatorImpl) Press(key string, options ...LocatorPressOptions) error {
+ if l.err != nil {
+ return l.err
+ }
+ opt := FramePressOptions{
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&opt, options[0], false); err != nil {
+ return err
+ }
+ }
+ return l.frame.Press(l.selector, key, opt)
+}
+
+func (l *locatorImpl) PressSequentially(text string, options ...LocatorPressSequentiallyOptions) error {
+ if l.err != nil {
+ return l.err
+ }
+ var option LocatorTypeOptions
+ if len(options) == 1 {
+ option = LocatorTypeOptions(options[0])
+ }
+ return l.Type(text, option)
+}
+
+func (l *locatorImpl) Screenshot(options ...LocatorScreenshotOptions) ([]byte, error) {
+ if l.err != nil {
+ return nil, l.err
+ }
+ var option FrameWaitForSelectorOptions
+ if len(options) == 1 {
+ option.Timeout = options[0].Timeout
+ }
+
+ result, err := l.withElement(func(handle ElementHandle) (interface{}, error) {
+ var screenshotOption ElementHandleScreenshotOptions
+ if len(options) == 1 {
+ screenshotOption = ElementHandleScreenshotOptions(options[0])
+ }
+ return handle.Screenshot(screenshotOption)
+ }, option)
+ if err != nil {
+ return nil, err
+ }
+
+ return result.([]byte), nil
+}
+
+func (l *locatorImpl) ScrollIntoViewIfNeeded(options ...LocatorScrollIntoViewIfNeededOptions) error {
+ if l.err != nil {
+ return l.err
+ }
+ var option FrameWaitForSelectorOptions
+ if len(options) == 1 {
+ option.Timeout = options[0].Timeout
+ }
+
+ _, err := l.withElement(func(handle ElementHandle) (interface{}, error) {
+ var opt ElementHandleScrollIntoViewIfNeededOptions
+ if len(options) == 1 {
+ opt.Timeout = options[0].Timeout
+ }
+ return nil, handle.ScrollIntoViewIfNeeded(opt)
+ }, option)
+
+ return err
+}
+
+func (l *locatorImpl) SelectOption(values SelectOptionValues, options ...LocatorSelectOptionOptions) ([]string, error) {
+ if l.err != nil {
+ return nil, l.err
+ }
+ opt := FrameSelectOptionOptions{
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&opt, options[0], false); err != nil {
+ return nil, err
+ }
+ }
+ return l.frame.SelectOption(l.selector, values, opt)
+}
+
+func (l *locatorImpl) SelectText(options ...LocatorSelectTextOptions) error {
+ if l.err != nil {
+ return l.err
+ }
+ var option FrameWaitForSelectorOptions
+ if len(options) == 1 {
+ option.Timeout = options[0].Timeout
+ }
+
+ _, err := l.withElement(func(handle ElementHandle) (interface{}, error) {
+ var opt ElementHandleSelectTextOptions
+ if len(options) == 1 {
+ opt = ElementHandleSelectTextOptions(options[0])
+ }
+ return nil, handle.SelectText(opt)
+ }, option)
+
+ return err
+}
+
+func (l *locatorImpl) SetChecked(checked bool, options ...LocatorSetCheckedOptions) error {
+ if l.err != nil {
+ return l.err
+ }
+ opt := FrameSetCheckedOptions{
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&opt, options[0], false); err != nil {
+ return err
+ }
+ }
+ return l.frame.SetChecked(l.selector, checked, opt)
+}
+
+func (l *locatorImpl) SetInputFiles(files interface{}, options ...LocatorSetInputFilesOptions) error {
+ if l.err != nil {
+ return l.err
+ }
+ opt := FrameSetInputFilesOptions{
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&opt, options[0], false); err != nil {
+ return err
+ }
+ }
+ return l.frame.SetInputFiles(l.selector, files, opt)
+}
+
+func (l *locatorImpl) Tap(options ...LocatorTapOptions) error {
+ if l.err != nil {
+ return l.err
+ }
+ opt := FrameTapOptions{
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&opt, options[0], false); err != nil {
+ return err
+ }
+ }
+ return l.frame.Tap(l.selector, opt)
+}
+
+func (l *locatorImpl) TextContent(options ...LocatorTextContentOptions) (string, error) {
+ if l.err != nil {
+ return "", l.err
+ }
+ opt := FrameTextContentOptions{
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&opt, options[0], false); err != nil {
+ return "", err
+ }
+ }
+ return l.frame.TextContent(l.selector, opt)
+}
+
+func (l *locatorImpl) Type(text string, options ...LocatorTypeOptions) error {
+ if l.err != nil {
+ return l.err
+ }
+ opt := FrameTypeOptions{
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&opt, options[0], false); err != nil {
+ return err
+ }
+ }
+ return l.frame.Type(l.selector, text, opt)
+}
+
+func (l *locatorImpl) Uncheck(options ...LocatorUncheckOptions) error {
+ if l.err != nil {
+ return l.err
+ }
+ opt := FrameUncheckOptions{
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&opt, options[0], false); err != nil {
+ return err
+ }
+ }
+ return l.frame.Uncheck(l.selector, opt)
+}
+
+func (l *locatorImpl) WaitFor(options ...LocatorWaitForOptions) error {
+ if l.err != nil {
+ return l.err
+ }
+ opt := FrameWaitForSelectorOptions{
+ Strict: Bool(true),
+ }
+ if len(options) == 1 {
+ if err := assignStructFields(&opt, options[0], false); err != nil {
+ return err
+ }
+ }
+ _, err := l.frame.WaitForSelector(l.selector, opt)
+ return err
+}
+
+func (l *locatorImpl) withElement(
+ callback func(handle ElementHandle) (interface{}, error),
+ options ...FrameWaitForSelectorOptions,
+) (interface{}, error) {
+ if l.err != nil {
+ return nil, l.err
+ }
+ handle, err := l.frame.WaitForSelector(l.selector, options...)
+ if err != nil {
+ return nil, err
+ }
+
+ result, err := callback(handle)
+ if err != nil {
+ return nil, err
+ }
+ return result, nil
+}
+
+func (l *locatorImpl) expect(expression string, options frameExpectOptions) (*frameExpectResult, error) {
+ if l.err != nil {
+ return nil, l.err
+ }
+ overrides := map[string]interface{}{
+ "selector": l.selector,
+ "expression": expression,
+ }
+ if options.ExpectedValue != nil {
+ overrides["expectedValue"] = serializeArgument(options.ExpectedValue)
+ options.ExpectedValue = nil
+ }
+ result, err := l.frame.channel.SendReturnAsDict("expect", options, overrides)
+ if err != nil {
+ return nil, err
+ }
+ var (
+ received interface{}
+ matches bool
+ log []string
+ )
+
+ if v, ok := result["received"]; ok {
+ received = parseResult(v)
+ }
+ if v, ok := result["matches"]; ok {
+ matches = v.(bool)
+ }
+ if v, ok := result["log"]; ok {
+ for _, l := range v.([]interface{}) {
+ log = append(log, l.(string))
+ }
+ }
+ return &frameExpectResult{Received: received, Matches: matches, Log: log}, nil
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/locator_assertions.go b/vendor/github.com/playwright-community/playwright-go/locator_assertions.go
new file mode 100644
index 0000000..e2ea2bb
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/locator_assertions.go
@@ -0,0 +1,568 @@
+package playwright
+
+import (
+ "fmt"
+ "regexp"
+)
+
+type locatorAssertionsImpl struct {
+ assertionsBase
+}
+
+func newLocatorAssertions(locator Locator, isNot bool, defaultTimeout *float64) *locatorAssertionsImpl {
+ return &locatorAssertionsImpl{
+ assertionsBase: assertionsBase{
+ actualLocator: locator,
+ isNot: isNot,
+ defaultTimeout: defaultTimeout,
+ },
+ }
+}
+
+func (la *locatorAssertionsImpl) ToBeAttached(options ...LocatorAssertionsToBeAttachedOptions) error {
+ expression := "to.be.attached"
+ var timeout *float64
+ if len(options) == 1 {
+ if options[0].Attached != nil && !*options[0].Attached {
+ expression = "to.be.detached"
+ }
+ timeout = options[0].Timeout
+ }
+ return la.expect(
+ expression,
+ frameExpectOptions{Timeout: timeout},
+ nil,
+ "Locator expected to be attached",
+ )
+}
+
+func (la *locatorAssertionsImpl) ToBeChecked(options ...LocatorAssertionsToBeCheckedOptions) error {
+ var timeout *float64
+
+ expectedValue := map[string]interface{}{}
+ expected := "checked"
+
+ if len(options) == 1 {
+ if options[0].Indeterminate != nil {
+ expectedValue["indeterminate"] = *options[0].Indeterminate
+ if *options[0].Indeterminate {
+ expected = "indeterminate"
+ }
+ } else {
+ if options[0].Checked != nil {
+ expectedValue["checked"] = *options[0].Checked
+ if !*options[0].Checked {
+ expected = "unchecked"
+ }
+ }
+ }
+ timeout = options[0].Timeout
+ }
+ return la.expect(
+ "to.be.checked",
+ frameExpectOptions{
+ ExpectedValue: expectedValue,
+ Timeout: timeout,
+ },
+ nil,
+ fmt.Sprintf("Locator expected to be %s", expected),
+ )
+}
+
+func (la *locatorAssertionsImpl) ToBeDisabled(options ...LocatorAssertionsToBeDisabledOptions) error {
+ var timeout *float64
+ if len(options) == 1 {
+ timeout = options[0].Timeout
+ }
+ return la.expect(
+ "to.be.disabled",
+ frameExpectOptions{Timeout: timeout},
+ nil,
+ "Locator expected to be disabled",
+ )
+}
+
+func (la *locatorAssertionsImpl) ToBeEditable(options ...LocatorAssertionsToBeEditableOptions) error {
+ var timeout *float64
+ if len(options) == 1 {
+ timeout = options[0].Timeout
+ }
+ return la.expect(
+ "to.be.editable",
+ frameExpectOptions{Timeout: timeout},
+ nil,
+ "Locator expected to be editable",
+ )
+}
+
+func (la *locatorAssertionsImpl) ToBeEmpty(options ...LocatorAssertionsToBeEmptyOptions) error {
+ var timeout *float64
+ if len(options) == 1 {
+ timeout = options[0].Timeout
+ }
+ return la.expect(
+ "to.be.empty",
+ frameExpectOptions{Timeout: timeout},
+ nil,
+ "Locator expected to be empty",
+ )
+}
+
+func (la *locatorAssertionsImpl) ToBeEnabled(options ...LocatorAssertionsToBeEnabledOptions) error {
+ var timeout *float64
+ if len(options) == 1 {
+ timeout = options[0].Timeout
+ }
+ return la.expect(
+ "to.be.enabled",
+ frameExpectOptions{Timeout: timeout},
+ nil,
+ "Locator expected to be enabled",
+ )
+}
+
+func (la *locatorAssertionsImpl) ToBeFocused(options ...LocatorAssertionsToBeFocusedOptions) error {
+ var timeout *float64
+ if len(options) == 1 {
+ timeout = options[0].Timeout
+ }
+ return la.expect(
+ "to.be.focused",
+ frameExpectOptions{Timeout: timeout},
+ nil,
+ "Locator expected to be focused",
+ )
+}
+
+func (la *locatorAssertionsImpl) ToBeHidden(options ...LocatorAssertionsToBeHiddenOptions) error {
+ var timeout *float64
+ if len(options) == 1 {
+ timeout = options[0].Timeout
+ }
+ return la.expect(
+ "to.be.hidden",
+ frameExpectOptions{Timeout: timeout},
+ nil,
+ "Locator expected to be hidden",
+ )
+}
+
+func (la *locatorAssertionsImpl) ToBeInViewport(options ...LocatorAssertionsToBeInViewportOptions) error {
+ var (
+ ratio *float64
+ timeout *float64
+ )
+ if len(options) == 1 {
+ ratio = options[0].Ratio
+ timeout = options[0].Timeout
+ }
+ return la.expect(
+ "to.be.in.viewport",
+ frameExpectOptions{
+ ExpectedNumber: ratio,
+ Timeout: timeout,
+ },
+ nil,
+ "Locator expected to be in viewport",
+ )
+}
+
+func (la *locatorAssertionsImpl) ToBeVisible(options ...LocatorAssertionsToBeVisibleOptions) error {
+ var timeout *float64
+ if len(options) == 1 {
+ timeout = options[0].Timeout
+ }
+ return la.expect(
+ "to.be.visible",
+ frameExpectOptions{Timeout: timeout},
+ nil,
+ "Locator expected to be visible",
+ )
+}
+
+func (la *locatorAssertionsImpl) ToContainClass(expected interface{}, options ...LocatorAssertionsToContainClassOptions) error {
+ var timeout *float64
+ if len(options) == 1 {
+ timeout = options[0].Timeout
+ }
+ switch expected.(type) {
+ case []string:
+ expectedText, err := toExpectedTextValues(convertToInterfaceList(expected), false, false, nil)
+ if err != nil {
+ return err
+ }
+ return la.expect(
+ "to.contain.class.array",
+ frameExpectOptions{
+ ExpectedText: expectedText,
+ Timeout: timeout,
+ },
+ expected,
+ "Locator expected to contain class",
+ )
+ case string:
+ expectedText, err := toExpectedTextValues([]interface{}{expected}, false, false, nil)
+ if err != nil {
+ return err
+ }
+ return la.expect(
+ "to.contain.class",
+ frameExpectOptions{
+ ExpectedText: expectedText,
+ Timeout: timeout,
+ },
+ expected,
+ "Locator expected to contain class",
+ )
+ default:
+ return fmt.Errorf("expected should be string or []string, but got %T", expected)
+ }
+}
+
+func (la *locatorAssertionsImpl) ToContainText(expected interface{}, options ...LocatorAssertionsToContainTextOptions) error {
+ var (
+ timeout *float64
+ useInnerText *bool
+ ignoreCase *bool
+ )
+ if len(options) == 1 {
+ timeout = options[0].Timeout
+ useInnerText = options[0].UseInnerText
+ ignoreCase = options[0].IgnoreCase
+ }
+
+ switch expected.(type) {
+ case []string, []*regexp.Regexp:
+ expectedText, err := toExpectedTextValues(convertToInterfaceList(expected), true, true, ignoreCase)
+ if err != nil {
+ return err
+ }
+ return la.expect(
+ "to.contain.text.array",
+ frameExpectOptions{
+ ExpectedText: expectedText,
+ UseInnerText: useInnerText,
+ Timeout: timeout,
+ },
+ expected,
+ "Locator expected to contain text",
+ )
+ default:
+ expectedText, err := toExpectedTextValues([]interface{}{expected}, true, true, ignoreCase)
+ if err != nil {
+ return err
+ }
+ return la.expect(
+ "to.have.text",
+ frameExpectOptions{
+ ExpectedText: expectedText,
+ UseInnerText: useInnerText,
+ Timeout: timeout,
+ },
+ expected,
+ "Locator expected to contain text",
+ )
+ }
+}
+
+func (la *locatorAssertionsImpl) ToHaveAccessibleDescription(description interface{}, options ...LocatorAssertionsToHaveAccessibleDescriptionOptions) error {
+ var timeout *float64
+ var ignoreCase *bool
+ if len(options) == 1 {
+ timeout = options[0].Timeout
+ ignoreCase = options[0].IgnoreCase
+ }
+ expectedText, err := toExpectedTextValues([]interface{}{description}, false, false, ignoreCase)
+ if err != nil {
+ return err
+ }
+ return la.expect(
+ "to.have.accessible.description",
+ frameExpectOptions{ExpectedText: expectedText, Timeout: timeout},
+ description,
+ "Locator expected to have AccessibleDescription",
+ )
+}
+
+func (la *locatorAssertionsImpl) ToHaveAccessibleErrorMessage(errorMessage interface{}, options ...LocatorAssertionsToHaveAccessibleErrorMessageOptions) error {
+ var timeout *float64
+ var ignoreCase *bool
+ if len(options) == 1 {
+ timeout = options[0].Timeout
+ ignoreCase = options[0].IgnoreCase
+ }
+ expectedText, err := toExpectedTextValues([]interface{}{errorMessage}, false, false, ignoreCase)
+ if err != nil {
+ return err
+ }
+ return la.expect(
+ "to.have.accessible.error.message",
+ frameExpectOptions{ExpectedText: expectedText, Timeout: timeout},
+ errorMessage,
+ "Locator expected to have AccessibleErrorMessage",
+ )
+}
+
+func (la *locatorAssertionsImpl) ToHaveAccessibleName(name interface{}, options ...LocatorAssertionsToHaveAccessibleNameOptions) error {
+ var timeout *float64
+ var ignoreCase *bool
+ if len(options) == 1 {
+ timeout = options[0].Timeout
+ ignoreCase = options[0].IgnoreCase
+ }
+ expectedText, err := toExpectedTextValues([]interface{}{name}, false, false, ignoreCase)
+ if err != nil {
+ return err
+ }
+ return la.expect(
+ "to.have.accessible.name",
+ frameExpectOptions{ExpectedText: expectedText, Timeout: timeout},
+ name,
+ "Locator expected to have AccessibleName",
+ )
+}
+
+func (la *locatorAssertionsImpl) ToHaveAttribute(name string, value interface{}, options ...LocatorAssertionsToHaveAttributeOptions) error {
+ var timeout *float64
+ var ignoreCase *bool
+ if len(options) == 1 {
+ timeout = options[0].Timeout
+ ignoreCase = options[0].IgnoreCase
+ }
+ expectedText, err := toExpectedTextValues([]interface{}{value}, false, false, ignoreCase)
+ if err != nil {
+ return err
+ }
+ return la.expect(
+ "to.have.attribute.value",
+ frameExpectOptions{
+ ExpressionArg: name,
+ ExpectedText: expectedText,
+ Timeout: timeout,
+ },
+ value,
+ "Locator expected to have attribute",
+ )
+}
+
+func (la *locatorAssertionsImpl) ToHaveClass(expected interface{}, options ...LocatorAssertionsToHaveClassOptions) error {
+ var timeout *float64
+ if len(options) == 1 {
+ timeout = options[0].Timeout
+ }
+ switch expected.(type) {
+ case []string, []*regexp.Regexp:
+ expectedText, err := toExpectedTextValues(convertToInterfaceList(expected), false, false, nil)
+ if err != nil {
+ return err
+ }
+ return la.expect(
+ "to.have.class.array",
+ frameExpectOptions{
+ ExpectedText: expectedText,
+ Timeout: timeout,
+ },
+ expected,
+ "Locator expected to have class",
+ )
+ default:
+ expectedText, err := toExpectedTextValues([]interface{}{expected}, false, false, nil)
+ if err != nil {
+ return err
+ }
+ return la.expect(
+ "to.have.class",
+ frameExpectOptions{
+ ExpectedText: expectedText,
+ Timeout: timeout,
+ },
+ expected,
+ "Locator expected to have class",
+ )
+ }
+}
+
+func (la *locatorAssertionsImpl) ToHaveCount(count int, options ...LocatorAssertionsToHaveCountOptions) error {
+ var timeout *float64
+ if len(options) == 1 {
+ timeout = options[0].Timeout
+ }
+ return la.expect(
+ "to.have.count",
+ frameExpectOptions{ExpectedNumber: Float(float64(count)), Timeout: timeout},
+ count,
+ "Locator expected to have count",
+ )
+}
+
+func (la *locatorAssertionsImpl) ToHaveCSS(name string, value interface{}, options ...LocatorAssertionsToHaveCSSOptions) error {
+ var timeout *float64
+ if len(options) == 1 {
+ timeout = options[0].Timeout
+ }
+ expectedText, err := toExpectedTextValues([]interface{}{value}, false, false, nil)
+ if err != nil {
+ return err
+ }
+ return la.expect(
+ "to.have.css",
+ frameExpectOptions{
+ ExpressionArg: name,
+ ExpectedText: expectedText,
+ Timeout: timeout,
+ },
+ value,
+ "Locator expected to have CSS",
+ )
+}
+
+func (la *locatorAssertionsImpl) ToHaveId(id interface{}, options ...LocatorAssertionsToHaveIdOptions) error {
+ var timeout *float64
+ if len(options) == 1 {
+ timeout = options[0].Timeout
+ }
+ expectedText, err := toExpectedTextValues([]interface{}{id}, false, false, nil)
+ if err != nil {
+ return err
+ }
+ return la.expect(
+ "to.have.id",
+ frameExpectOptions{ExpectedText: expectedText, Timeout: timeout},
+ id,
+ "Locator expected to have ID",
+ )
+}
+
+func (la *locatorAssertionsImpl) ToHaveJSProperty(name string, value interface{}, options ...LocatorAssertionsToHaveJSPropertyOptions) error {
+ var timeout *float64
+ if len(options) == 1 {
+ timeout = options[0].Timeout
+ }
+ return la.expect(
+ "to.have.property",
+ frameExpectOptions{
+ ExpressionArg: name,
+ ExpectedValue: value,
+ Timeout: timeout,
+ },
+ value,
+ "Locator expected to have JS Property",
+ )
+}
+
+func (la *locatorAssertionsImpl) ToHaveRole(role AriaRole, options ...LocatorAssertionsToHaveRoleOptions) error {
+ var timeout *float64
+ if len(options) == 1 {
+ timeout = options[0].Timeout
+ }
+ expectedText, err := toExpectedTextValues([]interface{}{string(role)}, false, false, nil)
+ if err != nil {
+ return err
+ }
+ return la.expect(
+ "to.have.role",
+ frameExpectOptions{ExpectedText: expectedText, Timeout: timeout},
+ role,
+ "Locator expected to have Role",
+ )
+}
+
+func (la *locatorAssertionsImpl) ToHaveText(expected interface{}, options ...LocatorAssertionsToHaveTextOptions) error {
+ var (
+ timeout *float64
+ useInnerText *bool
+ ignoreCase *bool
+ )
+ if len(options) == 1 {
+ timeout = options[0].Timeout
+ useInnerText = options[0].UseInnerText
+ ignoreCase = options[0].IgnoreCase
+ }
+
+ switch expected.(type) {
+ case []string, []*regexp.Regexp:
+ expectedText, err := toExpectedTextValues(convertToInterfaceList(expected), false, true, ignoreCase)
+ if err != nil {
+ return err
+ }
+ return la.expect(
+ "to.have.text.array",
+ frameExpectOptions{
+ ExpectedText: expectedText,
+ UseInnerText: useInnerText,
+ Timeout: timeout,
+ },
+ expected,
+ "Locator expected to have text",
+ )
+ default:
+ expectedText, err := toExpectedTextValues([]interface{}{expected}, false, true, ignoreCase)
+ if err != nil {
+ return err
+ }
+ return la.expect(
+ "to.have.text",
+ frameExpectOptions{
+ ExpectedText: expectedText,
+ UseInnerText: useInnerText,
+ Timeout: timeout,
+ },
+ expected,
+ "Locator expected to have text",
+ )
+ }
+}
+
+func (la *locatorAssertionsImpl) ToHaveValue(value interface{}, options ...LocatorAssertionsToHaveValueOptions) error {
+ var timeout *float64
+ if len(options) == 1 {
+ timeout = options[0].Timeout
+ }
+ expectedText, err := toExpectedTextValues([]interface{}{value}, false, false, nil)
+ if err != nil {
+ return err
+ }
+ return la.expect(
+ "to.have.value",
+ frameExpectOptions{ExpectedText: expectedText, Timeout: timeout},
+ value,
+ "Locator expected to have Value",
+ )
+}
+
+func (la *locatorAssertionsImpl) ToHaveValues(values []interface{}, options ...LocatorAssertionsToHaveValuesOptions) error {
+ var timeout *float64
+ if len(options) == 1 {
+ timeout = options[0].Timeout
+ }
+ expectedText, err := toExpectedTextValues(values, false, false, nil)
+ if err != nil {
+ return err
+ }
+ return la.expect(
+ "to.have.values",
+ frameExpectOptions{ExpectedText: expectedText, Timeout: timeout},
+ values,
+ "Locator expected to have Values",
+ )
+}
+
+func (la *locatorAssertionsImpl) ToMatchAriaSnapshot(expected string, options ...LocatorAssertionsToMatchAriaSnapshotOptions) error {
+ var timeout *float64
+ if len(options) == 1 {
+ timeout = options[0].Timeout
+ }
+ return la.expect(
+ "to.match.aria",
+ frameExpectOptions{
+ ExpectedValue: expected,
+ Timeout: timeout,
+ },
+ expected,
+ "Locator expected to match Aria snapshot",
+ )
+}
+
+func (la *locatorAssertionsImpl) Not() LocatorAssertions {
+ return newLocatorAssertions(la.actualLocator, true, la.defaultTimeout)
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/locator_helpers.go b/vendor/github.com/playwright-community/playwright-go/locator_helpers.go
new file mode 100644
index 0000000..2836fca
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/locator_helpers.go
@@ -0,0 +1,133 @@
+package playwright
+
+import (
+ "encoding/json"
+ "fmt"
+ "regexp"
+ "strings"
+)
+
+func convertRegexp(reg *regexp.Regexp) (pattern, flags string) {
+ matches := regexp.MustCompile(`\(\?([imsU]+)\)(.+)`).FindStringSubmatch(reg.String())
+
+ if len(matches) == 3 {
+ pattern = matches[2]
+ flags = matches[1]
+ } else {
+ pattern = reg.String()
+ }
+ return
+}
+
+func escapeForAttributeSelector(text interface{}, exact bool) string {
+ switch text := text.(type) {
+ case *regexp.Regexp:
+ return escapeRegexForSelector(text)
+ default:
+ suffix := "i"
+ if exact {
+ suffix = "s"
+ }
+ return fmt.Sprintf(`"%s"%s`, strings.Replace(strings.Replace(text.(string), `\`, `\\`, -1), `"`, `\"`, -1), suffix)
+ }
+}
+
+func escapeForTextSelector(text interface{}, exact bool) string {
+ switch text := text.(type) {
+ case *regexp.Regexp:
+ return escapeRegexForSelector(text)
+ default:
+ if exact {
+ return fmt.Sprintf(`%ss`, escapeText(text.(string)))
+ }
+ return fmt.Sprintf(`%si`, escapeText(text.(string)))
+ }
+}
+
+func escapeRegexForSelector(re *regexp.Regexp) string {
+ pattern, flag := convertRegexp(re)
+ return fmt.Sprintf(`/%s/%s`, strings.ReplaceAll(pattern, `>>`, `\>\>`), flag)
+}
+
+func escapeText(s string) string {
+ builder := &strings.Builder{}
+ encoder := json.NewEncoder(builder)
+ encoder.SetEscapeHTML(false)
+ _ = encoder.Encode(s)
+ return strings.TrimSpace(builder.String())
+}
+
+func getByAltTextSelector(text interface{}, exact bool) string {
+ return getByAttributeTextSelector("alt", text, exact)
+}
+
+func getByAttributeTextSelector(attrName string, text interface{}, exact bool) string {
+ return fmt.Sprintf(`internal:attr=[%s=%s]`, attrName, escapeForAttributeSelector(text, exact))
+}
+
+func getByLabelSelector(text interface{}, exact bool) string {
+ return fmt.Sprintf(`internal:label=%s`, escapeForTextSelector(text, exact))
+}
+
+func getByPlaceholderSelector(text interface{}, exact bool) string {
+ return getByAttributeTextSelector("placeholder", text, exact)
+}
+
+func getByRoleSelector(role AriaRole, options ...LocatorGetByRoleOptions) string {
+ props := make(map[string]string)
+ if len(options) == 1 {
+ if options[0].Checked != nil {
+ props["checked"] = fmt.Sprintf("%t", *options[0].Checked)
+ }
+ if options[0].Disabled != nil {
+ props["disabled"] = fmt.Sprintf("%t", *options[0].Disabled)
+ }
+ if options[0].Selected != nil {
+ props["selected"] = fmt.Sprintf("%t", *options[0].Selected)
+ }
+ if options[0].Expanded != nil {
+ props["expanded"] = fmt.Sprintf("%t", *options[0].Expanded)
+ }
+ if options[0].IncludeHidden != nil {
+ props["include-hidden"] = fmt.Sprintf("%t", *options[0].IncludeHidden)
+ }
+ if options[0].Level != nil {
+ props["level"] = fmt.Sprintf("%d", *options[0].Level)
+ }
+ if options[0].Name != nil {
+ exact := false
+ if options[0].Exact != nil {
+ exact = *options[0].Exact
+ }
+ props["name"] = escapeForAttributeSelector(options[0].Name, exact)
+ }
+ if options[0].Pressed != nil {
+ props["pressed"] = fmt.Sprintf("%t", *options[0].Pressed)
+ }
+ }
+ propsStr := ""
+ for k, v := range props {
+ propsStr += "[" + k + "=" + v + "]"
+ }
+ return fmt.Sprintf("internal:role=%s%s", role, propsStr)
+}
+
+func getByTextSelector(text interface{}, exact bool) string {
+ return fmt.Sprintf(`internal:text=%s`, escapeForTextSelector(text, exact))
+}
+
+func getByTestIdSelector(testIdAttributeName string, testId interface{}) string {
+ return fmt.Sprintf(`internal:testid=[%s=%s]`, testIdAttributeName, escapeForAttributeSelector(testId, true))
+}
+
+func getByTitleSelector(text interface{}, exact bool) string {
+ return getByAttributeTextSelector("title", text, exact)
+}
+
+func getTestIdAttributeName() string {
+ return testIdAttributeName
+}
+
+func setTestIdAttributeName(name string) {
+ testIdAttributeName = name
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/network.go b/vendor/github.com/playwright-community/playwright-go/network.go
new file mode 100644
index 0000000..6f76fa5
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/network.go
@@ -0,0 +1,62 @@
+package playwright
+
+import (
+ "strings"
+)
+
+type rawHeaders struct {
+ headersArray []NameValue
+ headersMap map[string][]string
+}
+
+func (r *rawHeaders) Get(name string) string {
+ values := r.GetAll(name)
+ if len(values) == 0 {
+ return ""
+ }
+ sep := ", "
+ if strings.ToLower(name) == "set-cookie" {
+ sep = "\n"
+ }
+ return strings.Join(values, sep)
+}
+
+func (r *rawHeaders) GetAll(name string) []string {
+ name = strings.ToLower(name)
+ if _, ok := r.headersMap[name]; !ok {
+ return []string{}
+ }
+ return r.headersMap[name]
+}
+
+func (r *rawHeaders) Headers() map[string]string {
+ out := make(map[string]string)
+ for key := range r.headersMap {
+ out[key] = r.Get(key)
+ }
+ return out
+}
+
+func (r *rawHeaders) HeadersArray() []NameValue {
+ return r.headersArray
+}
+
+func newRawHeaders(headers interface{}) *rawHeaders {
+ r := &rawHeaders{}
+ r.headersArray = make([]NameValue, 0)
+ r.headersMap = make(map[string][]string)
+ for _, header := range headers.([]interface{}) {
+ entry := header.(map[string]interface{})
+ name := entry["name"].(string)
+ value := entry["value"].(string)
+ r.headersArray = append(r.headersArray, NameValue{
+ Name: name,
+ Value: value,
+ })
+ if _, ok := r.headersMap[strings.ToLower(name)]; !ok {
+ r.headersMap[strings.ToLower(name)] = make([]string, 0)
+ }
+ r.headersMap[strings.ToLower(name)] = append(r.headersMap[strings.ToLower(name)], value)
+ }
+ return r
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/objectFactory.go b/vendor/github.com/playwright-community/playwright-go/objectFactory.go
new file mode 100644
index 0000000..9474c54
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/objectFactory.go
@@ -0,0 +1,74 @@
+package playwright
+
+func createObjectFactory(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) interface{} {
+ switch objectType {
+ case "Android":
+ return nil
+ case "AndroidSocket":
+ return nil
+ case "AndroidDevice":
+ return nil
+ case "APIRequestContext":
+ return newAPIRequestContext(parent, objectType, guid, initializer)
+ case "Artifact":
+ return newArtifact(parent, objectType, guid, initializer)
+ case "BindingCall":
+ return newBindingCall(parent, objectType, guid, initializer)
+ case "Browser":
+ return newBrowser(parent, objectType, guid, initializer)
+ case "BrowserType":
+ return newBrowserType(parent, objectType, guid, initializer)
+ case "BrowserContext":
+ return newBrowserContext(parent, objectType, guid, initializer)
+ case "CDPSession":
+ return newCDPSession(parent, objectType, guid, initializer)
+ case "Dialog":
+ return newDialog(parent, objectType, guid, initializer)
+ case "Electron":
+ return nil
+ case "ElectronApplication":
+ return nil
+ case "ElementHandle":
+ return newElementHandle(parent, objectType, guid, initializer)
+ case "Frame":
+ return newFrame(parent, objectType, guid, initializer)
+ case "JSHandle":
+ return newJSHandle(parent, objectType, guid, initializer)
+ case "JsonPipe":
+ return newJsonPipe(parent, objectType, guid, initializer)
+ case "LocalUtils":
+ localUtils := newLocalUtils(parent, objectType, guid, initializer)
+ if localUtils.connection.localUtils == nil {
+ localUtils.connection.localUtils = localUtils
+ }
+ return localUtils
+ case "Page":
+ return newPage(parent, objectType, guid, initializer)
+ case "Playwright":
+ return newPlaywright(parent, objectType, guid, initializer)
+ case "Request":
+ return newRequest(parent, objectType, guid, initializer)
+ case "Response":
+ return newResponse(parent, objectType, guid, initializer)
+ case "Route":
+ return newRoute(parent, objectType, guid, initializer)
+ case "Selectors":
+ return newSelectorsOwner(parent, objectType, guid, initializer)
+ case "SocksSupport":
+ return nil
+ case "Stream":
+ return newStream(parent, objectType, guid, initializer)
+ case "Tracing":
+ return newTracing(parent, objectType, guid, initializer)
+ case "WebSocket":
+ return newWebsocket(parent, objectType, guid, initializer)
+ case "WebSocketRoute":
+ return newWebSocketRoute(parent, objectType, guid, initializer)
+ case "Worker":
+ return newWorker(parent, objectType, guid, initializer)
+ case "WritableStream":
+ return newWritableStream(parent, objectType, guid, initializer)
+ default:
+ panic(objectType)
+ }
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/page.go b/vendor/github.com/playwright-community/playwright-go/page.go
new file mode 100644
index 0000000..d4271a0
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/page.go
@@ -0,0 +1,1384 @@
+package playwright
+
+import (
+ "encoding/base64"
+ "errors"
+ "fmt"
+ "os"
+ "slices"
+ "sync"
+
+ "github.com/playwright-community/playwright-go/internal/safe"
+)
+
+type pageImpl struct {
+ channelOwner
+ isClosed bool
+ closedOrCrashed chan error
+ video *videoImpl
+ mouse *mouseImpl
+ keyboard *keyboardImpl
+ touchscreen *touchscreenImpl
+ timeoutSettings *timeoutSettings
+ browserContext *browserContextImpl
+ frames []Frame
+ workers []Worker
+ mainFrame Frame
+ routes []*routeHandlerEntry
+ webSocketRoutes []*webSocketRouteHandler
+ viewportSize *Size
+ ownedContext BrowserContext
+ bindings *safe.SyncMap[string, BindingCallFunction]
+ closeReason *string
+ closeWasCalled bool
+ harRouters []*harRouter
+ locatorHandlers map[float64]*locatorHandlerEntry
+}
+
+type locatorHandlerEntry struct {
+ locator *locatorImpl
+ handler func(Locator)
+ times *int
+}
+
+func (p *pageImpl) AddLocatorHandler(locator Locator, handler func(Locator), options ...PageAddLocatorHandlerOptions) error {
+ if locator == nil || handler == nil {
+ return errors.New("locator or handler must not be nil")
+ }
+ if locator.Err() != nil {
+ return locator.Err()
+ }
+
+ var option PageAddLocatorHandlerOptions
+ if len(options) == 1 {
+ option = options[0]
+ if option.Times != nil && *option.Times == 0 {
+ return nil
+ }
+ }
+
+ loc := locator.(*locatorImpl)
+ if loc.frame != p.mainFrame {
+ return errors.New("locator must belong to the main frame of this page")
+ }
+ uid, err := p.channel.Send("registerLocatorHandler", map[string]any{
+ "selector": loc.selector,
+ "noWaitAfter": option.NoWaitAfter,
+ })
+ if err != nil {
+ return err
+ }
+ p.locatorHandlers[uid.(float64)] = &locatorHandlerEntry{locator: loc, handler: handler, times: option.Times}
+ return nil
+}
+
+func (p *pageImpl) onLocatorHandlerTriggered(uid float64) {
+ var remove *bool
+ handler, ok := p.locatorHandlers[uid]
+ if !ok {
+ return
+ }
+ if handler.times != nil {
+ *handler.times--
+ if *handler.times == 0 {
+ remove = Bool(true)
+ }
+ }
+ defer func() {
+ if remove != nil && *remove {
+ delete(p.locatorHandlers, uid)
+ }
+ _, _ = p.connection.WrapAPICall(func() (interface{}, error) {
+ _, err := p.channel.Send("resolveLocatorHandlerNoReply", map[string]any{
+ "uid": uid,
+ "remove": remove,
+ })
+ return nil, err
+ }, true)
+ }()
+
+ handler.handler(handler.locator)
+}
+
+func (p *pageImpl) RemoveLocatorHandler(locator Locator) error {
+ for uid := range p.locatorHandlers {
+ if p.locatorHandlers[uid].locator.equals(locator) {
+ delete(p.locatorHandlers, uid)
+ p.channel.SendNoReply("unregisterLocatorHandler", map[string]any{
+ "uid": uid,
+ })
+ return nil
+ }
+ }
+ return nil
+}
+
+func (p *pageImpl) Context() BrowserContext {
+ return p.browserContext
+}
+
+func (b *pageImpl) Clock() Clock {
+ return b.browserContext.clock
+}
+
+func (p *pageImpl) Close(options ...PageCloseOptions) error {
+ if len(options) == 1 {
+ p.closeReason = options[0].Reason
+ }
+ p.closeWasCalled = true
+ _, err := p.channel.Send("close", options)
+ if err == nil && p.ownedContext != nil {
+ err = p.ownedContext.Close()
+ }
+ if errors.Is(err, ErrTargetClosed) || (len(options) == 1 && options[0].RunBeforeUnload != nil && *(options[0].RunBeforeUnload)) {
+ return nil
+ }
+ return err
+}
+
+func (p *pageImpl) InnerText(selector string, options ...PageInnerTextOptions) (string, error) {
+ if len(options) == 1 {
+ return p.mainFrame.InnerText(selector, FrameInnerTextOptions(options[0]))
+ }
+ return p.mainFrame.InnerText(selector)
+}
+
+func (p *pageImpl) InnerHTML(selector string, options ...PageInnerHTMLOptions) (string, error) {
+ if len(options) == 1 {
+ return p.mainFrame.InnerHTML(selector, FrameInnerHTMLOptions(options[0]))
+ }
+ return p.mainFrame.InnerHTML(selector)
+}
+
+func (p *pageImpl) Opener() (Page, error) {
+ channel := p.initializer["opener"]
+ channelOwner := fromNullableChannel(channel)
+ if channelOwner == nil {
+ // not popup page or opener has been closed
+ return nil, nil
+ }
+ return channelOwner.(*pageImpl), nil
+}
+
+func (p *pageImpl) MainFrame() Frame {
+ return p.mainFrame
+}
+
+func (p *pageImpl) Frame(options ...PageFrameOptions) Frame {
+ option := PageFrameOptions{}
+ if len(options) == 1 {
+ option = options[0]
+ }
+ var matcher *urlMatcher
+ if option.URL != nil {
+ matcher = newURLMatcher(option.URL, p.browserContext.options.BaseURL)
+ }
+
+ for _, f := range p.frames {
+ if option.Name != nil && f.Name() == *option.Name {
+ return f
+ }
+
+ if option.URL != nil && matcher != nil && matcher.Matches(f.URL()) {
+ return f
+ }
+ }
+
+ return nil
+}
+
+func (p *pageImpl) Frames() []Frame {
+ return p.frames
+}
+
+func (p *pageImpl) SetDefaultNavigationTimeout(timeout float64) {
+ p.timeoutSettings.SetDefaultNavigationTimeout(&timeout)
+ p.channel.SendNoReplyInternal("setDefaultNavigationTimeoutNoReply", map[string]interface{}{
+ "timeout": timeout,
+ })
+}
+
+func (p *pageImpl) SetDefaultTimeout(timeout float64) {
+ p.timeoutSettings.SetDefaultTimeout(&timeout)
+ p.channel.SendNoReplyInternal("setDefaultTimeoutNoReply", map[string]interface{}{
+ "timeout": timeout,
+ })
+}
+
+func (p *pageImpl) QuerySelector(selector string, options ...PageQuerySelectorOptions) (ElementHandle, error) {
+ if len(options) == 1 {
+ return p.mainFrame.QuerySelector(selector, FrameQuerySelectorOptions(options[0]))
+ }
+ return p.mainFrame.QuerySelector(selector)
+}
+
+func (p *pageImpl) QuerySelectorAll(selector string) ([]ElementHandle, error) {
+ return p.mainFrame.QuerySelectorAll(selector)
+}
+
+func (p *pageImpl) WaitForSelector(selector string, options ...PageWaitForSelectorOptions) (ElementHandle, error) {
+ if len(options) == 1 {
+ return p.mainFrame.WaitForSelector(selector, FrameWaitForSelectorOptions(options[0]))
+ }
+ return p.mainFrame.WaitForSelector(selector)
+}
+
+func (p *pageImpl) DispatchEvent(selector string, typ string, eventInit interface{}, options ...PageDispatchEventOptions) error {
+ if len(options) == 1 {
+ return p.mainFrame.DispatchEvent(selector, typ, eventInit, FrameDispatchEventOptions(options[0]))
+ }
+ return p.mainFrame.DispatchEvent(selector, typ, eventInit)
+}
+
+func (p *pageImpl) Evaluate(expression string, arg ...interface{}) (interface{}, error) {
+ return p.mainFrame.Evaluate(expression, arg...)
+}
+
+func (p *pageImpl) EvaluateHandle(expression string, arg ...interface{}) (JSHandle, error) {
+ return p.mainFrame.EvaluateHandle(expression, arg...)
+}
+
+func (p *pageImpl) EvalOnSelector(selector string, expression string, arg interface{}, options ...PageEvalOnSelectorOptions) (interface{}, error) {
+ if len(options) == 1 {
+ return p.mainFrame.EvalOnSelector(selector, expression, arg, FrameEvalOnSelectorOptions(options[0]))
+ }
+ return p.mainFrame.EvalOnSelector(selector, expression, arg)
+}
+
+func (p *pageImpl) EvalOnSelectorAll(selector string, expression string, arg ...interface{}) (interface{}, error) {
+ return p.mainFrame.EvalOnSelectorAll(selector, expression, arg...)
+}
+
+func (p *pageImpl) AddScriptTag(options PageAddScriptTagOptions) (ElementHandle, error) {
+ return p.mainFrame.AddScriptTag(FrameAddScriptTagOptions(options))
+}
+
+func (p *pageImpl) AddStyleTag(options PageAddStyleTagOptions) (ElementHandle, error) {
+ return p.mainFrame.AddStyleTag(FrameAddStyleTagOptions(options))
+}
+
+func (p *pageImpl) SetExtraHTTPHeaders(headers map[string]string) error {
+ _, err := p.channel.Send("setExtraHTTPHeaders", map[string]interface{}{
+ "headers": serializeMapToNameAndValue(headers),
+ })
+ return err
+}
+
+func (p *pageImpl) URL() string {
+ return p.mainFrame.URL()
+}
+
+func (p *pageImpl) Unroute(url interface{}, handlers ...routeHandler) error {
+ p.Lock()
+ defer p.Unlock()
+
+ removed, remaining, err := unroute(p.routes, url, handlers...)
+ if err != nil {
+ return err
+ }
+ return p.unrouteInternal(removed, remaining, UnrouteBehaviorDefault)
+}
+
+func (p *pageImpl) unrouteInternal(removed []*routeHandlerEntry, remaining []*routeHandlerEntry, behavior *UnrouteBehavior) error {
+ p.routes = remaining
+ err := p.updateInterceptionPatterns()
+ if err != nil {
+ return err
+ }
+ if behavior == nil || behavior == UnrouteBehaviorDefault {
+ return nil
+ }
+ wg := &sync.WaitGroup{}
+ for _, entry := range removed {
+ wg.Add(1)
+ go func(entry *routeHandlerEntry) {
+ defer wg.Done()
+ entry.Stop(string(*behavior))
+ }(entry)
+ }
+ wg.Wait()
+ return nil
+}
+
+func (p *pageImpl) disposeHarRouters() {
+ for _, router := range p.harRouters {
+ router.dispose()
+ }
+ p.harRouters = make([]*harRouter, 0)
+}
+
+func (p *pageImpl) UnrouteAll(options ...PageUnrouteAllOptions) error {
+ var behavior *UnrouteBehavior
+ if len(options) == 1 {
+ behavior = options[0].Behavior
+ }
+ p.Lock()
+ defer p.Unlock()
+ defer p.disposeHarRouters()
+ return p.unrouteInternal(p.routes, []*routeHandlerEntry{}, behavior)
+}
+
+func (p *pageImpl) Content() (string, error) {
+ return p.mainFrame.Content()
+}
+
+func (p *pageImpl) SetContent(html string, options ...PageSetContentOptions) error {
+ if len(options) == 1 {
+ return p.mainFrame.SetContent(html, FrameSetContentOptions(options[0]))
+ }
+ return p.mainFrame.SetContent(html)
+}
+
+func (p *pageImpl) Goto(url string, options ...PageGotoOptions) (Response, error) {
+ if len(options) == 1 {
+ return p.mainFrame.Goto(url, FrameGotoOptions(options[0]))
+ }
+ return p.mainFrame.Goto(url)
+}
+
+func (p *pageImpl) Reload(options ...PageReloadOptions) (Response, error) {
+ channel, err := p.channel.Send("reload", options)
+ if err != nil {
+ return nil, err
+ }
+ channelOwner := fromNullableChannel(channel)
+ if channelOwner == nil {
+ return nil, nil
+ }
+ return channelOwner.(*responseImpl), nil
+}
+
+func (p *pageImpl) WaitForLoadState(options ...PageWaitForLoadStateOptions) error {
+ if len(options) == 1 {
+ return p.mainFrame.WaitForLoadState(FrameWaitForLoadStateOptions(options[0]))
+ }
+ return p.mainFrame.WaitForLoadState()
+}
+
+func (p *pageImpl) GoBack(options ...PageGoBackOptions) (Response, error) {
+ channel, err := p.channel.Send("goBack", options)
+ if err != nil {
+ return nil, err
+ }
+ channelOwner := fromNullableChannel(channel)
+ if channelOwner == nil {
+ // can not go back
+ return nil, nil
+ }
+ return channelOwner.(*responseImpl), nil
+}
+
+func (p *pageImpl) GoForward(options ...PageGoForwardOptions) (Response, error) {
+ channel, err := p.channel.Send("goForward", options)
+ if err != nil {
+ return nil, err
+ }
+ channelOwner := fromNullableChannel(channel)
+ if channelOwner == nil {
+ // can not go forward
+ return nil, nil
+ }
+ return channelOwner.(*responseImpl), nil
+}
+
+func (p *pageImpl) EmulateMedia(options ...PageEmulateMediaOptions) error {
+ _, err := p.channel.Send("emulateMedia", options)
+ if err != nil {
+ return err
+ }
+ return err
+}
+
+func (p *pageImpl) SetViewportSize(width, height int) error {
+ _, err := p.channel.Send("setViewportSize", map[string]interface{}{
+ "viewportSize": map[string]interface{}{
+ "width": width,
+ "height": height,
+ },
+ })
+ if err != nil {
+ return err
+ }
+ p.viewportSize.Width = width
+ p.viewportSize.Height = height
+ return nil
+}
+
+func (p *pageImpl) ViewportSize() *Size {
+ return p.viewportSize
+}
+
+func (p *pageImpl) BringToFront() error {
+ _, err := p.channel.Send("bringToFront")
+ return err
+}
+
+func (p *pageImpl) Type(selector, text string, options ...PageTypeOptions) error {
+ if len(options) == 1 {
+ return p.mainFrame.Type(selector, text, FrameTypeOptions(options[0]))
+ }
+ return p.mainFrame.Type(selector, text)
+}
+
+func (p *pageImpl) Fill(selector, text string, options ...PageFillOptions) error {
+ if len(options) == 1 {
+ return p.mainFrame.Fill(selector, text, FrameFillOptions(options[0]))
+ }
+ return p.mainFrame.Fill(selector, text)
+}
+
+func (p *pageImpl) Press(selector, key string, options ...PagePressOptions) error {
+ if len(options) == 1 {
+ return p.mainFrame.Press(selector, key, FramePressOptions(options[0]))
+ }
+ return p.mainFrame.Press(selector, key)
+}
+
+func (p *pageImpl) Title() (string, error) {
+ return p.mainFrame.Title()
+}
+
+func (p *pageImpl) Workers() []Worker {
+ return p.workers
+}
+
+func (p *pageImpl) Request() APIRequestContext {
+ return p.Context().Request()
+}
+
+func (p *pageImpl) Screenshot(options ...PageScreenshotOptions) ([]byte, error) {
+ var path *string
+ overrides := map[string]interface{}{}
+ if len(options) == 1 {
+ path = options[0].Path
+ options[0].Path = nil
+ if options[0].Mask != nil {
+ masks := make([]map[string]interface{}, 0)
+ for _, m := range options[0].Mask {
+ if m.Err() != nil { // ErrLocatorNotSameFrame
+ return nil, m.Err()
+ }
+ l, ok := m.(*locatorImpl)
+ if ok {
+ masks = append(masks, map[string]interface{}{
+ "selector": l.selector,
+ "frame": l.frame.channel,
+ })
+ }
+ }
+ overrides["mask"] = masks
+ }
+ }
+ data, err := p.channel.Send("screenshot", options, overrides)
+ if err != nil {
+ return nil, err
+ }
+ image, err := base64.StdEncoding.DecodeString(data.(string))
+ if err != nil {
+ return nil, fmt.Errorf("could not decode base64 :%w", err)
+ }
+ if path != nil {
+ if err := os.WriteFile(*path, image, 0o644); err != nil {
+ return nil, err
+ }
+ }
+ return image, nil
+}
+
+func (p *pageImpl) PDF(options ...PagePdfOptions) ([]byte, error) {
+ var path *string
+ if len(options) == 1 {
+ path = options[0].Path
+ }
+ data, err := p.channel.Send("pdf", options)
+ if err != nil {
+ return nil, err
+ }
+ pdf, err := base64.StdEncoding.DecodeString(data.(string))
+ if err != nil {
+ return nil, fmt.Errorf("could not decode base64 :%w", err)
+ }
+ if path != nil {
+ if err := os.WriteFile(*path, pdf, 0o644); err != nil {
+ return nil, err
+ }
+ }
+ return pdf, nil
+}
+
+func (p *pageImpl) Click(selector string, options ...PageClickOptions) error {
+ if len(options) == 1 {
+ return p.mainFrame.Click(selector, FrameClickOptions(options[0]))
+ }
+ return p.mainFrame.Click(selector)
+}
+
+func (p *pageImpl) WaitForEvent(event string, options ...PageWaitForEventOptions) (interface{}, error) {
+ return p.waiterForEvent(event, options...).Wait()
+}
+
+func (p *pageImpl) waiterForEvent(event string, options ...PageWaitForEventOptions) *waiter {
+ timeout := p.timeoutSettings.Timeout()
+ var predicate interface{} = nil
+ if len(options) == 1 {
+ if options[0].Timeout != nil {
+ timeout = *options[0].Timeout
+ }
+ predicate = options[0].Predicate
+ }
+ waiter := newWaiter().WithTimeout(timeout)
+ waiter.RejectOnEvent(p, "close", p.closeErrorWithReason())
+ waiter.RejectOnEvent(p, "crash", errors.New("page crashed"))
+ return waiter.WaitForEvent(p, event, predicate)
+}
+
+func (p *pageImpl) waiterForRequest(url interface{}, options ...PageExpectRequestOptions) *waiter {
+ option := PageExpectRequestOptions{}
+ if len(options) == 1 {
+ option = options[0]
+ }
+ if option.Timeout == nil {
+ option.Timeout = Float(p.timeoutSettings.Timeout())
+ }
+ var matcher *urlMatcher
+ if url != nil {
+ matcher = newURLMatcher(url, p.browserContext.options.BaseURL)
+ }
+ predicate := func(req *requestImpl) bool {
+ if matcher != nil {
+ return matcher.Matches(req.URL())
+ }
+ return true
+ }
+
+ waiter := newWaiter().WithTimeout(*option.Timeout)
+ return waiter.WaitForEvent(p, "request", predicate)
+}
+
+func (p *pageImpl) waiterForResponse(url interface{}, options ...PageExpectResponseOptions) *waiter {
+ option := PageExpectResponseOptions{}
+ if len(options) == 1 {
+ option = options[0]
+ }
+ if option.Timeout == nil {
+ option.Timeout = Float(p.timeoutSettings.Timeout())
+ }
+ var matcher *urlMatcher
+ if url != nil {
+ matcher = newURLMatcher(url, p.browserContext.options.BaseURL)
+ }
+ predicate := func(req *responseImpl) bool {
+ if matcher != nil {
+ return matcher.Matches(req.URL())
+ }
+ return true
+ }
+
+ waiter := newWaiter().WithTimeout(*option.Timeout)
+ return waiter.WaitForEvent(p, "response", predicate)
+}
+
+func (p *pageImpl) ExpectEvent(event string, cb func() error, options ...PageExpectEventOptions) (interface{}, error) {
+ if len(options) == 1 {
+ return p.waiterForEvent(event, PageWaitForEventOptions(options[0])).RunAndWait(cb)
+ }
+ return p.waiterForEvent(event).RunAndWait(cb)
+}
+
+func (p *pageImpl) ExpectNavigation(cb func() error, options ...PageExpectNavigationOptions) (Response, error) {
+ if len(options) == 1 {
+ return p.mainFrame.ExpectNavigation(cb, FrameExpectNavigationOptions(options[0]))
+ }
+ return p.mainFrame.ExpectNavigation(cb)
+}
+
+func (p *pageImpl) ExpectConsoleMessage(cb func() error, options ...PageExpectConsoleMessageOptions) (ConsoleMessage, error) {
+ option := PageWaitForEventOptions{}
+ if len(options) == 1 {
+ option.Timeout = options[0].Timeout
+ option.Predicate = options[0].Predicate
+ }
+ ret, err := p.waiterForEvent("console", option).RunAndWait(cb)
+ if ret == nil {
+ return nil, err
+ }
+ return ret.(*consoleMessageImpl), err
+}
+
+func (p *pageImpl) ExpectDownload(cb func() error, options ...PageExpectDownloadOptions) (Download, error) {
+ option := PageWaitForEventOptions{}
+ if len(options) == 1 {
+ option.Timeout = options[0].Timeout
+ option.Predicate = options[0].Predicate
+ }
+ ret, err := p.waiterForEvent("download", option).RunAndWait(cb)
+ if ret == nil {
+ return nil, err
+ }
+ return ret.(*downloadImpl), err
+}
+
+func (p *pageImpl) ExpectFileChooser(cb func() error, options ...PageExpectFileChooserOptions) (FileChooser, error) {
+ option := PageWaitForEventOptions{}
+ if len(options) == 1 {
+ option.Timeout = options[0].Timeout
+ option.Predicate = options[0].Predicate
+ }
+ ret, err := p.waiterForEvent("filechooser", option).RunAndWait(cb)
+ if ret == nil {
+ return nil, err
+ }
+ return ret.(*fileChooserImpl), err
+}
+
+func (p *pageImpl) ExpectPopup(cb func() error, options ...PageExpectPopupOptions) (Page, error) {
+ option := PageWaitForEventOptions{}
+ if len(options) == 1 {
+ option.Timeout = options[0].Timeout
+ option.Predicate = options[0].Predicate
+ }
+ ret, err := p.waiterForEvent("popup", option).RunAndWait(cb)
+ if ret == nil {
+ return nil, err
+ }
+ return ret.(*pageImpl), err
+}
+
+func (p *pageImpl) ExpectResponse(url interface{}, cb func() error, options ...PageExpectResponseOptions) (Response, error) {
+ ret, err := p.waiterForResponse(url, options...).RunAndWait(cb)
+ if ret == nil {
+ return nil, err
+ }
+ return ret.(*responseImpl), err
+}
+
+func (p *pageImpl) ExpectRequest(url interface{}, cb func() error, options ...PageExpectRequestOptions) (Request, error) {
+ ret, err := p.waiterForRequest(url, options...).RunAndWait(cb)
+ if ret == nil {
+ return nil, err
+ }
+ return ret.(*requestImpl), err
+}
+
+func (p *pageImpl) ExpectRequestFinished(cb func() error, options ...PageExpectRequestFinishedOptions) (Request, error) {
+ option := PageWaitForEventOptions{}
+ if len(options) == 1 {
+ option.Timeout = options[0].Timeout
+ option.Predicate = options[0].Predicate
+ }
+ ret, err := p.waiterForEvent("requestfinished", option).RunAndWait(cb)
+ if ret == nil {
+ return nil, err
+ }
+ return ret.(*requestImpl), err
+}
+
+func (p *pageImpl) ExpectWebSocket(cb func() error, options ...PageExpectWebSocketOptions) (WebSocket, error) {
+ option := PageWaitForEventOptions{}
+ if len(options) == 1 {
+ option.Timeout = options[0].Timeout
+ option.Predicate = options[0].Predicate
+ }
+ ret, err := p.waiterForEvent("websocket", option).RunAndWait(cb)
+ if ret == nil {
+ return nil, err
+ }
+ return ret.(*webSocketImpl), err
+}
+
+func (p *pageImpl) ExpectWorker(cb func() error, options ...PageExpectWorkerOptions) (Worker, error) {
+ option := PageWaitForEventOptions{}
+ if len(options) == 1 {
+ option.Timeout = options[0].Timeout
+ option.Predicate = options[0].Predicate
+ }
+ ret, err := p.waiterForEvent("worker", option).RunAndWait(cb)
+ if ret == nil {
+ return nil, err
+ }
+ return ret.(*workerImpl), err
+}
+
+func (p *pageImpl) Route(url interface{}, handler routeHandler, times ...int) error {
+ p.Lock()
+ defer p.Unlock()
+ p.routes = slices.Insert(p.routes, 0, newRouteHandlerEntry(newURLMatcher(url, p.browserContext.options.BaseURL), handler, times...))
+ return p.updateInterceptionPatterns()
+}
+
+func (p *pageImpl) GetAttribute(selector string, name string, options ...PageGetAttributeOptions) (string, error) {
+ if len(options) == 1 {
+ return p.mainFrame.GetAttribute(selector, name, FrameGetAttributeOptions(options[0]))
+ }
+ return p.mainFrame.GetAttribute(selector, name)
+}
+
+func (p *pageImpl) Hover(selector string, options ...PageHoverOptions) error {
+ if len(options) == 1 {
+ return p.mainFrame.Hover(selector, FrameHoverOptions(options[0]))
+ }
+ return p.mainFrame.Hover(selector)
+}
+
+func (p *pageImpl) IsClosed() bool {
+ return p.isClosed
+}
+
+func (p *pageImpl) AddInitScript(script Script) error {
+ var source string
+ if script.Content != nil {
+ source = *script.Content
+ }
+ if script.Path != nil {
+ content, err := os.ReadFile(*script.Path)
+ if err != nil {
+ return err
+ }
+ source = string(content)
+ }
+ _, err := p.channel.Send("addInitScript", map[string]interface{}{
+ "source": source,
+ })
+ return err
+}
+
+func (p *pageImpl) Keyboard() Keyboard {
+ return p.keyboard
+}
+
+func (p *pageImpl) Mouse() Mouse {
+ return p.mouse
+}
+
+func (p *pageImpl) RouteFromHAR(har string, options ...PageRouteFromHAROptions) error {
+ opt := PageRouteFromHAROptions{}
+ if len(options) == 1 {
+ opt = options[0]
+ }
+ if opt.Update != nil && *opt.Update {
+ return p.browserContext.recordIntoHar(har, browserContextRecordIntoHarOptions{
+ Page: p,
+ URL: opt.URL,
+ })
+ }
+ notFound := opt.NotFound
+ if notFound == nil {
+ notFound = HarNotFoundAbort
+ }
+ router := newHarRouter(p.connection.localUtils, har, *notFound, opt.URL)
+ p.harRouters = append(p.harRouters, router)
+ return router.addPageRoute(p)
+}
+
+func (p *pageImpl) Touchscreen() Touchscreen {
+ return p.touchscreen
+}
+
+func newPage(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *pageImpl {
+ viewportSize := &Size{}
+ if _, ok := initializer["viewportSize"].(map[string]interface{}); ok {
+ viewportSize.Height = int(initializer["viewportSize"].(map[string]interface{})["height"].(float64))
+ viewportSize.Width = int(initializer["viewportSize"].(map[string]interface{})["width"].(float64))
+ }
+ bt := &pageImpl{
+ workers: make([]Worker, 0),
+ routes: make([]*routeHandlerEntry, 0),
+ bindings: safe.NewSyncMap[string, BindingCallFunction](),
+ viewportSize: viewportSize,
+ harRouters: make([]*harRouter, 0),
+ locatorHandlers: make(map[float64]*locatorHandlerEntry, 0),
+ }
+ bt.createChannelOwner(bt, parent, objectType, guid, initializer)
+ bt.browserContext = fromChannel(parent.channel).(*browserContextImpl)
+ bt.timeoutSettings = newTimeoutSettings(bt.browserContext.timeoutSettings)
+ mainframe := fromChannel(initializer["mainFrame"]).(*frameImpl)
+ mainframe.page = bt
+ bt.mainFrame = mainframe
+ bt.frames = []Frame{mainframe}
+ bt.mouse = newMouse(bt.channel)
+ bt.keyboard = newKeyboard(bt.channel)
+ bt.touchscreen = newTouchscreen(bt.channel)
+ bt.channel.On("bindingCall", func(params map[string]interface{}) {
+ bt.onBinding(fromChannel(params["binding"]).(*bindingCallImpl))
+ })
+ bt.channel.On("close", bt.onClose)
+ bt.channel.On("crash", func() {
+ bt.Emit("crash", bt)
+ })
+ bt.channel.On("domcontentloaded", func() {
+ bt.Emit("domcontentloaded", bt)
+ })
+ bt.channel.On("fileChooser", func(ev map[string]interface{}) {
+ bt.Emit("filechooser", newFileChooser(bt, fromChannel(ev["element"]).(*elementHandleImpl), ev["isMultiple"].(bool)))
+ })
+ bt.channel.On("frameAttached", func(ev map[string]interface{}) {
+ bt.onFrameAttached(fromChannel(ev["frame"]).(*frameImpl))
+ })
+ bt.channel.On("frameDetached", func(ev map[string]interface{}) {
+ bt.onFrameDetached(fromChannel(ev["frame"]).(*frameImpl))
+ })
+ bt.channel.On("locatorHandlerTriggered", func(ev map[string]interface{}) {
+ bt.channel.CreateTask(func() {
+ bt.onLocatorHandlerTriggered(ev["uid"].(float64))
+ })
+ })
+ bt.channel.On(
+ "load", func(ev map[string]interface{}) {
+ bt.Emit("load", bt)
+ },
+ )
+ bt.channel.On("popup", func(ev map[string]interface{}) {
+ bt.Emit("popup", fromChannel(ev["page"]).(*pageImpl))
+ })
+ bt.channel.On("route", func(ev map[string]interface{}) {
+ bt.channel.CreateTask(func() {
+ bt.onRoute(fromChannel(ev["route"]).(*routeImpl))
+ })
+ })
+ bt.channel.On("download", func(ev map[string]interface{}) {
+ url := ev["url"].(string)
+ suggestedFilename := ev["suggestedFilename"].(string)
+ artifact := fromChannel(ev["artifact"]).(*artifactImpl)
+ bt.Emit("download", newDownload(bt, url, suggestedFilename, artifact))
+ })
+ bt.channel.On("video", func(params map[string]interface{}) {
+ artifact := fromChannel(params["artifact"]).(*artifactImpl)
+ bt.Video().(*videoImpl).artifactReady(artifact)
+ })
+ bt.channel.On("webSocket", func(ev map[string]interface{}) {
+ bt.Emit("websocket", fromChannel(ev["webSocket"]).(*webSocketImpl))
+ })
+ bt.channel.On("webSocketRoute", func(ev map[string]interface{}) {
+ bt.channel.CreateTask(func() {
+ bt.onWebSocketRoute(fromChannel(ev["webSocketRoute"]).(*webSocketRouteImpl))
+ })
+ })
+
+ bt.channel.On("worker", func(ev map[string]interface{}) {
+ bt.onWorker(fromChannel(ev["worker"]).(*workerImpl))
+ })
+ bt.closedOrCrashed = make(chan error, 1)
+ bt.OnClose(func(Page) {
+ select {
+ case bt.closedOrCrashed <- bt.closeErrorWithReason():
+ default:
+ }
+ })
+ bt.OnCrash(func(Page) {
+ select {
+ case bt.closedOrCrashed <- ErrTargetClosed:
+ default:
+ }
+ })
+ bt.setEventSubscriptionMapping(map[string]string{
+ "console": "console",
+ "dialog": "dialog",
+ "request": "request",
+ "response": "response",
+ "requestfinished": "requestFinished",
+ "responsefailed": "responseFailed",
+ "filechooser": "fileChooser",
+ })
+
+ return bt
+}
+
+func (p *pageImpl) closeErrorWithReason() error {
+ if p.closeReason != nil {
+ return targetClosedError(p.closeReason)
+ }
+ return targetClosedError(p.browserContext.effectiveCloseReason())
+}
+
+func (p *pageImpl) onBinding(binding *bindingCallImpl) {
+ function, ok := p.bindings.Load(binding.initializer["name"].(string))
+ if !ok || function == nil {
+ return
+ }
+ go binding.Call(function)
+}
+
+func (p *pageImpl) onFrameAttached(frame *frameImpl) {
+ frame.page = p
+ p.frames = append(p.frames, frame)
+ p.Emit("frameattached", frame)
+}
+
+func (p *pageImpl) onFrameDetached(frame *frameImpl) {
+ frame.detached = true
+ frames := make([]Frame, 0)
+ for i := 0; i < len(p.frames); i++ {
+ if p.frames[i] != frame {
+ frames = append(frames, frame)
+ }
+ }
+ if len(frames) != len(p.frames) {
+ p.frames = frames
+ }
+ p.Emit("framedetached", frame)
+}
+
+func (p *pageImpl) onRoute(route *routeImpl) {
+ p.Lock()
+ route.context = p.browserContext
+ routes := make([]*routeHandlerEntry, len(p.routes))
+ copy(routes, p.routes)
+ p.Unlock()
+
+ checkInterceptionIfNeeded := func() {
+ p.Lock()
+ defer p.Unlock()
+ if len(p.routes) == 0 {
+ _, err := p.connection.WrapAPICall(func() (interface{}, error) {
+ err := p.updateInterceptionPatterns()
+ return nil, err
+ }, true)
+ if err != nil {
+ logger.Error("could not update interception patterns", "error", err)
+ }
+ }
+ }
+
+ url := route.Request().URL()
+ for _, handlerEntry := range routes {
+ // If the page was closed we stall all requests right away.
+ if p.closeWasCalled || p.browserContext.closeWasCalled {
+ return
+ }
+ if !handlerEntry.Matches(url) {
+ continue
+ }
+ if !slices.ContainsFunc(p.routes, func(entry *routeHandlerEntry) bool {
+ return entry == handlerEntry
+ }) {
+ continue
+ }
+ if handlerEntry.WillExceed() {
+ p.routes = slices.DeleteFunc(p.routes, func(rhe *routeHandlerEntry) bool {
+ return rhe == handlerEntry
+ })
+ }
+ handled := handlerEntry.Handle(route)
+ checkInterceptionIfNeeded()
+
+ if <-handled {
+ return
+ }
+ }
+ p.browserContext.onRoute(route)
+}
+
+func (p *pageImpl) updateInterceptionPatterns() error {
+ patterns := prepareInterceptionPatterns(p.routes)
+ _, err := p.channel.Send("setNetworkInterceptionPatterns", map[string]interface{}{
+ "patterns": patterns,
+ })
+ return err
+}
+
+func (p *pageImpl) onWorker(worker *workerImpl) {
+ p.workers = append(p.workers, worker)
+ worker.page = p
+ p.Emit("worker", worker)
+}
+
+func (p *pageImpl) onClose() {
+ p.isClosed = true
+ newPages := []Page{}
+ newBackgoundPages := []Page{}
+ if p.browserContext != nil {
+ p.browserContext.Lock()
+ for _, page := range p.browserContext.pages {
+ if page != p {
+ newPages = append(newPages, page)
+ }
+ }
+ for _, page := range p.browserContext.backgroundPages {
+ if page != p {
+ newBackgoundPages = append(newBackgoundPages, page)
+ }
+ }
+ p.browserContext.pages = newPages
+ p.browserContext.backgroundPages = newBackgoundPages
+ p.browserContext.Unlock()
+ }
+ p.disposeHarRouters()
+ p.Emit("close", p)
+}
+
+func (p *pageImpl) SetInputFiles(selector string, files interface{}, options ...PageSetInputFilesOptions) error {
+ if len(options) == 1 {
+ return p.mainFrame.SetInputFiles(selector, files, FrameSetInputFilesOptions(options[0]))
+ }
+ return p.mainFrame.SetInputFiles(selector, files)
+}
+
+func (p *pageImpl) Check(selector string, options ...PageCheckOptions) error {
+ if len(options) == 1 {
+ return p.mainFrame.Check(selector, FrameCheckOptions(options[0]))
+ }
+ return p.mainFrame.Check(selector)
+}
+
+func (p *pageImpl) Uncheck(selector string, options ...PageUncheckOptions) error {
+ if len(options) == 1 {
+ return p.mainFrame.Uncheck(selector, FrameUncheckOptions(options[0]))
+ }
+ return p.mainFrame.Uncheck(selector)
+}
+
+func (p *pageImpl) WaitForTimeout(timeout float64) {
+ p.mainFrame.WaitForTimeout(timeout)
+}
+
+func (p *pageImpl) WaitForFunction(expression string, arg interface{}, options ...PageWaitForFunctionOptions) (JSHandle, error) {
+ if len(options) == 1 {
+ return p.mainFrame.WaitForFunction(expression, arg, FrameWaitForFunctionOptions(options[0]))
+ }
+ return p.mainFrame.WaitForFunction(expression, arg)
+}
+
+func (p *pageImpl) Dblclick(expression string, options ...PageDblclickOptions) error {
+ if len(options) == 1 {
+ return p.mainFrame.Dblclick(expression, FrameDblclickOptions(options[0]))
+ }
+ return p.mainFrame.Dblclick(expression)
+}
+
+func (p *pageImpl) Focus(expression string, options ...PageFocusOptions) error {
+ if len(options) == 1 {
+ return p.mainFrame.Focus(expression, FrameFocusOptions(options[0]))
+ }
+ return p.mainFrame.Focus(expression)
+}
+
+func (p *pageImpl) TextContent(selector string, options ...PageTextContentOptions) (string, error) {
+ if len(options) == 1 {
+ return p.mainFrame.TextContent(selector, FrameTextContentOptions(options[0]))
+ }
+ return p.mainFrame.TextContent(selector)
+}
+
+func (p *pageImpl) Video() Video {
+ p.Lock()
+ defer p.Unlock()
+
+ if p.video == nil {
+ p.video = newVideo(p)
+ }
+ return p.video
+}
+
+func (p *pageImpl) Tap(selector string, options ...PageTapOptions) error {
+ if len(options) == 1 {
+ return p.mainFrame.Tap(selector, FrameTapOptions(options[0]))
+ }
+ return p.mainFrame.Tap(selector)
+}
+
+func (p *pageImpl) ExposeFunction(name string, binding ExposedFunction) error {
+ return p.ExposeBinding(name, func(source *BindingSource, args ...interface{}) interface{} {
+ return binding(args...)
+ })
+}
+
+func (p *pageImpl) ExposeBinding(name string, binding BindingCallFunction, handle ...bool) error {
+ needsHandle := false
+ if len(handle) == 1 {
+ needsHandle = handle[0]
+ }
+ if _, ok := p.bindings.Load(name); ok {
+ return fmt.Errorf("Function '%s' has been already registered", name)
+ }
+ if _, ok := p.browserContext.bindings.Load(name); ok {
+ return fmt.Errorf("Function '%s' has been already registered in the browser context", name)
+ }
+ _, err := p.channel.Send("exposeBinding", map[string]interface{}{
+ "name": name,
+ "needsHandle": needsHandle,
+ })
+ if err != nil {
+ return err
+ }
+ p.bindings.Store(name, binding)
+ return nil
+}
+
+func (p *pageImpl) SelectOption(selector string, values SelectOptionValues, options ...PageSelectOptionOptions) ([]string, error) {
+ if len(options) == 1 {
+ return p.mainFrame.SelectOption(selector, values, FrameSelectOptionOptions(options[0]))
+ }
+ return p.mainFrame.SelectOption(selector, values)
+}
+
+func (p *pageImpl) IsChecked(selector string, options ...PageIsCheckedOptions) (bool, error) {
+ if len(options) == 1 {
+ return p.mainFrame.IsChecked(selector, FrameIsCheckedOptions(options[0]))
+ }
+ return p.mainFrame.IsChecked(selector)
+}
+
+func (p *pageImpl) IsDisabled(selector string, options ...PageIsDisabledOptions) (bool, error) {
+ if len(options) == 1 {
+ return p.mainFrame.IsDisabled(selector, FrameIsDisabledOptions(options[0]))
+ }
+ return p.mainFrame.IsDisabled(selector)
+}
+
+func (p *pageImpl) IsEditable(selector string, options ...PageIsEditableOptions) (bool, error) {
+ if len(options) == 1 {
+ return p.mainFrame.IsEditable(selector, FrameIsEditableOptions(options[0]))
+ }
+ return p.mainFrame.IsEditable(selector)
+}
+
+func (p *pageImpl) IsEnabled(selector string, options ...PageIsEnabledOptions) (bool, error) {
+ if len(options) == 1 {
+ return p.mainFrame.IsEnabled(selector, FrameIsEnabledOptions(options[0]))
+ }
+ return p.mainFrame.IsEnabled(selector)
+}
+
+func (p *pageImpl) IsHidden(selector string, options ...PageIsHiddenOptions) (bool, error) {
+ if len(options) == 1 {
+ return p.mainFrame.IsHidden(selector, FrameIsHiddenOptions(options[0]))
+ }
+ return p.mainFrame.IsHidden(selector)
+}
+
+func (p *pageImpl) IsVisible(selector string, options ...PageIsVisibleOptions) (bool, error) {
+ if len(options) == 1 {
+ return p.mainFrame.IsVisible(selector, FrameIsVisibleOptions(options[0]))
+ }
+ return p.mainFrame.IsVisible(selector)
+}
+
+func (p *pageImpl) DragAndDrop(source, target string, options ...PageDragAndDropOptions) error {
+ if len(options) == 1 {
+ return p.mainFrame.DragAndDrop(source, target, FrameDragAndDropOptions(options[0]))
+ }
+ return p.mainFrame.DragAndDrop(source, target)
+}
+
+func (p *pageImpl) Pause() (err error) {
+ defaultNavigationTimout := p.browserContext.timeoutSettings.DefaultNavigationTimeout()
+ defaultTimeout := p.browserContext.timeoutSettings.DefaultTimeout()
+ p.browserContext.SetDefaultNavigationTimeout(0)
+ p.browserContext.SetDefaultTimeout(0)
+ select {
+ case err = <-p.closedOrCrashed:
+ case err = <-p.browserContext.pause():
+ }
+ if err != nil {
+ return err
+ }
+ p.browserContext.setDefaultNavigationTimeoutImpl(defaultNavigationTimout)
+ p.browserContext.setDefaultTimeoutImpl(defaultTimeout)
+ return
+}
+
+func (p *pageImpl) InputValue(selector string, options ...PageInputValueOptions) (string, error) {
+ if len(options) == 1 {
+ return p.mainFrame.InputValue(selector, FrameInputValueOptions(options[0]))
+ }
+ return p.mainFrame.InputValue(selector)
+}
+
+func (p *pageImpl) WaitForURL(url interface{}, options ...PageWaitForURLOptions) error {
+ if len(options) == 1 {
+ return p.mainFrame.WaitForURL(url, FrameWaitForURLOptions(options[0]))
+ }
+ return p.mainFrame.WaitForURL(url)
+}
+
+func (p *pageImpl) SetChecked(selector string, checked bool, options ...PageSetCheckedOptions) error {
+ if len(options) == 1 {
+ return p.mainFrame.SetChecked(selector, checked, FrameSetCheckedOptions(options[0]))
+ }
+ return p.mainFrame.SetChecked(selector, checked)
+}
+
+func (p *pageImpl) Locator(selector string, options ...PageLocatorOptions) Locator {
+ var option FrameLocatorOptions
+ if len(options) == 1 {
+ option = FrameLocatorOptions(options[0])
+ }
+ return p.mainFrame.Locator(selector, option)
+}
+
+func (p *pageImpl) GetByAltText(text interface{}, options ...PageGetByAltTextOptions) Locator {
+ exact := false
+ if len(options) == 1 {
+ if *options[0].Exact {
+ exact = true
+ }
+ }
+ return p.Locator(getByAltTextSelector(text, exact))
+}
+
+func (p *pageImpl) GetByLabel(text interface{}, options ...PageGetByLabelOptions) Locator {
+ exact := false
+ if len(options) == 1 {
+ if *options[0].Exact {
+ exact = true
+ }
+ }
+ return p.Locator(getByLabelSelector(text, exact))
+}
+
+func (p *pageImpl) GetByPlaceholder(text interface{}, options ...PageGetByPlaceholderOptions) Locator {
+ exact := false
+ if len(options) == 1 {
+ if *options[0].Exact {
+ exact = true
+ }
+ }
+ return p.Locator(getByPlaceholderSelector(text, exact))
+}
+
+func (p *pageImpl) GetByRole(role AriaRole, options ...PageGetByRoleOptions) Locator {
+ if len(options) == 1 {
+ return p.Locator(getByRoleSelector(role, LocatorGetByRoleOptions(options[0])))
+ }
+ return p.Locator(getByRoleSelector(role))
+}
+
+func (p *pageImpl) GetByTestId(testId interface{}) Locator {
+ return p.Locator(getByTestIdSelector(getTestIdAttributeName(), testId))
+}
+
+func (p *pageImpl) GetByText(text interface{}, options ...PageGetByTextOptions) Locator {
+ exact := false
+ if len(options) == 1 {
+ if *options[0].Exact {
+ exact = true
+ }
+ }
+ return p.Locator(getByTextSelector(text, exact))
+}
+
+func (p *pageImpl) GetByTitle(text interface{}, options ...PageGetByTitleOptions) Locator {
+ exact := false
+ if len(options) == 1 {
+ if *options[0].Exact {
+ exact = true
+ }
+ }
+ return p.Locator(getByTitleSelector(text, exact))
+}
+
+func (p *pageImpl) FrameLocator(selector string) FrameLocator {
+ return p.mainFrame.FrameLocator(selector)
+}
+
+func (p *pageImpl) OnClose(fn func(Page)) {
+ p.On("close", fn)
+}
+
+func (p *pageImpl) OnConsole(fn func(ConsoleMessage)) {
+ p.On("console", fn)
+}
+
+func (p *pageImpl) OnCrash(fn func(Page)) {
+ p.On("crash", fn)
+}
+
+func (p *pageImpl) OnDialog(fn func(Dialog)) {
+ p.On("dialog", fn)
+}
+
+func (p *pageImpl) OnDOMContentLoaded(fn func(Page)) {
+ p.On("domcontentloaded", fn)
+}
+
+func (p *pageImpl) OnDownload(fn func(Download)) {
+ p.On("download", fn)
+}
+
+func (p *pageImpl) OnFileChooser(fn func(FileChooser)) {
+ p.On("filechooser", fn)
+}
+
+func (p *pageImpl) OnFrameAttached(fn func(Frame)) {
+ p.On("frameattached", fn)
+}
+
+func (p *pageImpl) OnFrameDetached(fn func(Frame)) {
+ p.On("framedetached", fn)
+}
+
+func (p *pageImpl) OnFrameNavigated(fn func(Frame)) {
+ p.On("framenavigated", fn)
+}
+
+func (p *pageImpl) OnLoad(fn func(Page)) {
+ p.On("load", fn)
+}
+
+func (p *pageImpl) OnPageError(fn func(error)) {
+ p.On("pageerror", fn)
+}
+
+func (p *pageImpl) OnPopup(fn func(Page)) {
+ p.On("popup", fn)
+}
+
+func (p *pageImpl) OnRequest(fn func(Request)) {
+ p.On("request", fn)
+}
+
+func (p *pageImpl) OnRequestFailed(fn func(Request)) {
+ p.On("requestfailed", fn)
+}
+
+func (p *pageImpl) OnRequestFinished(fn func(Request)) {
+ p.On("requestfinished", fn)
+}
+
+func (p *pageImpl) OnResponse(fn func(Response)) {
+ p.On("response", fn)
+}
+
+func (p *pageImpl) OnWebSocket(fn func(WebSocket)) {
+ p.On("websocket", fn)
+}
+
+func (p *pageImpl) OnWorker(fn func(Worker)) {
+ p.On("worker", fn)
+}
+
+func (p *pageImpl) RequestGC() error {
+ _, err := p.channel.Send("requestGC")
+ return err
+}
+
+func (p *pageImpl) RouteWebSocket(url interface{}, handler func(WebSocketRoute)) error {
+ p.Lock()
+ defer p.Unlock()
+ p.webSocketRoutes = slices.Insert(p.webSocketRoutes, 0, newWebSocketRouteHandler(newURLMatcher(url, p.browserContext.options.BaseURL, true), handler))
+
+ return p.updateWebSocketInterceptionPatterns()
+}
+
+func (p *pageImpl) onWebSocketRoute(wr WebSocketRoute) {
+ p.Lock()
+ index := slices.IndexFunc(p.webSocketRoutes, func(r *webSocketRouteHandler) bool {
+ return r.Matches(wr.URL())
+ })
+ if index == -1 {
+ p.Unlock()
+ p.browserContext.onWebSocketRoute(wr)
+ return
+ }
+ handler := p.webSocketRoutes[index]
+ p.Unlock()
+ handler.Handle(wr)
+}
+
+func (p *pageImpl) updateWebSocketInterceptionPatterns() error {
+ patterns := prepareWebSocketRouteHandlerInterceptionPatterns(p.webSocketRoutes)
+ _, err := p.channel.Send("setWebSocketInterceptionPatterns", map[string]interface{}{
+ "patterns": patterns,
+ })
+ return err
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/page_assertions.go b/vendor/github.com/playwright-community/playwright-go/page_assertions.go
new file mode 100644
index 0000000..43bd0dc
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/page_assertions.go
@@ -0,0 +1,70 @@
+package playwright
+
+import (
+ "net/url"
+ "path"
+)
+
+type pageAssertionsImpl struct {
+ assertionsBase
+ actualPage Page
+}
+
+func newPageAssertions(page Page, isNot bool, defaultTimeout *float64) *pageAssertionsImpl {
+ return &pageAssertionsImpl{
+ assertionsBase: assertionsBase{
+ actualLocator: page.Locator(":root"),
+ isNot: isNot,
+ defaultTimeout: defaultTimeout,
+ },
+ actualPage: page,
+ }
+}
+
+func (pa *pageAssertionsImpl) ToHaveTitle(titleOrRegExp interface{}, options ...PageAssertionsToHaveTitleOptions) error {
+ var timeout *float64
+ if len(options) == 1 {
+ timeout = options[0].Timeout
+ }
+ expectedValues, err := toExpectedTextValues([]interface{}{titleOrRegExp}, false, true, nil)
+ if err != nil {
+ return err
+ }
+ return pa.expect(
+ "to.have.title",
+ frameExpectOptions{ExpectedText: expectedValues, Timeout: timeout},
+ titleOrRegExp,
+ "Page title expected to be",
+ )
+}
+
+func (pa *pageAssertionsImpl) ToHaveURL(urlOrRegExp interface{}, options ...PageAssertionsToHaveURLOptions) error {
+ var timeout *float64
+ var ignoreCase *bool
+ if len(options) == 1 {
+ timeout = options[0].Timeout
+ ignoreCase = options[0].IgnoreCase
+ }
+
+ baseURL := pa.actualPage.Context().(*browserContextImpl).options.BaseURL
+ if urlPath, ok := urlOrRegExp.(string); ok && baseURL != nil {
+ u, _ := url.Parse(*baseURL)
+ u.Path = path.Join(u.Path, urlPath)
+ urlOrRegExp = u.String()
+ }
+
+ expectedValues, err := toExpectedTextValues([]interface{}{urlOrRegExp}, false, false, ignoreCase)
+ if err != nil {
+ return err
+ }
+ return pa.expect(
+ "to.have.url",
+ frameExpectOptions{ExpectedText: expectedValues, Timeout: timeout},
+ urlOrRegExp,
+ "Page URL expected to be",
+ )
+}
+
+func (pa *pageAssertionsImpl) Not() PageAssertions {
+ return newPageAssertions(pa.actualPage, true, pa.defaultTimeout)
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/playwright.go b/vendor/github.com/playwright-community/playwright-go/playwright.go
new file mode 100644
index 0000000..805ac14
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/playwright.go
@@ -0,0 +1,64 @@
+// Package playwright is a library to automate Chromium, Firefox and WebKit with
+// a single API. Playwright is built to enable cross-browser web automation that
+// is ever-green, capable, reliable and fast.
+package playwright
+
+// DeviceDescriptor represents a single device
+type DeviceDescriptor struct {
+ UserAgent string `json:"userAgent"`
+ Viewport *Size `json:"viewport"`
+ Screen *Size `json:"screen"`
+ DeviceScaleFactor float64 `json:"deviceScaleFactor"`
+ IsMobile bool `json:"isMobile"`
+ HasTouch bool `json:"hasTouch"`
+ DefaultBrowserType string `json:"defaultBrowserType"`
+}
+
+// Playwright represents a Playwright instance
+type Playwright struct {
+ channelOwner
+ Selectors Selectors
+ Chromium BrowserType
+ Firefox BrowserType
+ WebKit BrowserType
+ Request APIRequest
+ Devices map[string]*DeviceDescriptor
+}
+
+// Stop stops the Playwright instance
+func (p *Playwright) Stop() error {
+ return p.connection.Stop()
+}
+
+func (p *Playwright) setSelectors(selectors Selectors) {
+ selectorsOwner := fromChannel(p.initializer["selectors"]).(*selectorsOwnerImpl)
+ p.Selectors.(*selectorsImpl).removeChannel(selectorsOwner)
+ p.Selectors = selectors
+ p.Selectors.(*selectorsImpl).addChannel(selectorsOwner)
+}
+
+func newPlaywright(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *Playwright {
+ pw := &Playwright{
+ Selectors: newSelectorsImpl(),
+ Chromium: fromChannel(initializer["chromium"]).(*browserTypeImpl),
+ Firefox: fromChannel(initializer["firefox"]).(*browserTypeImpl),
+ WebKit: fromChannel(initializer["webkit"]).(*browserTypeImpl),
+ Devices: make(map[string]*DeviceDescriptor),
+ }
+ pw.createChannelOwner(pw, parent, objectType, guid, initializer)
+ pw.Request = newApiRequestImpl(pw)
+ pw.Chromium.(*browserTypeImpl).playwright = pw
+ pw.Firefox.(*browserTypeImpl).playwright = pw
+ pw.WebKit.(*browserTypeImpl).playwright = pw
+ selectorsOwner := fromChannel(initializer["selectors"]).(*selectorsOwnerImpl)
+ pw.Selectors.(*selectorsImpl).addChannel(selectorsOwner)
+ pw.connection.afterClose = func() {
+ pw.Selectors.(*selectorsImpl).removeChannel(selectorsOwner)
+ }
+ if pw.connection.localUtils != nil {
+ pw.Devices = pw.connection.localUtils.Devices
+ }
+ return pw
+}
+
+//go:generate bash scripts/generate-api.sh
diff --git a/vendor/github.com/playwright-community/playwright-go/request.go b/vendor/github.com/playwright-community/playwright-go/request.go
new file mode 100644
index 0000000..43a3161
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/request.go
@@ -0,0 +1,274 @@
+package playwright
+
+import (
+ "encoding/base64"
+ "encoding/json"
+ "fmt"
+)
+
+type serializedFallbackOverrides struct {
+ URL *string
+ Method *string
+ Headers map[string]string
+ PostDataBuffer []byte
+}
+
+type requestImpl struct {
+ channelOwner
+ timing *RequestTiming
+ provisionalHeaders *rawHeaders
+ allHeaders *rawHeaders
+ redirectedFrom Request
+ redirectedTo Request
+ failureText string
+ fallbackOverrides *serializedFallbackOverrides
+}
+
+func (r *requestImpl) URL() string {
+ if r.fallbackOverrides.URL != nil {
+ return *r.fallbackOverrides.URL
+ }
+ return r.initializer["url"].(string)
+}
+
+func (r *requestImpl) ResourceType() string {
+ return r.initializer["resourceType"].(string)
+}
+
+func (r *requestImpl) Method() string {
+ if r.fallbackOverrides.Method != nil {
+ return *r.fallbackOverrides.Method
+ }
+ return r.initializer["method"].(string)
+}
+
+func (r *requestImpl) PostData() (string, error) {
+ body, err := r.PostDataBuffer()
+ if err != nil {
+ return "", err
+ }
+ return string(body), err
+}
+
+func (r *requestImpl) PostDataJSON(v interface{}) error {
+ body, err := r.PostDataBuffer()
+ if err != nil {
+ return err
+ }
+ return json.Unmarshal(body, v)
+}
+
+func (r *requestImpl) PostDataBuffer() ([]byte, error) {
+ if r.fallbackOverrides.PostDataBuffer != nil {
+ return r.fallbackOverrides.PostDataBuffer, nil
+ }
+ if _, ok := r.initializer["postData"]; !ok {
+ return nil, nil
+ }
+ return base64.StdEncoding.DecodeString(r.initializer["postData"].(string))
+}
+
+func (r *requestImpl) Headers() map[string]string {
+ if r.fallbackOverrides.Headers != nil {
+ return newRawHeaders(serializeMapToNameAndValue(r.fallbackOverrides.Headers)).Headers()
+ }
+ return r.provisionalHeaders.Headers()
+}
+
+func (r *requestImpl) Response() (Response, error) {
+ channel, err := r.channel.Send("response")
+ if err != nil {
+ return nil, err
+ }
+ channelOwner := fromNullableChannel(channel)
+ if channelOwner == nil {
+ // no response
+ return nil, nil
+ }
+ return channelOwner.(*responseImpl), nil
+}
+
+func (r *requestImpl) Frame() Frame {
+ channel, ok := r.initializer["frame"]
+ if !ok {
+ // Service Worker requests do not have an associated frame.
+ return nil
+ }
+ frame := fromChannel(channel).(*frameImpl)
+ if frame.page == nil {
+ // Frame for this navigation request is not available, because the request
+ // was issued before the frame is created. You can check whether the request
+ // is a navigation request by calling IsNavigationRequest() method.
+ return nil
+ }
+ return frame
+}
+
+func (r *requestImpl) IsNavigationRequest() bool {
+ return r.initializer["isNavigationRequest"].(bool)
+}
+
+func (r *requestImpl) RedirectedFrom() Request {
+ return r.redirectedFrom
+}
+
+func (r *requestImpl) RedirectedTo() Request {
+ return r.redirectedTo
+}
+
+func (r *requestImpl) Failure() error {
+ if r.failureText == "" {
+ return nil
+ }
+ return fmt.Errorf("%v", r.failureText)
+}
+
+func (r *requestImpl) Timing() *RequestTiming {
+ return r.timing
+}
+
+func (r *requestImpl) AllHeaders() (map[string]string, error) {
+ headers, err := r.ActualHeaders()
+ if err != nil {
+ return nil, err
+ }
+ return headers.Headers(), nil
+}
+
+func (r *requestImpl) HeadersArray() ([]NameValue, error) {
+ headers, err := r.ActualHeaders()
+ if err != nil {
+ return nil, err
+ }
+ return headers.HeadersArray(), nil
+}
+
+func (r *requestImpl) HeaderValue(name string) (string, error) {
+ headers, err := r.ActualHeaders()
+ if err != nil {
+ return "", err
+ }
+ return headers.Get(name), err
+}
+
+func (r *requestImpl) HeaderValues(name string) ([]string, error) {
+ headers, err := r.ActualHeaders()
+ if err != nil {
+ return []string{}, err
+ }
+ return headers.GetAll(name), err
+}
+
+func (r *requestImpl) ActualHeaders() (*rawHeaders, error) {
+ if r.fallbackOverrides.Headers != nil {
+ return newRawHeaders(serializeMapToNameAndValue(r.fallbackOverrides.Headers)), nil
+ }
+ if r.allHeaders == nil {
+ response, err := r.Response()
+ if err != nil {
+ return nil, err
+ }
+ if response == nil {
+ return r.provisionalHeaders, nil
+ }
+ headers, err := r.channel.Send("rawRequestHeaders")
+ if err != nil {
+ return nil, err
+ }
+ r.allHeaders = newRawHeaders(headers)
+ }
+ return r.allHeaders, nil
+}
+
+func (r *requestImpl) ServiceWorker() Worker {
+ channel, ok := r.initializer["serviceWorker"]
+ if !ok {
+ return nil
+ }
+ return fromChannel(channel).(*workerImpl)
+}
+
+func (r *requestImpl) Sizes() (*RequestSizesResult, error) {
+ response, err := r.Response()
+ if err != nil {
+ return nil, err
+ }
+ sizes, err := response.(*responseImpl).channel.Send("sizes")
+ if err != nil {
+ return nil, err
+ }
+ result := &RequestSizesResult{}
+ remapMapToStruct(sizes, result)
+ return result, nil
+}
+
+func (r *requestImpl) applyFallbackOverrides(options RouteFallbackOptions) {
+ if options.URL != nil {
+ r.fallbackOverrides.URL = options.URL
+ }
+ if options.Method != nil {
+ r.fallbackOverrides.Method = options.Method
+ }
+ r.fallbackOverrides.Headers = options.Headers
+ if options.PostData != nil {
+ switch v := options.PostData.(type) {
+ case string:
+ r.fallbackOverrides.PostDataBuffer = []byte(v)
+ case []byte:
+ r.fallbackOverrides.PostDataBuffer = v
+ }
+ }
+}
+
+func (r *requestImpl) targetClosed() <-chan error {
+ page := r.safePage()
+ if page == nil {
+ return make(<-chan error, 1)
+ }
+ return page.closedOrCrashed
+}
+
+func (r *requestImpl) setResponseEndTiming(t float64) {
+ r.timing.ResponseEnd = t
+ if r.timing.ResponseStart == -1 {
+ r.timing.ResponseStart = t
+ }
+}
+
+func (r *requestImpl) safePage() *pageImpl {
+ channel := fromNullableChannel(r.initializer["frame"])
+ if channel == nil {
+ return nil
+ }
+ frame, ok := channel.(*frameImpl)
+ if !ok {
+ return nil
+ }
+ return frame.page
+}
+
+func newRequest(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *requestImpl {
+ req := &requestImpl{}
+ req.createChannelOwner(req, parent, objectType, guid, initializer)
+ redirectedFrom := fromNullableChannel(initializer["redirectedFrom"])
+ if redirectedFrom != nil {
+ req.redirectedFrom = redirectedFrom.(*requestImpl)
+ }
+ if req.redirectedFrom != nil {
+ req.redirectedFrom.(*requestImpl).redirectedTo = req
+ }
+ req.timing = &RequestTiming{
+ StartTime: 0,
+ DomainLookupStart: -1,
+ DomainLookupEnd: -1,
+ ConnectStart: -1,
+ SecureConnectionStart: -1,
+ ConnectEnd: -1,
+ RequestStart: -1,
+ ResponseStart: -1,
+ ResponseEnd: -1,
+ }
+ req.provisionalHeaders = newRawHeaders(req.initializer["headers"])
+ req.fallbackOverrides = &serializedFallbackOverrides{}
+ return req
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/response.go b/vendor/github.com/playwright-community/playwright-go/response.go
new file mode 100644
index 0000000..8f26d6d
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/response.go
@@ -0,0 +1,162 @@
+package playwright
+
+import (
+ "encoding/base64"
+ "encoding/json"
+)
+
+type responseImpl struct {
+ channelOwner
+ request *requestImpl
+ provisionalHeaders *rawHeaders
+ rawHeaders *rawHeaders
+ finished chan error
+}
+
+func (r *responseImpl) FromServiceWorker() bool {
+ return r.initializer["fromServiceWorker"].(bool)
+}
+
+func (r *responseImpl) URL() string {
+ return r.initializer["url"].(string)
+}
+
+func (r *responseImpl) Ok() bool {
+ return r.Status() == 0 || (r.Status() >= 200 && r.Status() <= 299)
+}
+
+func (r *responseImpl) Status() int {
+ return int(r.initializer["status"].(float64))
+}
+
+func (r *responseImpl) StatusText() string {
+ return r.initializer["statusText"].(string)
+}
+
+func (r *responseImpl) Headers() map[string]string {
+ return r.provisionalHeaders.Headers()
+}
+
+func (r *responseImpl) Finished() error {
+ select {
+ case err := <-r.request.targetClosed():
+ return err
+ case err := <-r.finished:
+ return err
+ }
+}
+
+func (r *responseImpl) Body() ([]byte, error) {
+ b64Body, err := r.channel.Send("body")
+ if err != nil {
+ return nil, err
+ }
+ return base64.StdEncoding.DecodeString(b64Body.(string))
+}
+
+func (r *responseImpl) Text() (string, error) {
+ body, err := r.Body()
+ if err != nil {
+ return "", err
+ }
+ return string(body), nil
+}
+
+func (r *responseImpl) JSON(v interface{}) error {
+ body, err := r.Body()
+ if err != nil {
+ return err
+ }
+ return json.Unmarshal(body, v)
+}
+
+func (r *responseImpl) Request() Request {
+ return r.request
+}
+
+func (r *responseImpl) Frame() Frame {
+ return r.request.Frame()
+}
+
+func (r *responseImpl) AllHeaders() (map[string]string, error) {
+ headers, err := r.ActualHeaders()
+ if err != nil {
+ return nil, err
+ }
+ return headers.Headers(), nil
+}
+
+func (r *responseImpl) HeadersArray() ([]NameValue, error) {
+ headers, err := r.ActualHeaders()
+ if err != nil {
+ return nil, err
+ }
+ return headers.HeadersArray(), nil
+}
+
+func (r *responseImpl) HeaderValue(name string) (string, error) {
+ headers, err := r.ActualHeaders()
+ if err != nil {
+ return "", err
+ }
+ return headers.Get(name), err
+}
+
+func (r *responseImpl) HeaderValues(name string) ([]string, error) {
+ headers, err := r.ActualHeaders()
+ if err != nil {
+ return []string{}, err
+ }
+ return headers.GetAll(name), err
+}
+
+func (r *responseImpl) ActualHeaders() (*rawHeaders, error) {
+ if r.rawHeaders == nil {
+ headers, err := r.channel.Send("rawResponseHeaders")
+ if err != nil {
+ return nil, err
+ }
+ r.rawHeaders = newRawHeaders(headers)
+ }
+ return r.rawHeaders, nil
+}
+
+func (r *responseImpl) SecurityDetails() (*ResponseSecurityDetailsResult, error) {
+ details, err := r.channel.Send("securityDetails")
+ if err != nil {
+ return nil, err
+ }
+ result := &ResponseSecurityDetailsResult{}
+ remapMapToStruct(details.(map[string]interface{}), result)
+ return result, nil
+}
+
+func (r *responseImpl) ServerAddr() (*ResponseServerAddrResult, error) {
+ addr, err := r.channel.Send("serverAddr")
+ if err != nil {
+ return nil, err
+ }
+ result := &ResponseServerAddrResult{}
+ remapMapToStruct(addr, result)
+ return result, nil
+}
+
+func newResponse(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *responseImpl {
+ resp := &responseImpl{}
+ resp.createChannelOwner(resp, parent, objectType, guid, initializer)
+ timing := resp.initializer["timing"].(map[string]interface{})
+ resp.request = fromChannel(resp.initializer["request"]).(*requestImpl)
+ resp.request.timing = &RequestTiming{
+ StartTime: timing["startTime"].(float64),
+ DomainLookupStart: timing["domainLookupStart"].(float64),
+ DomainLookupEnd: timing["domainLookupEnd"].(float64),
+ ConnectStart: timing["connectStart"].(float64),
+ SecureConnectionStart: timing["secureConnectionStart"].(float64),
+ ConnectEnd: timing["connectEnd"].(float64),
+ RequestStart: timing["requestStart"].(float64),
+ ResponseStart: timing["responseStart"].(float64),
+ }
+ resp.provisionalHeaders = newRawHeaders(resp.initializer["headers"])
+ resp.finished = make(chan error, 1)
+ return resp
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/route.go b/vendor/github.com/playwright-community/playwright-go/route.go
new file mode 100644
index 0000000..c9e6ee9
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/route.go
@@ -0,0 +1,270 @@
+package playwright
+
+import (
+ "encoding/base64"
+ "errors"
+ "net/http"
+ "os"
+ "reflect"
+ "strconv"
+ "strings"
+)
+
+type routeImpl struct {
+ channelOwner
+ handling *chan bool
+ context *browserContextImpl
+ didThrow bool
+}
+
+func (r *routeImpl) startHandling() chan bool {
+ r.Lock()
+ defer r.Unlock()
+ handling := make(chan bool, 1)
+ r.handling = &handling
+ return handling
+}
+
+func (r *routeImpl) reportHandled(done bool) {
+ r.Lock()
+ defer r.Unlock()
+ if r.handling != nil {
+ handling := *r.handling
+ r.handling = nil
+ handling <- done
+ }
+}
+
+func (r *routeImpl) checkNotHandled() error {
+ r.RLock()
+ defer r.RUnlock()
+ if r.handling == nil {
+ return errors.New("Route is already handled!")
+ }
+ return nil
+}
+
+func (r *routeImpl) Request() Request {
+ return fromChannel(r.initializer["request"]).(*requestImpl)
+}
+
+func unpackOptionalArgument(input interface{}) interface{} {
+ inputValue := reflect.ValueOf(input)
+ if inputValue.Kind() != reflect.Slice {
+ panic("Needs to be a slice")
+ }
+ if inputValue.Len() == 0 {
+ return nil
+ }
+ return inputValue.Index(0).Interface()
+}
+
+func (r *routeImpl) Abort(errorCode ...string) error {
+ return r.handleRoute(func() error {
+ return r.raceWithPageClose(func() error {
+ _, err := r.channel.Send("abort", map[string]interface{}{
+ "errorCode": unpackOptionalArgument(errorCode),
+ })
+ return err
+ })
+ })
+}
+
+func (r *routeImpl) raceWithPageClose(f func() error) error {
+ errChan := make(chan error, 1)
+ go func() {
+ errChan <- f()
+ }()
+
+ select {
+ case <-r.Request().(*requestImpl).targetClosed():
+ // upstream does not throw the err
+ return nil
+ case err := <-errChan:
+ return err
+ }
+}
+
+func (r *routeImpl) Fulfill(options ...RouteFulfillOptions) error {
+ return r.handleRoute(func() error {
+ return r.innerFulfill(options...)
+ })
+}
+
+func (r *routeImpl) handleRoute(cb func() error) error {
+ err := r.checkNotHandled()
+ if err != nil {
+ return err
+ }
+ if err := cb(); err != nil {
+ r.didThrow = true
+ return err
+ }
+ r.reportHandled(true)
+ return nil
+}
+
+func (r *routeImpl) innerFulfill(options ...RouteFulfillOptions) error {
+ err := r.checkNotHandled()
+ if err != nil {
+ return err
+ }
+ option := RouteFulfillOptions{}
+ if len(options) == 1 {
+ option = options[0]
+ }
+ overrides := map[string]interface{}{
+ "status": 200,
+ }
+ headers := make(map[string]string)
+
+ if option.Response != nil {
+ overrides["status"] = option.Response.Status()
+ headers = option.Response.Headers()
+ response, ok := option.Response.(*apiResponseImpl)
+ if option.Body == nil && option.Path == nil && ok && response.request.connection == r.connection {
+ overrides["fetchResponseUid"] = response.fetchUid()
+ } else {
+ option.Body, _ = option.Response.Body()
+ }
+ option.Response = nil
+ }
+ if option.Status != nil {
+ overrides["status"] = *option.Status
+ option.Status = nil
+ }
+
+ length := 0
+ isBase64 := false
+ var fileContentType string
+ if _, ok := option.Body.(string); ok {
+ isBase64 = false
+ } else if body, ok := option.Body.([]byte); ok {
+ option.Body = base64.StdEncoding.EncodeToString(body)
+ length = len(body)
+ isBase64 = true
+ } else if option.Path != nil {
+ content, err := os.ReadFile(*option.Path)
+ if err != nil {
+ return err
+ }
+ fileContentType = http.DetectContentType(content)
+ option.Body = base64.StdEncoding.EncodeToString(content)
+ isBase64 = true
+ length = len(content)
+ }
+
+ if option.Headers != nil {
+ headers = make(map[string]string)
+ for key, val := range option.Headers {
+ headers[strings.ToLower(key)] = val
+ }
+ option.Headers = nil
+ }
+ if option.ContentType != nil {
+ headers["content-type"] = *option.ContentType
+ option.ContentType = nil
+ } else if option.Path != nil {
+ headers["content-type"] = fileContentType
+ }
+ if _, ok := headers["content-length"]; !ok && length > 0 {
+ headers["content-length"] = strconv.Itoa(length)
+ }
+ overrides["headers"] = serializeMapToNameAndValue(headers)
+ overrides["isBase64"] = isBase64
+
+ option.Path = nil
+ err = r.raceWithPageClose(func() error {
+ _, err := r.channel.Send("fulfill", option, overrides)
+ return err
+ })
+ return err
+}
+
+func (r *routeImpl) Fallback(options ...RouteFallbackOptions) error {
+ err := r.checkNotHandled()
+ if err != nil {
+ return err
+ }
+ opt := RouteFallbackOptions{}
+ if len(options) == 1 {
+ opt = options[0]
+ }
+ r.Request().(*requestImpl).applyFallbackOverrides(opt)
+ r.reportHandled(false)
+ return nil
+}
+
+func (r *routeImpl) Fetch(options ...RouteFetchOptions) (APIResponse, error) {
+ opt := &APIRequestContextFetchOptions{}
+ url := ""
+ if len(options) == 1 {
+ err := assignStructFields(opt, options[0], true)
+ if err != nil {
+ return nil, err
+ }
+ opt.Data = options[0].PostData
+ if options[0].URL != nil {
+ url = *options[0].URL
+ }
+ }
+ ret, err := r.connection.WrapAPICall(func() (interface{}, error) {
+ return r.context.request.innerFetch(url, r.Request(), *opt)
+ }, false)
+ if ret == nil {
+ return nil, err
+ }
+ return ret.(APIResponse), err
+}
+
+func (r *routeImpl) Continue(options ...RouteContinueOptions) error {
+ option := &RouteFallbackOptions{}
+ if len(options) == 1 {
+ err := assignStructFields(option, options[0], true)
+ if err != nil {
+ return err
+ }
+ }
+
+ return r.handleRoute(func() error {
+ r.Request().(*requestImpl).applyFallbackOverrides(*option)
+ return r.internalContinue(false)
+ })
+}
+
+func (r *routeImpl) internalContinue(isFallback bool) error {
+ overrides := make(map[string]interface{})
+ overrides["url"] = r.Request().(*requestImpl).fallbackOverrides.URL
+ overrides["method"] = r.Request().(*requestImpl).fallbackOverrides.Method
+ headers := r.Request().(*requestImpl).fallbackOverrides.Headers
+ if headers != nil {
+ overrides["headers"] = serializeMapToNameAndValue(headers)
+ }
+ postDataBuf := r.Request().(*requestImpl).fallbackOverrides.PostDataBuffer
+ if postDataBuf != nil {
+ overrides["postData"] = base64.StdEncoding.EncodeToString(postDataBuf)
+ }
+ overrides["isFallback"] = isFallback
+ return r.raceWithPageClose(func() error {
+ _, err := r.channel.Send("continue", overrides)
+ return err
+ })
+}
+
+func (r *routeImpl) redirectedNavigationRequest(url string) error {
+ return r.handleRoute(func() error {
+ return r.raceWithPageClose(func() error {
+ _, err := r.channel.Send("redirectNavigationRequest", map[string]interface{}{
+ "url": url,
+ })
+ return err
+ })
+ })
+}
+
+func newRoute(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *routeImpl {
+ bt := &routeImpl{}
+ bt.createChannelOwner(bt, parent, objectType, guid, initializer)
+ bt.markAsInternalType()
+ return bt
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/run.go b/vendor/github.com/playwright-community/playwright-go/run.go
new file mode 100644
index 0000000..79ad11e
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/run.go
@@ -0,0 +1,409 @@
+package playwright
+
+import (
+ "archive/zip"
+ "bytes"
+ "errors"
+ "fmt"
+ "io"
+ "log"
+ "log/slog"
+ "net/http"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "runtime"
+ "strings"
+)
+
+const playwrightCliVersion = "1.52.0"
+
+var (
+ logger = slog.Default()
+ playwrightCDNMirrors = []string{
+ "https://playwright.azureedge.net",
+ "https://playwright-akamai.azureedge.net",
+ "https://playwright-verizon.azureedge.net",
+ }
+)
+
+// PlaywrightDriver wraps the Playwright CLI of upstream Playwright.
+//
+// It's required for playwright-go to work.
+type PlaywrightDriver struct {
+ Version string
+ options *RunOptions
+}
+
+func NewDriver(options ...*RunOptions) (*PlaywrightDriver, error) {
+ transformed, err := transformRunOptions(options...) // get default values
+ if err != nil {
+ return nil, err
+ }
+ return &PlaywrightDriver{
+ options: transformed,
+ Version: playwrightCliVersion,
+ }, nil
+}
+
+func getDefaultCacheDirectory() (string, error) {
+ userHomeDir, err := os.UserHomeDir()
+ if err != nil {
+ return "", fmt.Errorf("could not get user home directory: %w", err)
+ }
+ switch runtime.GOOS {
+ case "windows":
+ return filepath.Join(userHomeDir, "AppData", "Local"), nil
+ case "darwin":
+ return filepath.Join(userHomeDir, "Library", "Caches"), nil
+ case "linux":
+ return filepath.Join(userHomeDir, ".cache"), nil
+ }
+ return "", errors.New("could not determine cache directory")
+}
+
+func (d *PlaywrightDriver) isUpToDateDriver() (bool, error) {
+ if _, err := os.Stat(d.options.DriverDirectory); os.IsNotExist(err) {
+ if err := os.MkdirAll(d.options.DriverDirectory, 0o777); err != nil {
+ return false, fmt.Errorf("could not create driver directory: %w", err)
+ }
+ }
+ if _, err := os.Stat(getDriverCliJs(d.options.DriverDirectory)); os.IsNotExist(err) {
+ return false, nil
+ } else if err != nil {
+ return false, fmt.Errorf("could not check if driver is up2date: %w", err)
+ }
+ cmd := d.Command("--version")
+ output, err := cmd.Output()
+ if err != nil {
+ return false, fmt.Errorf("could not run driver: %w", err)
+ }
+ if bytes.Contains(output, []byte(d.Version)) {
+ return true, nil
+ }
+ // avoid triggering downloads and accidentally overwriting files
+ return false, fmt.Errorf("driver exists but version not %s in : %s", d.Version, d.options.DriverDirectory)
+}
+
+// Command returns an exec.Cmd for the driver.
+func (d *PlaywrightDriver) Command(arg ...string) *exec.Cmd {
+ cmd := exec.Command(getNodeExecutable(d.options.DriverDirectory), append([]string{getDriverCliJs(d.options.DriverDirectory)}, arg...)...)
+ cmd.SysProcAttr = defaultSysProcAttr
+ return cmd
+}
+
+// Install downloads the driver and the browsers depending on [RunOptions].
+func (d *PlaywrightDriver) Install() error {
+ if err := d.DownloadDriver(); err != nil {
+ return fmt.Errorf("could not install driver: %w", err)
+ }
+ if d.options.SkipInstallBrowsers {
+ return nil
+ }
+
+ d.log("Downloading browsers...")
+ if err := d.installBrowsers(); err != nil {
+ return fmt.Errorf("could not install browsers: %w", err)
+ }
+ d.log("Downloaded browsers successfully")
+
+ return nil
+}
+
+// Uninstall removes the driver and the browsers.
+func (d *PlaywrightDriver) Uninstall() error {
+ d.log("Removing browsers...")
+ if err := d.uninstallBrowsers(); err != nil {
+ return fmt.Errorf("could not uninstall browsers: %w", err)
+ }
+
+ d.log("Removing driver...")
+ if err := os.RemoveAll(d.options.DriverDirectory); err != nil {
+ return fmt.Errorf("could not remove driver directory: %w", err)
+ }
+
+ d.log("Uninstall driver successfully")
+ return nil
+}
+
+// DownloadDriver downloads the driver only
+func (d *PlaywrightDriver) DownloadDriver() error {
+ up2Date, err := d.isUpToDateDriver()
+ if err != nil {
+ return err
+ }
+ if up2Date {
+ return nil
+ }
+
+ d.log("Downloading driver", "path", d.options.DriverDirectory)
+
+ body, err := downloadDriver(d.getDriverURLs())
+ if err != nil {
+ return err
+ }
+ zipReader, err := zip.NewReader(bytes.NewReader(body), int64(len(body)))
+ if err != nil {
+ return fmt.Errorf("could not read zip content: %w", err)
+ }
+
+ for _, zipFile := range zipReader.File {
+ zipFileDiskPath := filepath.Join(d.options.DriverDirectory, zipFile.Name)
+ if zipFile.FileInfo().IsDir() {
+ if err := os.MkdirAll(zipFileDiskPath, os.ModePerm); err != nil {
+ return fmt.Errorf("could not create directory: %w", err)
+ }
+ continue
+ }
+
+ outFile, err := os.Create(zipFileDiskPath)
+ if err != nil {
+ return fmt.Errorf("could not create driver: %w", err)
+ }
+ file, err := zipFile.Open()
+ if err != nil {
+ return fmt.Errorf("could not open zip file: %w", err)
+ }
+ if _, err = io.Copy(outFile, file); err != nil {
+ return fmt.Errorf("could not copy response body to file: %w", err)
+ }
+ if err := outFile.Close(); err != nil {
+ return fmt.Errorf("could not close file (driver): %w", err)
+ }
+ if err := file.Close(); err != nil {
+ return fmt.Errorf("could not close file (zip file): %w", err)
+ }
+ if zipFile.Mode().Perm()&0o100 != 0 && runtime.GOOS != "windows" {
+ if err := makeFileExecutable(zipFileDiskPath); err != nil {
+ return fmt.Errorf("could not make executable: %w", err)
+ }
+ }
+ }
+
+ d.log("Downloaded driver successfully")
+
+ return nil
+}
+
+func (d *PlaywrightDriver) log(msg string, args ...any) {
+ if d.options.Verbose {
+ logger.Info(msg, args...)
+ }
+}
+
+func (d *PlaywrightDriver) run() (*connection, error) {
+ transport, err := newPipeTransport(d, d.options.Stderr)
+ if err != nil {
+ return nil, err
+ }
+ connection := newConnection(transport)
+ return connection, nil
+}
+
+func (d *PlaywrightDriver) installBrowsers() error {
+ additionalArgs := []string{"install"}
+ if d.options.Browsers != nil {
+ additionalArgs = append(additionalArgs, d.options.Browsers...)
+ }
+
+ if d.options.OnlyInstallShell {
+ additionalArgs = append(additionalArgs, "--only-shell")
+ }
+
+ if d.options.DryRun {
+ additionalArgs = append(additionalArgs, "--dry-run")
+ }
+
+ cmd := d.Command(additionalArgs...)
+ cmd.Stdout = d.options.Stdout
+ cmd.Stderr = d.options.Stderr
+ return cmd.Run()
+}
+
+func (d *PlaywrightDriver) uninstallBrowsers() error {
+ cmd := d.Command("uninstall")
+ cmd.Stdout = d.options.Stdout
+ cmd.Stderr = d.options.Stderr
+ return cmd.Run()
+}
+
+// RunOptions are custom options to run the driver
+type RunOptions struct {
+ // DriverDirectory points to the playwright driver directory.
+ // It should have two subdirectories: node and package.
+ // You can also specify it using the environment variable PLAYWRIGHT_DRIVER_PATH.
+ //
+ // Default is user cache directory + "/ms-playwright-go/x.xx.xx":
+ // - Windows: %USERPROFILE%\AppData\Local
+ // - macOS: ~/Library/Caches
+ // - Linux: ~/.cache
+ DriverDirectory string
+ // OnlyInstallShell only downloads the headless shell. (For chromium browsers only)
+ OnlyInstallShell bool
+ SkipInstallBrowsers bool
+ // if not set and SkipInstallBrowsers is false, will download all browsers (chromium, firefox, webkit)
+ Browsers []string
+ Verbose bool // default true
+ Stdout io.Writer
+ Stderr io.Writer
+ Logger *slog.Logger
+ // DryRun does not install browser/dependencies. It will only print information.
+ DryRun bool
+}
+
+// Install does download the driver and the browsers.
+//
+// Use this before playwright.Run() or use playwright cli to install the driver and browsers
+func Install(options ...*RunOptions) error {
+ driver, err := NewDriver(options...)
+ if err != nil {
+ return fmt.Errorf("could not get driver instance: %w", err)
+ }
+ if err := driver.Install(); err != nil {
+ return fmt.Errorf("could not install driver: %w", err)
+ }
+ return nil
+}
+
+// Run starts a Playwright instance.
+//
+// Requires the driver and the browsers to be installed before.
+// Either use Install() or use playwright cli.
+func Run(options ...*RunOptions) (*Playwright, error) {
+ driver, err := NewDriver(options...)
+ if err != nil {
+ return nil, fmt.Errorf("could not get driver instance: %w", err)
+ }
+ up2date, err := driver.isUpToDateDriver()
+ if err != nil || !up2date {
+ return nil, fmt.Errorf("please install the driver (v%s) first: %w", playwrightCliVersion, err)
+ }
+ connection, err := driver.run()
+ if err != nil {
+ return nil, err
+ }
+ playwright, err := connection.Start()
+ return playwright, err
+}
+
+func transformRunOptions(options ...*RunOptions) (*RunOptions, error) {
+ option := &RunOptions{
+ Verbose: true,
+ }
+ if len(options) == 1 {
+ option = options[0]
+ }
+ if option.DriverDirectory == "" { // if user did not set it, try to get it from env
+ option.DriverDirectory = os.Getenv("PLAYWRIGHT_DRIVER_PATH")
+ }
+ if option.DriverDirectory == "" {
+ cacheDirectory, err := getDefaultCacheDirectory()
+ if err != nil {
+ return nil, fmt.Errorf("could not get default cache directory: %w", err)
+ }
+ option.DriverDirectory = filepath.Join(cacheDirectory, "ms-playwright-go", playwrightCliVersion)
+ }
+ if option.Stdout == nil {
+ option.Stdout = os.Stdout
+ }
+ if option.Stderr == nil {
+ option.Stderr = os.Stderr
+ } else if option.Logger == nil {
+ log.SetOutput(option.Stderr)
+ }
+ if option.Logger != nil {
+ logger = option.Logger
+ }
+ return option, nil
+}
+
+func getNodeExecutable(driverDirectory string) string {
+ envPath := os.Getenv("PLAYWRIGHT_NODEJS_PATH")
+ if envPath != "" {
+ return envPath
+ }
+
+ node := "node"
+ if runtime.GOOS == "windows" {
+ node = "node.exe"
+ }
+ return filepath.Join(driverDirectory, node)
+}
+
+func getDriverCliJs(driverDirectory string) string {
+ return filepath.Join(driverDirectory, "package", "cli.js")
+}
+
+func (d *PlaywrightDriver) getDriverURLs() []string {
+ platform := ""
+ switch runtime.GOOS {
+ case "windows":
+ platform = "win32_x64"
+ case "darwin":
+ if runtime.GOARCH == "arm64" {
+ platform = "mac-arm64"
+ } else {
+ platform = "mac"
+ }
+ case "linux":
+ if runtime.GOARCH == "arm64" {
+ platform = "linux-arm64"
+ } else {
+ platform = "linux"
+ }
+ }
+
+ baseURLs := []string{}
+ pattern := "%s/builds/driver/playwright-%s-%s.zip"
+ if !d.isReleaseVersion() {
+ pattern = "%s/builds/driver/next/playwright-%s-%s.zip"
+ }
+
+ if hostEnv := os.Getenv("PLAYWRIGHT_DOWNLOAD_HOST"); hostEnv != "" {
+ baseURLs = append(baseURLs, fmt.Sprintf(pattern, hostEnv, d.Version, platform))
+ } else {
+ for _, mirror := range playwrightCDNMirrors {
+ baseURLs = append(baseURLs, fmt.Sprintf(pattern, mirror, d.Version, platform))
+ }
+ }
+ return baseURLs
+}
+
+// isReleaseVersion checks if the version is not a beta or alpha release
+// this helps to determine the url from where to download the driver
+func (d *PlaywrightDriver) isReleaseVersion() bool {
+ return !strings.Contains(d.Version, "beta") && !strings.Contains(d.Version, "alpha") && !strings.Contains(d.Version, "next")
+}
+
+func makeFileExecutable(path string) error {
+ stats, err := os.Stat(path)
+ if err != nil {
+ return fmt.Errorf("could not stat driver: %w", err)
+ }
+ if err := os.Chmod(path, stats.Mode()|0x40); err != nil {
+ return fmt.Errorf("could not set permissions: %w", err)
+ }
+ return nil
+}
+
+func downloadDriver(driverURLs []string) (body []byte, e error) {
+ for _, driverURL := range driverURLs {
+ resp, err := http.Get(driverURL)
+ if err != nil {
+ e = errors.Join(e, fmt.Errorf("could not download driver from %s: %w", driverURL, err))
+ continue
+ }
+ defer resp.Body.Close()
+ if resp.StatusCode != http.StatusOK {
+ e = errors.Join(e, fmt.Errorf("error: got non 200 status code: %d (%s) from %s", resp.StatusCode, resp.Status, driverURL))
+ continue
+ }
+ body, err = io.ReadAll(resp.Body)
+ if err != nil {
+ e = errors.Join(e, fmt.Errorf("could not read response body: %w", err))
+ continue
+ }
+ return body, nil
+ }
+ return nil, e
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/run_unix.go b/vendor/github.com/playwright-community/playwright-go/run_unix.go
new file mode 100644
index 0000000..8ff102b
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/run_unix.go
@@ -0,0 +1,10 @@
+//go:build !windows
+
+package playwright
+
+import "syscall"
+
+var defaultSysProcAttr = &syscall.SysProcAttr{}
+
+// for WritableStream.Copy
+const defaultCopyBufSize = 1024 * 1024
diff --git a/vendor/github.com/playwright-community/playwright-go/run_win.go b/vendor/github.com/playwright-community/playwright-go/run_win.go
new file mode 100644
index 0000000..fe7b50d
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/run_win.go
@@ -0,0 +1,10 @@
+//go:build windows
+
+package playwright
+
+import "syscall"
+
+var defaultSysProcAttr = &syscall.SysProcAttr{HideWindow: true}
+
+// for WritableStream.Copy
+const defaultCopyBufSize = 64 * 1024
diff --git a/vendor/github.com/playwright-community/playwright-go/selectors.go b/vendor/github.com/playwright-community/playwright-go/selectors.go
new file mode 100644
index 0000000..1151647
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/selectors.go
@@ -0,0 +1,88 @@
+package playwright
+
+import (
+ "errors"
+ "os"
+ "sync"
+)
+
+type selectorsOwnerImpl struct {
+ channelOwner
+}
+
+func (s *selectorsOwnerImpl) setTestIdAttributeName(name string) {
+ s.channel.SendNoReply("setTestIdAttributeName", map[string]interface{}{
+ "testIdAttributeName": name,
+ })
+}
+
+func newSelectorsOwner(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *selectorsOwnerImpl {
+ obj := &selectorsOwnerImpl{}
+ obj.createChannelOwner(obj, parent, objectType, guid, initializer)
+ return obj
+}
+
+type selectorsImpl struct {
+ channels sync.Map
+ registrations []map[string]interface{}
+}
+
+func (s *selectorsImpl) Register(name string, script Script, options ...SelectorsRegisterOptions) error {
+ if script.Path == nil && script.Content == nil {
+ return errors.New("Either source or path should be specified")
+ }
+ source := ""
+ if script.Path != nil {
+ content, err := os.ReadFile(*script.Path)
+ if err != nil {
+ return err
+ }
+ source = string(content)
+ } else {
+ source = *script.Content
+ }
+ params := map[string]interface{}{
+ "name": name,
+ "source": source,
+ }
+ if len(options) == 1 && options[0].ContentScript != nil {
+ params["contentScript"] = *options[0].ContentScript
+ }
+ var err error
+ s.channels.Range(func(key, value any) bool {
+ _, err = value.(*selectorsOwnerImpl).channel.Send("register", params)
+ return err == nil
+ })
+ if err != nil {
+ return err
+ }
+ s.registrations = append(s.registrations, params)
+ return nil
+}
+
+func (s *selectorsImpl) SetTestIdAttribute(name string) {
+ setTestIdAttributeName(name)
+ s.channels.Range(func(key, value any) bool {
+ value.(*selectorsOwnerImpl).setTestIdAttributeName(name)
+ return true
+ })
+}
+
+func (s *selectorsImpl) addChannel(channel *selectorsOwnerImpl) {
+ s.channels.Store(channel.guid, channel)
+ for _, params := range s.registrations {
+ channel.channel.SendNoReply("register", params)
+ channel.setTestIdAttributeName(getTestIdAttributeName())
+ }
+}
+
+func (s *selectorsImpl) removeChannel(channel *selectorsOwnerImpl) {
+ s.channels.Delete(channel.guid)
+}
+
+func newSelectorsImpl() *selectorsImpl {
+ return &selectorsImpl{
+ channels: sync.Map{},
+ registrations: make([]map[string]interface{}, 0),
+ }
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/stream.go b/vendor/github.com/playwright-community/playwright-go/stream.go
new file mode 100644
index 0000000..e23942f
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/stream.go
@@ -0,0 +1,68 @@
+package playwright
+
+import (
+ "bufio"
+ "encoding/base64"
+ "os"
+ "path/filepath"
+)
+
+type streamImpl struct {
+ channelOwner
+}
+
+func (s *streamImpl) SaveAs(path string) error {
+ err := os.MkdirAll(filepath.Dir(path), 0o777)
+ if err != nil {
+ return err
+ }
+ file, err := os.Create(path)
+ if err != nil {
+ return err
+ }
+ defer file.Close()
+ writer := bufio.NewWriter(file)
+ for {
+ binary, err := s.channel.Send("read", map[string]interface{}{"size": 1024 * 1024})
+ if err != nil {
+ return err
+ }
+ bytes, err := base64.StdEncoding.DecodeString(binary.(string))
+ if err != nil {
+ return err
+ }
+ if len(bytes) == 0 {
+ break
+ }
+ _, err = writer.Write(bytes)
+ if err != nil {
+ return err
+ }
+ }
+ return writer.Flush()
+}
+
+func (s *streamImpl) ReadAll() ([]byte, error) {
+ var data []byte
+ for {
+ binary, err := s.channel.Send("read", map[string]interface{}{"size": 1024 * 1024})
+ if err != nil {
+ return nil, err
+ }
+ bytes, err := base64.StdEncoding.DecodeString(binary.(string))
+ if err != nil {
+ return nil, err
+ }
+ if len(bytes) == 0 {
+ break
+ }
+ data = append(data, bytes...)
+ }
+ return data, nil
+}
+
+func newStream(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *streamImpl {
+ stream := &streamImpl{}
+ stream.createChannelOwner(stream, parent, objectType, guid, initializer)
+ return stream
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/tracing.go b/vendor/github.com/playwright-community/playwright-go/tracing.go
new file mode 100644
index 0000000..decd872
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/tracing.go
@@ -0,0 +1,164 @@
+package playwright
+
+import "fmt"
+
+type tracingImpl struct {
+ channelOwner
+ includeSources bool
+ isTracing bool
+ stacksId string
+ tracesDir string
+}
+
+func (t *tracingImpl) Start(options ...TracingStartOptions) error {
+ chunkOption := TracingStartChunkOptions{}
+ if len(options) == 1 {
+ if options[0].Sources != nil {
+ t.includeSources = *options[0].Sources
+ }
+ chunkOption.Name = options[0].Name
+ chunkOption.Title = options[0].Title
+ }
+ innerStart := func() (interface{}, error) {
+ if _, err := t.channel.Send("tracingStart", options); err != nil {
+ return "", err
+ }
+ return t.channel.Send("tracingStartChunk", chunkOption)
+ }
+ name, err := innerStart()
+ if err != nil {
+ return err
+ }
+ return t.startCollectingStacks(name.(string))
+}
+
+func (t *tracingImpl) StartChunk(options ...TracingStartChunkOptions) error {
+ name, err := t.channel.Send("tracingStartChunk", options)
+ if err != nil {
+ return err
+ }
+ return t.startCollectingStacks(name.(string))
+}
+
+func (t *tracingImpl) StopChunk(path ...string) error {
+ filePath := ""
+ if len(path) == 1 {
+ filePath = path[0]
+ }
+ return t.doStopChunk(filePath)
+}
+
+func (t *tracingImpl) Stop(path ...string) error {
+ filePath := ""
+ if len(path) == 1 {
+ filePath = path[0]
+ }
+ if err := t.doStopChunk(filePath); err != nil {
+ return err
+ }
+ _, err := t.channel.Send("tracingStop")
+ return err
+}
+
+func (t *tracingImpl) doStopChunk(filePath string) (err error) {
+ if t.isTracing {
+ t.isTracing = false
+ t.connection.setInTracing(false)
+ }
+ if filePath == "" {
+ // Not interested in artifacts.
+ _, err = t.channel.Send("tracingStopChunk", map[string]interface{}{
+ "mode": "discard",
+ })
+ if t.stacksId != "" {
+ return t.connection.LocalUtils().TraceDiscarded(t.stacksId)
+ }
+ return err
+ }
+
+ isLocal := !t.connection.isRemote
+ if isLocal {
+ result, err := t.channel.SendReturnAsDict("tracingStopChunk", map[string]interface{}{
+ "mode": "entries",
+ })
+ if err != nil {
+ return err
+ }
+ entries, ok := result["entries"]
+ if !ok {
+ return fmt.Errorf("could not convert result to map: %v", result)
+ }
+ _, err = t.connection.LocalUtils().Zip(localUtilsZipOptions{
+ ZipFile: filePath,
+ Entries: entries.([]interface{}),
+ StacksId: t.stacksId,
+ Mode: "write",
+ IncludeSources: t.includeSources,
+ })
+ return err
+ }
+
+ result, err := t.channel.SendReturnAsDict("tracingStopChunk", map[string]interface{}{
+ "mode": "archive",
+ })
+ if err != nil {
+ return err
+ }
+ artifactChannel, ok := result["artifact"]
+ if !ok {
+ return fmt.Errorf("could not convert result to map: %v", result)
+ }
+ // Save trace to the final local file.
+ artifact := fromNullableChannel(artifactChannel).(*artifactImpl)
+ // The artifact may be missing if the browser closed while stopping tracing.
+ if artifact == nil {
+ if t.stacksId != "" {
+ return t.connection.LocalUtils().TraceDiscarded(t.stacksId)
+ }
+ return
+ }
+ if err := artifact.SaveAs(filePath); err != nil {
+ return err
+ }
+ if err := artifact.Delete(); err != nil {
+ return err
+ }
+ _, err = t.connection.LocalUtils().Zip(localUtilsZipOptions{
+ ZipFile: filePath,
+ Entries: []interface{}{},
+ StacksId: t.stacksId,
+ Mode: "append",
+ IncludeSources: t.includeSources,
+ })
+ return err
+}
+
+func (t *tracingImpl) startCollectingStacks(name string) (err error) {
+ if !t.isTracing {
+ t.isTracing = true
+ t.connection.setInTracing(true)
+ }
+ t.stacksId, err = t.connection.LocalUtils().TracingStarted(name, t.tracesDir)
+ return
+}
+
+func (t *tracingImpl) Group(name string, options ...TracingGroupOptions) error {
+ var option TracingGroupOptions
+ if len(options) == 1 {
+ option = options[0]
+ }
+ _, err := t.channel.Send("tracingGroup", option, map[string]interface{}{"name": name})
+ return err
+}
+
+func (t *tracingImpl) GroupEnd() error {
+ _, err := t.channel.Send("tracingGroupEnd")
+ return err
+}
+
+func newTracing(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *tracingImpl {
+ bt := &tracingImpl{}
+ bt.createChannelOwner(bt, parent, objectType, guid, initializer)
+ bt.markAsInternalType()
+ return bt
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/transport.go b/vendor/github.com/playwright-community/playwright-go/transport.go
new file mode 100644
index 0000000..1be3988
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/transport.go
@@ -0,0 +1,141 @@
+package playwright
+
+import (
+ "bufio"
+ "encoding/binary"
+ "fmt"
+ "io"
+ "os"
+
+ "github.com/go-jose/go-jose/v3/json"
+)
+
+type transport interface {
+ Send(msg map[string]interface{}) error
+ Poll() (*message, error)
+ Close() error
+}
+
+type pipeTransport struct {
+ writer io.WriteCloser
+ bufReader *bufio.Reader
+ closed chan struct{}
+ onClose func() error
+}
+
+func (t *pipeTransport) Poll() (*message, error) {
+ if t.isClosed() {
+ return nil, fmt.Errorf("transport closed")
+ }
+
+ var length uint32
+ err := binary.Read(t.bufReader, binary.LittleEndian, &length)
+ if err != nil {
+ return nil, fmt.Errorf("could not read protocol padding: %w", err)
+ }
+
+ data := make([]byte, length)
+ _, err = io.ReadFull(t.bufReader, data)
+ if err != nil {
+ return nil, fmt.Errorf("could not read protocol data: %w", err)
+ }
+
+ msg := &message{}
+ if err := json.Unmarshal(data, &msg); err != nil {
+ return nil, fmt.Errorf("could not decode json: %w", err)
+ }
+ if os.Getenv("DEBUGP") != "" {
+ fmt.Fprintf(os.Stdout, "\x1b[33mRECV>\x1b[0m\n%s\n", data)
+ }
+ return msg, nil
+}
+
+type message struct {
+ ID int `json:"id"`
+ GUID string `json:"guid"`
+ Method string `json:"method,omitempty"`
+ Params map[string]interface{} `json:"params,omitempty"`
+ Result map[string]interface{} `json:"result,omitempty"`
+ Error *struct {
+ Error Error `json:"error"`
+ } `json:"error,omitempty"`
+}
+
+func (t *pipeTransport) Send(msg map[string]interface{}) error {
+ if t.isClosed() {
+ return fmt.Errorf("transport closed")
+ }
+ msgBytes, err := json.Marshal(msg)
+ if err != nil {
+ return fmt.Errorf("pipeTransport: could not marshal json: %w", err)
+ }
+ if os.Getenv("DEBUGP") != "" {
+ fmt.Fprintf(os.Stdout, "\x1b[32mSEND>\x1b[0m\n%s\n", msgBytes)
+ }
+
+ lengthPadding := make([]byte, 4)
+ binary.LittleEndian.PutUint32(lengthPadding, uint32(len(msgBytes)))
+ if _, err = t.writer.Write(append(lengthPadding, msgBytes...)); err != nil {
+ return err
+ }
+ return nil
+}
+
+func (t *pipeTransport) Close() error {
+ select {
+ case <-t.closed:
+ return nil
+ default:
+ return t.onClose()
+ }
+}
+
+func (t *pipeTransport) isClosed() bool {
+ select {
+ case <-t.closed:
+ return true
+ default:
+ return false
+ }
+}
+
+func newPipeTransport(driver *PlaywrightDriver, stderr io.Writer) (transport, error) {
+ t := &pipeTransport{
+ closed: make(chan struct{}, 1),
+ }
+
+ cmd := driver.Command("run-driver")
+ cmd.Stderr = stderr
+ stdin, err := cmd.StdinPipe()
+ if err != nil {
+ return nil, fmt.Errorf("could not create stdin pipe: %w", err)
+ }
+ stdout, err := cmd.StdoutPipe()
+ if err != nil {
+ return nil, fmt.Errorf("could not create stdout pipe: %w", err)
+ }
+ t.writer = stdin
+ t.bufReader = bufio.NewReader(stdout)
+
+ t.onClose = func() error {
+ select {
+ case <-t.closed:
+ default:
+ close(t.closed)
+ }
+ if err := t.writer.Close(); err != nil {
+ return err
+ }
+ // playwright-cli will exit when its stdin is closed
+ if err := cmd.Wait(); err != nil {
+ return err
+ }
+ return nil
+ }
+
+ if err := cmd.Start(); err != nil {
+ return nil, fmt.Errorf("could not start driver: %w", err)
+ }
+
+ return t, nil
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/type_helpers.go b/vendor/github.com/playwright-community/playwright-go/type_helpers.go
new file mode 100644
index 0000000..d821e7c
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/type_helpers.go
@@ -0,0 +1,72 @@
+package playwright
+
+// String is a helper routine that allocates a new string value
+// to store v and returns a pointer to it.
+func String(v string) *string {
+ return &v
+}
+
+// Bool is a helper routine that allocates a new bool value
+// to store v and returns a pointer to it.
+func Bool(v bool) *bool {
+ return &v
+}
+
+// Int is a helper routine that allocates a new int32 value
+// to store v and returns a pointer to it.
+func Int(v int) *int {
+ return &v
+}
+
+// Float is a helper routine that allocates a new float64 value
+// to store v and returns a pointer to it.
+func Float(v float64) *float64 {
+ return &v
+}
+
+// Null will be used in certain scenarios where a strict nil pointer
+// check is not possible
+func Null() interface{} {
+ return "PW_NULL"
+}
+
+// StringSlice is a helper routine that allocates a new StringSlice value
+// to store v and returns a pointer to it.
+func StringSlice(v ...string) *[]string {
+ var o []string
+ o = append(o, v...)
+ return &o
+}
+
+// IntSlice is a helper routine that allocates a new IntSlice value
+// to store v and returns a pointer to it.
+func IntSlice(v ...int) *[]int {
+ var o []int
+ o = append(o, v...)
+ return &o
+}
+
+// ToOptionalStorageState converts StorageState to OptionalStorageState for use directly in [Browser.NewContext]
+func (s StorageState) ToOptionalStorageState() *OptionalStorageState {
+ cookies := make([]OptionalCookie, len(s.Cookies))
+ for i, c := range s.Cookies {
+ cookies[i] = c.ToOptionalCookie()
+ }
+ return &OptionalStorageState{
+ Origins: s.Origins,
+ Cookies: cookies,
+ }
+}
+
+func (c Cookie) ToOptionalCookie() OptionalCookie {
+ return OptionalCookie{
+ Name: c.Name,
+ Value: c.Value,
+ Domain: String(c.Domain),
+ Path: String(c.Path),
+ Expires: Float(c.Expires),
+ HttpOnly: Bool(c.HttpOnly),
+ Secure: Bool(c.Secure),
+ SameSite: c.SameSite,
+ }
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/video.go b/vendor/github.com/playwright-community/playwright-go/video.go
new file mode 100644
index 0000000..a57b61a
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/video.go
@@ -0,0 +1,97 @@
+package playwright
+
+import (
+ "errors"
+ "sync"
+)
+
+type videoImpl struct {
+ page *pageImpl
+ artifact *artifactImpl
+ artifactChan chan *artifactImpl
+ done chan struct{}
+ closeOnce sync.Once
+ isRemote bool
+}
+
+func (v *videoImpl) Path() (string, error) {
+ if v.isRemote {
+ return "", errors.New("Path is not available when connecting remotely. Use SaveAs() to save a local copy.")
+ }
+ v.getArtifact()
+ if v.artifact == nil {
+ return "", errors.New("Page did not produce any video frames")
+ }
+ return v.artifact.AbsolutePath(), nil
+}
+
+func (v *videoImpl) Delete() error {
+ v.getArtifact()
+ if v.artifact == nil {
+ return nil
+ }
+ return v.artifact.Delete()
+}
+
+func (v *videoImpl) SaveAs(path string) error {
+ if !v.page.IsClosed() {
+ return errors.New("Page is not yet closed. Close the page prior to calling SaveAs")
+ }
+ v.getArtifact()
+ if v.artifact == nil {
+ return errors.New("Page did not produce any video frames")
+ }
+ return v.artifact.SaveAs(path)
+}
+
+func (v *videoImpl) artifactReady(artifact *artifactImpl) {
+ v.artifactChan <- artifact
+}
+
+func (v *videoImpl) pageClosed(p Page) {
+ v.closeOnce.Do(func() {
+ close(v.done)
+ })
+}
+
+func (v *videoImpl) getArtifact() {
+ // prevent channel block if no video will be produced
+ if v.page.browserContext.options == nil {
+ v.pageClosed(v.page)
+ } else {
+ option := v.page.browserContext.options
+ if option == nil || option.RecordVideo == nil { // no recordVideo option
+ v.pageClosed(v.page)
+ }
+ }
+ select {
+ case artifact := <-v.artifactChan:
+ if artifact != nil {
+ v.artifact = artifact
+ }
+ case <-v.done: // page closed
+ select { // make sure get artifact if it's ready before page closed
+ case artifact := <-v.artifactChan:
+ if artifact != nil {
+ v.artifact = artifact
+ }
+ default:
+ }
+ }
+}
+
+func newVideo(page *pageImpl) *videoImpl {
+ video := &videoImpl{
+ page: page,
+ artifactChan: make(chan *artifactImpl, 1),
+ done: make(chan struct{}, 1),
+ isRemote: page.connection.isRemote,
+ }
+
+ if page.isClosed {
+ video.pageClosed(page)
+ } else {
+ page.OnClose(video.pageClosed)
+ }
+ return video
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/waiter.go b/vendor/github.com/playwright-community/playwright-go/waiter.go
new file mode 100644
index 0000000..fbcb39f
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/waiter.go
@@ -0,0 +1,181 @@
+package playwright
+
+import (
+ "context"
+ "fmt"
+ "reflect"
+ "sync"
+ "sync/atomic"
+ "time"
+)
+
+type (
+ waiter struct {
+ mu sync.Mutex
+ timeout float64
+ fulfilled atomic.Bool
+ listeners []eventListener
+ errChan chan error
+ waitFunc func() (interface{}, error)
+ }
+ eventListener struct {
+ emitter EventEmitter
+ event string
+ handler interface{}
+ }
+)
+
+// RejectOnEvent sets the Waiter to return an error when an event occurs (and the predicate returns true)
+func (w *waiter) RejectOnEvent(emitter EventEmitter, event string, err error, predicates ...interface{}) *waiter {
+ w.mu.Lock()
+ defer w.mu.Unlock()
+ if w.waitFunc != nil {
+ w.reject(fmt.Errorf("waiter: call RejectOnEvent before WaitForEvent"))
+ return w
+ }
+ handler := func(ev ...interface{}) {
+ if w.fulfilled.Load() {
+ return
+ }
+ if len(predicates) == 0 {
+ w.reject(err)
+ } else {
+ result := reflect.ValueOf(predicates[0]).Call([]reflect.Value{reflect.ValueOf(ev[0])})
+ if result[0].Bool() {
+ w.reject(err)
+ }
+ }
+ }
+ emitter.On(event, handler)
+ w.listeners = append(w.listeners, eventListener{
+ emitter: emitter,
+ event: event,
+ handler: handler,
+ })
+ return w
+}
+
+// WithTimeout sets timeout, in milliseconds, for the waiter. 0 means no timeout.
+func (w *waiter) WithTimeout(timeout float64) *waiter {
+ w.mu.Lock()
+ defer w.mu.Unlock()
+ if w.waitFunc != nil {
+ w.reject(fmt.Errorf("waiter: please set timeout before WaitForEvent"))
+ return w
+ }
+ w.timeout = timeout
+ return w
+}
+
+// WaitForEvent sets the Waiter to return when an event occurs (and the predicate returns true)
+func (w *waiter) WaitForEvent(emitter EventEmitter, event string, predicate interface{}) *waiter {
+ w.mu.Lock()
+ defer w.mu.Unlock()
+ if w.waitFunc != nil {
+ w.reject(fmt.Errorf("waiter: WaitForEvent can only be called once"))
+ return w
+ }
+ evChan := make(chan interface{}, 1)
+ handler := w.createHandler(evChan, predicate)
+ ctx, cancel := context.WithCancel(context.Background())
+ if w.timeout != 0 {
+ timeout := w.timeout
+ go func() {
+ select {
+ case <-time.After(time.Duration(timeout) * time.Millisecond):
+ err := fmt.Errorf("%w:Timeout %.2fms exceeded.", ErrTimeout, timeout)
+ w.reject(err)
+ return
+ case <-ctx.Done():
+ return
+ }
+ }()
+ }
+
+ emitter.On(event, handler)
+ w.listeners = append(w.listeners, eventListener{
+ emitter: emitter,
+ event: event,
+ handler: handler,
+ })
+
+ w.waitFunc = func() (interface{}, error) {
+ var (
+ err error
+ val interface{}
+ )
+ select {
+ case err = <-w.errChan:
+ break
+ case val = <-evChan:
+ break
+ }
+ cancel()
+ w.mu.Lock()
+ defer w.mu.Unlock()
+ for _, l := range w.listeners {
+ l.emitter.RemoveListener(l.event, l.handler)
+ }
+ close(evChan)
+ if err != nil {
+ return nil, err
+ }
+ return val, nil
+ }
+ return w
+}
+
+// Wait waits for the waiter to return. It needs to call WaitForEvent once first.
+func (w *waiter) Wait() (interface{}, error) {
+ if w.waitFunc == nil {
+ return nil, fmt.Errorf("waiter: call WaitForEvent first")
+ }
+ return w.waitFunc()
+}
+
+// RunAndWait waits for the waiter to return after calls func.
+func (w *waiter) RunAndWait(cb func() error) (interface{}, error) {
+ if w.waitFunc == nil {
+ return nil, fmt.Errorf("waiter: call WaitForEvent first")
+ }
+ if cb != nil {
+ if err := cb(); err != nil {
+ w.errChan <- err
+ }
+ }
+ return w.waitFunc()
+}
+
+func (w *waiter) createHandler(evChan chan<- interface{}, predicate interface{}) func(...interface{}) {
+ return func(ev ...interface{}) {
+ if w.fulfilled.Load() {
+ return
+ }
+ if predicate == nil || reflect.ValueOf(predicate).IsNil() {
+ w.fulfilled.Store(true)
+ if len(ev) == 1 {
+ evChan <- ev[0]
+ } else {
+ evChan <- nil
+ }
+ } else {
+ result := reflect.ValueOf(predicate).Call([]reflect.Value{reflect.ValueOf(ev[0])})
+ if result[0].Bool() {
+ w.fulfilled.Store(true)
+ evChan <- ev[0]
+ }
+ }
+ }
+}
+
+func (w *waiter) reject(err error) {
+ w.fulfilled.Store(true)
+ w.errChan <- err
+}
+
+func newWaiter() *waiter {
+ w := &waiter{
+ errChan: make(chan error, 1),
+ }
+ return w
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/web_error.go b/vendor/github.com/playwright-community/playwright-go/web_error.go
new file mode 100644
index 0000000..b8dab79
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/web_error.go
@@ -0,0 +1,21 @@
+package playwright
+
+type webErrorImpl struct {
+ err error
+ page Page
+}
+
+func (e *webErrorImpl) Page() Page {
+ return e.page
+}
+
+func (e *webErrorImpl) Error() error {
+ return e.err
+}
+
+func newWebError(page Page, err error) WebError {
+ return &webErrorImpl{
+ err: err,
+ page: page,
+ }
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/websocket.go b/vendor/github.com/playwright-community/playwright-go/websocket.go
new file mode 100644
index 0000000..4d63ec3
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/websocket.go
@@ -0,0 +1,134 @@
+package playwright
+
+import (
+ "encoding/base64"
+ "errors"
+)
+
+type webSocketImpl struct {
+ channelOwner
+ isClosed bool
+ page *pageImpl
+}
+
+func (ws *webSocketImpl) URL() string {
+ return ws.initializer["url"].(string)
+}
+
+func newWebsocket(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *webSocketImpl {
+ ws := &webSocketImpl{}
+ ws.createChannelOwner(ws, parent, objectType, guid, initializer)
+ ws.page = fromChannel(parent.channel).(*pageImpl)
+ ws.channel.On("close", func() {
+ ws.Lock()
+ ws.isClosed = true
+ ws.Unlock()
+ ws.Emit("close", ws)
+ })
+ ws.channel.On(
+ "frameSent",
+ func(params map[string]interface{}) {
+ ws.onFrameSent(params["opcode"].(float64), params["data"].(string))
+ },
+ )
+ ws.channel.On(
+ "frameReceived",
+ func(params map[string]interface{}) {
+ ws.onFrameReceived(params["opcode"].(float64), params["data"].(string))
+ },
+ )
+ ws.channel.On(
+ "socketError",
+ func(params map[string]interface{}) {
+ ws.Emit("socketerror", params["error"])
+ },
+ )
+ return ws
+}
+
+func (ws *webSocketImpl) onFrameSent(opcode float64, data string) {
+ if opcode == 2 {
+ payload, err := base64.StdEncoding.DecodeString(data)
+ if err != nil {
+ logger.Error("could not decode WebSocket.onFrameSent payload", "error", err)
+ return
+ }
+ ws.Emit("framesent", payload)
+ } else {
+ ws.Emit("framesent", []byte(data))
+ }
+}
+
+func (ws *webSocketImpl) onFrameReceived(opcode float64, data string) {
+ if opcode == 2 {
+ payload, err := base64.StdEncoding.DecodeString(data)
+ if err != nil {
+ logger.Error("could not decode WebSocket.onFrameReceived payload", "error", err)
+ return
+ }
+ ws.Emit("framereceived", payload)
+ } else {
+ ws.Emit("framereceived", []byte(data))
+ }
+}
+
+func (ws *webSocketImpl) ExpectEvent(event string, cb func() error, options ...WebSocketExpectEventOptions) (interface{}, error) {
+ return ws.expectEvent(event, cb, options...)
+}
+
+func (ws *webSocketImpl) WaitForEvent(event string, options ...WebSocketWaitForEventOptions) (interface{}, error) {
+ if len(options) == 1 {
+ option := WebSocketExpectEventOptions(options[0])
+ return ws.expectEvent(event, nil, option)
+ } else {
+ return ws.expectEvent(event, nil)
+ }
+}
+
+func (ws *webSocketImpl) expectEvent(event string, cb func() error, options ...WebSocketExpectEventOptions) (interface{}, error) {
+ var predicate interface{} = nil
+ timeout := ws.page.timeoutSettings.Timeout()
+ if len(options) == 1 {
+ if options[0].Timeout != nil {
+ timeout = *options[0].Timeout
+ }
+ if options[0].Predicate != nil {
+ predicate = options[0].Predicate
+ }
+ }
+ waiter := newWaiter().WithTimeout(timeout)
+ if event != "close" {
+ waiter.RejectOnEvent(ws, "close", errors.New("websocket closed"))
+ }
+ if event != "socketerror" {
+ waiter.RejectOnEvent(ws, "socketerror", errors.New("websocket error"))
+ }
+ waiter.RejectOnEvent(ws.page, "close", errors.New("page closed"))
+ if cb == nil {
+ return waiter.WaitForEvent(ws, event, predicate).Wait()
+ } else {
+ return waiter.WaitForEvent(ws, event, predicate).RunAndWait(cb)
+ }
+}
+
+func (ws *webSocketImpl) IsClosed() bool {
+ ws.RLock()
+ defer ws.RUnlock()
+ return ws.isClosed
+}
+
+func (ws *webSocketImpl) OnClose(fn func(WebSocket)) {
+ ws.On("close", fn)
+}
+
+func (ws *webSocketImpl) OnFrameReceived(fn func(payload []byte)) {
+ ws.On("framereceived", fn)
+}
+
+func (ws *webSocketImpl) OnFrameSent(fn func(payload []byte)) {
+ ws.On("framesent", fn)
+}
+
+func (ws *webSocketImpl) OnSocketError(fn func(string)) {
+ ws.On("socketerror", fn)
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/websocket_route.go b/vendor/github.com/playwright-community/playwright-go/websocket_route.go
new file mode 100644
index 0000000..bb74ab9
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/websocket_route.go
@@ -0,0 +1,220 @@
+package playwright
+
+import (
+ "encoding/base64"
+ "fmt"
+ "regexp"
+ "sync/atomic"
+)
+
+type webSocketRouteImpl struct {
+ channelOwner
+ connected *atomic.Bool
+ server WebSocketRoute
+ onPageMessage func(interface{})
+ onPageClose func(code *int, reason *string)
+ onServerMessage func(interface{})
+ onServerClose func(code *int, reason *string)
+}
+
+func newWebSocketRoute(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *webSocketRouteImpl {
+ route := &webSocketRouteImpl{
+ connected: &atomic.Bool{},
+ }
+ route.createChannelOwner(route, parent, objectType, guid, initializer)
+ route.markAsInternalType()
+
+ route.server = newServerWebSocketRoute(route)
+
+ route.channel.On("messageFromPage", func(event map[string]interface{}) {
+ msg, err := untransformWebSocketMessage(event)
+ if err != nil {
+ panic(fmt.Errorf("Could not decode WebSocket message: %w", err))
+ }
+ if route.onPageMessage != nil {
+ route.onPageMessage(msg)
+ } else if route.connected.Load() {
+ go route.channel.SendNoReply("sendToServer", event)
+ }
+ })
+
+ route.channel.On("messageFromServer", func(event map[string]interface{}) {
+ msg, err := untransformWebSocketMessage(event)
+ if err != nil {
+ panic(fmt.Errorf("Could not decode WebSocket message: %w", err))
+ }
+ if route.onServerMessage != nil {
+ route.onServerMessage(msg)
+ } else {
+ go route.channel.SendNoReply("sendToPage", event)
+ }
+ })
+
+ route.channel.On("closePage", func(event map[string]interface{}) {
+ if route.onPageClose != nil {
+ route.onPageClose(event["code"].(*int), event["reason"].(*string))
+ } else {
+ go route.channel.SendNoReply("closeServer", event)
+ }
+ })
+
+ route.channel.On("closeServer", func(event map[string]interface{}) {
+ if route.onServerClose != nil {
+ route.onServerClose(event["code"].(*int), event["reason"].(*string))
+ } else {
+ go route.channel.SendNoReply("closePage", event)
+ }
+ })
+
+ return route
+}
+
+func (r *webSocketRouteImpl) Close(options ...WebSocketRouteCloseOptions) {
+ r.channel.SendNoReply("closePage", options, map[string]interface{}{"wasClean": true})
+}
+
+func (r *webSocketRouteImpl) ConnectToServer() (WebSocketRoute, error) {
+ if r.connected.Load() {
+ return nil, fmt.Errorf("Already connected to the server")
+ }
+ r.channel.SendNoReply("connect")
+ r.connected.Store(true)
+ return r.server, nil
+}
+
+func (r *webSocketRouteImpl) OnClose(handler func(code *int, reason *string)) {
+ r.onPageClose = handler
+}
+
+func (r *webSocketRouteImpl) OnMessage(handler func(interface{})) {
+ r.onPageMessage = handler
+}
+
+func (r *webSocketRouteImpl) Send(message interface{}) {
+ data, err := transformWebSocketMessage(message)
+ if err != nil {
+ panic(fmt.Errorf("Could not encode WebSocket message: %w", err))
+ }
+ go r.channel.SendNoReply("sendToPage", data)
+}
+
+func (r *webSocketRouteImpl) URL() string {
+ return r.initializer["url"].(string)
+}
+
+func (r *webSocketRouteImpl) afterHandle() error {
+ if r.connected.Load() {
+ return nil
+ }
+ // Ensure that websocket is "open" and can send messages without an actual server connection.
+ _, err := r.channel.Send("ensureOpened")
+ return err
+}
+
+type serverWebSocketRouteImpl struct {
+ webSocketRoute *webSocketRouteImpl
+}
+
+func newServerWebSocketRoute(route *webSocketRouteImpl) *serverWebSocketRouteImpl {
+ return &serverWebSocketRouteImpl{webSocketRoute: route}
+}
+
+func (s *serverWebSocketRouteImpl) OnMessage(handler func(interface{})) {
+ s.webSocketRoute.onServerMessage = handler
+}
+
+func (s *serverWebSocketRouteImpl) OnClose(handler func(code *int, reason *string)) {
+ s.webSocketRoute.onServerClose = handler
+}
+
+func (s *serverWebSocketRouteImpl) ConnectToServer() (WebSocketRoute, error) {
+ return nil, fmt.Errorf("ConnectToServer must be called on the page-side WebSocketRoute")
+}
+
+func (s *serverWebSocketRouteImpl) URL() string {
+ return s.webSocketRoute.URL()
+}
+
+func (s *serverWebSocketRouteImpl) Close(options ...WebSocketRouteCloseOptions) {
+ go s.webSocketRoute.channel.SendNoReply("close", options, map[string]interface{}{"wasClean": true})
+}
+
+func (s *serverWebSocketRouteImpl) Send(message interface{}) {
+ data, err := transformWebSocketMessage(message)
+ if err != nil {
+ panic(fmt.Errorf("Could not encode WebSocket message: %w", err))
+ }
+ go s.webSocketRoute.channel.SendNoReply("sendToServer", data)
+}
+
+func transformWebSocketMessage(message interface{}) (map[string]interface{}, error) {
+ data := map[string]interface{}{}
+ switch v := message.(type) {
+ case []byte:
+ data["isBase64"] = true
+ data["message"] = base64.StdEncoding.EncodeToString(v)
+ case string:
+ data["isBase64"] = false
+ data["message"] = v
+ default:
+ return nil, fmt.Errorf("Unsupported message type: %T", v)
+ }
+ return data, nil
+}
+
+func untransformWebSocketMessage(data map[string]interface{}) (interface{}, error) {
+ if data["isBase64"].(bool) {
+ return base64.StdEncoding.DecodeString(data["message"].(string))
+ }
+ return data["message"], nil
+}
+
+type webSocketRouteHandler struct {
+ matcher *urlMatcher
+ handler func(WebSocketRoute)
+}
+
+func newWebSocketRouteHandler(matcher *urlMatcher, handler func(WebSocketRoute)) *webSocketRouteHandler {
+ return &webSocketRouteHandler{matcher: matcher, handler: handler}
+}
+
+func (h *webSocketRouteHandler) Handle(route WebSocketRoute) {
+ h.handler(route)
+ err := route.(*webSocketRouteImpl).afterHandle()
+ if err != nil {
+ panic(fmt.Errorf("Could not handle WebSocketRoute: %w", err))
+ }
+}
+
+func (h *webSocketRouteHandler) Matches(wsURL string) bool {
+ return h.matcher.Matches(wsURL)
+}
+
+func prepareWebSocketRouteHandlerInterceptionPatterns(handlers []*webSocketRouteHandler) []map[string]interface{} {
+ patterns := []map[string]interface{}{}
+ all := false
+ for _, handler := range handlers {
+ switch handler.matcher.raw.(type) {
+ case *regexp.Regexp:
+ pattern, flags := convertRegexp(handler.matcher.raw.(*regexp.Regexp))
+ patterns = append(patterns, map[string]interface{}{
+ "regexSource": pattern,
+ "regexFlags": flags,
+ })
+ case string:
+ patterns = append(patterns, map[string]interface{}{
+ "glob": handler.matcher.raw.(string),
+ })
+ default:
+ all = true
+ }
+ }
+ if all {
+ return []map[string]interface{}{
+ {
+ "glob": "**/*",
+ },
+ }
+ }
+ return patterns
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/worker.go b/vendor/github.com/playwright-community/playwright-go/worker.go
new file mode 100644
index 0000000..6504385
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/worker.go
@@ -0,0 +1,78 @@
+package playwright
+
+type workerImpl struct {
+ channelOwner
+ page *pageImpl
+ context *browserContextImpl
+}
+
+func (w *workerImpl) URL() string {
+ return w.initializer["url"].(string)
+}
+
+func (w *workerImpl) Evaluate(expression string, options ...interface{}) (interface{}, error) {
+ var arg interface{}
+ if len(options) == 1 {
+ arg = options[0]
+ }
+ result, err := w.channel.Send("evaluateExpression", map[string]interface{}{
+ "expression": expression,
+ "arg": serializeArgument(arg),
+ })
+ if err != nil {
+ return nil, err
+ }
+ return parseResult(result), nil
+}
+
+func (w *workerImpl) EvaluateHandle(expression string, options ...interface{}) (JSHandle, error) {
+ var arg interface{}
+ if len(options) == 1 {
+ arg = options[0]
+ }
+ result, err := w.channel.Send("evaluateExpressionHandle", map[string]interface{}{
+ "expression": expression,
+ "arg": serializeArgument(arg),
+ })
+ if err != nil {
+ return nil, err
+ }
+ return fromChannel(result).(*jsHandleImpl), nil
+}
+
+func (w *workerImpl) onClose() {
+ if w.page != nil {
+ w.page.Lock()
+ workers := make([]Worker, 0)
+ for i := 0; i < len(w.page.workers); i++ {
+ if w.page.workers[i] != w {
+ workers = append(workers, w.page.workers[i])
+ }
+ }
+ w.page.workers = workers
+ w.page.Unlock()
+ }
+ if w.context != nil {
+ w.context.Lock()
+ workers := make([]Worker, 0)
+ for i := 0; i < len(w.context.serviceWorkers); i++ {
+ if w.context.serviceWorkers[i] != w {
+ workers = append(workers, w.context.serviceWorkers[i])
+ }
+ }
+ w.context.serviceWorkers = workers
+ w.context.Unlock()
+ }
+ w.Emit("close", w)
+}
+
+func (w *workerImpl) OnClose(fn func(Worker)) {
+ w.On("close", fn)
+}
+
+func newWorker(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *workerImpl {
+ bt := &workerImpl{}
+ bt.createChannelOwner(bt, parent, objectType, guid, initializer)
+ bt.channel.On("close", bt.onClose)
+ return bt
+}
diff --git a/vendor/github.com/playwright-community/playwright-go/writable_stream.go b/vendor/github.com/playwright-community/playwright-go/writable_stream.go
new file mode 100644
index 0000000..7f144b4
--- /dev/null
+++ b/vendor/github.com/playwright-community/playwright-go/writable_stream.go
@@ -0,0 +1,44 @@
+package playwright
+
+import (
+ "encoding/base64"
+ "io"
+ "os"
+)
+
+type writableStream struct {
+ channelOwner
+}
+
+func (s *writableStream) Copy(file string) error {
+ f, err := os.OpenFile(file, os.O_RDONLY, 0)
+ if err != nil {
+ return err
+ }
+ defer f.Close()
+
+ for {
+ buf := make([]byte, defaultCopyBufSize)
+ n, err := f.Read(buf)
+ if err != nil && err != io.EOF {
+ return err
+ }
+ if n == 0 {
+ break
+ }
+ _, err = s.channel.Send("write", map[string]interface{}{
+ "binary": base64.StdEncoding.EncodeToString(buf[:n]),
+ })
+ if err != nil {
+ return err
+ }
+ }
+ _, err = s.channel.Send("close")
+ return err
+}
+
+func newWritableStream(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *writableStream {
+ stream := &writableStream{}
+ stream.createChannelOwner(stream, parent, objectType, guid, initializer)
+ return stream
+}
diff --git a/vendor/github.com/testcontainers/testcontainers-go/.golangci.yml b/vendor/github.com/testcontainers/testcontainers-go/.golangci.yml
index 7db1f4d..8d66883 100644
--- a/vendor/github.com/testcontainers/testcontainers-go/.golangci.yml
+++ b/vendor/github.com/testcontainers/testcontainers-go/.golangci.yml
@@ -1,86 +1,89 @@
+formatters:
+ enable:
+ - gci
+ - gofumpt
+ settings:
+ gci:
+ sections:
+ - standard
+ - default
+ - prefix(github.com/testcontainers)
linters:
enable:
- - errcheck
- errorlint
- - gci
- gocritic
- - gofumpt
- misspell
- - nolintlint
- nakedret
+ - nolintlint
- perfsprint
- revive
- testifylint
- thelper
- usestdlibvars
-
-linters-settings:
- errorlint:
- # Check whether fmt.Errorf uses the %w verb for formatting errors.
- # See the https://github.com/polyfloyd/go-errorlint for caveats.
- errorf: true
- # Permit more than 1 %w verb, valid per Go 1.20 (Requires errorf:true)
- errorf-multi: true
- # Check for plain type assertions and type switches.
- asserts: true
- # Check for plain error comparisons.
- comparison: true
- gci:
- sections:
- - standard
- - default
- - prefix(github.com/testcontainers)
- nakedret:
- max-func-lines: 0
- revive:
- rules:
- - name: blank-imports
- - name: context-as-argument
- arguments:
- - allowTypesBefore: "*testing.T"
- - name: context-keys-type
- - name: dot-imports
- - name: early-return
- arguments:
- - "preserveScope"
- - name: empty-block
- - name: error-naming
- disabled: true
- - name: error-return
- - name: error-strings
- disabled: true
- - name: errorf
- - name: increment-decrement
- - name: indent-error-flow
- arguments:
- - "preserveScope"
- - name: range
- - name: receiver-naming
- - name: redefines-builtin-id
- disabled: true
- - name: superfluous-else
- arguments:
- - "preserveScope"
- - name: time-naming
- - name: unexported-return
- disabled: true
- - name: unreachable-code
- - name: unused-parameter
- - name: use-any
- - name: var-declaration
- - name: var-naming
- arguments:
- - ["ID"] # AllowList
- - ["VM"] # DenyList
- - - upperCaseConst: true # Extra parameter (upperCaseConst|skipPackageNameChecks)
- testifylint:
- disable:
- - float-compare
- - go-require
- enable-all: true
+ exclusions:
+ presets:
+ - comments
+ - common-false-positives
+ - legacy
+ - std-error-handling
+ settings:
+ errorlint:
+ asserts: true
+ comparison: true
+ errorf: true
+ errorf-multi: true
+ revive:
+ rules:
+ - name: blank-imports
+ - name: context-as-argument
+ arguments:
+ - allowTypesBefore: '*testing.T'
+ - name: context-keys-type
+ - name: dot-imports
+ - name: early-return
+ arguments:
+ - preserveScope
+ - name: empty-block
+ - name: error-naming
+ disabled: true
+ - name: error-return
+ - name: error-strings
+ disabled: true
+ - name: errorf
+ - name: increment-decrement
+ - name: indent-error-flow
+ arguments:
+ - preserveScope
+ - name: range
+ - name: receiver-naming
+ - name: redefines-builtin-id
+ disabled: true
+ - name: superfluous-else
+ arguments:
+ - preserveScope
+ - name: time-naming
+ - name: unexported-return
+ disabled: true
+ - name: unreachable-code
+ - name: unused-parameter
+ - name: use-any
+ - name: var-declaration
+ - name: var-naming
+ arguments:
+ - - ID
+ - - VM
+ - - upperCaseConst: true
+ staticcheck:
+ checks:
+ - all
+ testifylint:
+ disable:
+ - float-compare
+ - go-require
+ enable-all: true
output:
formats:
- - format: colored-line-number
- path-prefix: "."
-run:
- timeout: 5m
+ text:
+ path: stdout
+ path-prefix: .
+version: "2"
diff --git a/vendor/github.com/testcontainers/testcontainers-go/Makefile b/vendor/github.com/testcontainers/testcontainers-go/Makefile
index 8edc9d4..de6ccbd 100644
--- a/vendor/github.com/testcontainers/testcontainers-go/Makefile
+++ b/vendor/github.com/testcontainers/testcontainers-go/Makefile
@@ -24,7 +24,7 @@ tidy-all:
## --------------------------------------
DOCS_CONTAINER=mkdocs-container
-DOCS_IMAGE=python:3.8
+DOCS_IMAGE=python:3.13
.PHONY: clean-docs
clean-docs:
diff --git a/vendor/github.com/testcontainers/testcontainers-go/Pipfile b/vendor/github.com/testcontainers/testcontainers-go/Pipfile
index 2648278..f35e8eb 100644
--- a/vendor/github.com/testcontainers/testcontainers-go/Pipfile
+++ b/vendor/github.com/testcontainers/testcontainers-go/Pipfile
@@ -8,9 +8,9 @@ verify_ssl = true
[packages]
mkdocs = "==1.5.3"
mkdocs-codeinclude-plugin = "==0.2.1"
-mkdocs-include-markdown-plugin = "==6.2.2"
+mkdocs-include-markdown-plugin = "==7.1.5"
mkdocs-material = "==9.5.18"
mkdocs-markdownextradata-plugin = "==0.2.6"
[requires]
-python_version = "3.8"
+python_version = "3.13"
diff --git a/vendor/github.com/testcontainers/testcontainers-go/Pipfile.lock b/vendor/github.com/testcontainers/testcontainers-go/Pipfile.lock
index d08964a..e3b2e97 100644
--- a/vendor/github.com/testcontainers/testcontainers-go/Pipfile.lock
+++ b/vendor/github.com/testcontainers/testcontainers-go/Pipfile.lock
@@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
- "sha256": "0411eac13d1b06b42671b8a654fb269eb0c329d9a3d41f669ccf7b653ef8ad32"
+ "sha256": "4a9599a9c2db79998493adaaa691752f995ed409e15840df5aae155c83963d51"
},
"pipfile-spec": 6,
"requires": {
@@ -26,11 +26,11 @@
},
"bracex": {
"hashes": [
- "sha256:0725da5045e8d37ea9592ab3614d8b561e22c3c5fde3964699be672e072ab611",
- "sha256:d2fcf4b606a82ac325471affe1706dd9bbaa3536c91ef86a31f6b766f3dad1d0"
+ "sha256:12c50952415bfa773d2d9ccb8e79651b8cdb1f31a42f6091b804f6ba2b4a66b6",
+ "sha256:13e5732fec27828d6af308628285ad358047cec36801598368cb28bc631dbaf6"
],
"markers": "python_version >= '3.8'",
- "version": "==2.5"
+ "version": "==2.5.post1"
},
"certifi": {
"hashes": [
@@ -139,11 +139,11 @@
},
"click": {
"hashes": [
- "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28",
- "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"
+ "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2",
+ "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a"
],
"markers": "python_version >= '3.7'",
- "version": "==8.1.7"
+ "version": "==8.1.8"
},
"colorama": {
"hashes": [
@@ -178,86 +178,86 @@
},
"jinja2": {
"hashes": [
- "sha256:8fefff8dc3034e27bb80d67c671eb8a9bc424c0ef4c0826edbff304cceff43bb",
- "sha256:aba0f4dc9ed8013c424088f68a5c226f7d6097ed89b246d7749c2ec4175c6adb"
+ "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d",
+ "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67"
],
- "index": "pypi",
"markers": "python_version >= '3.7'",
- "version": "==3.1.5"
+ "version": "==3.1.6"
},
"markdown": {
"hashes": [
- "sha256:2ae2471477cfd02dbbf038d5d9bc226d40def84b4fe2986e49b59b6b472bbed2",
- "sha256:7eb6df5690b81a1d7942992c97fad2938e956e79df20cbc6186e9c3a77b1c803"
+ "sha256:794a929b79c5af141ef5ab0f2f642d0f7b1872981250230e72682346f7cc90dc",
+ "sha256:7df81e63f0df5c4b24b7d156eb81e4690595239b7d70937d0409f1b0de319c6f"
],
- "markers": "python_version >= '3.8'",
- "version": "==3.7"
+ "markers": "python_version >= '3.9'",
+ "version": "==3.8"
},
"markupsafe": {
"hashes": [
- "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf",
- "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff",
- "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f",
- "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3",
- "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532",
- "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f",
- "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617",
- "sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df",
- "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4",
- "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906",
- "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f",
- "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4",
- "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8",
- "sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371",
- "sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2",
- "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465",
- "sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52",
- "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6",
- "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169",
- "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad",
- "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2",
- "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0",
- "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029",
- "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f",
- "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a",
- "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced",
- "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5",
- "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c",
- "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf",
- "sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9",
- "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb",
- "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad",
- "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3",
- "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1",
- "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46",
- "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc",
- "sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a",
- "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee",
- "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900",
- "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5",
- "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea",
- "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f",
- "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5",
- "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e",
- "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a",
- "sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f",
- "sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50",
- "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a",
- "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b",
- "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4",
- "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff",
- "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2",
- "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46",
- "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b",
- "sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf",
- "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5",
- "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5",
- "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab",
- "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd",
- "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68"
- ],
- "markers": "python_version >= '3.7'",
- "version": "==2.1.5"
+ "sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4",
+ "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30",
+ "sha256:1225beacc926f536dc82e45f8a4d68502949dc67eea90eab715dea3a21c1b5f0",
+ "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9",
+ "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396",
+ "sha256:1a9d3f5f0901fdec14d8d2f66ef7d035f2157240a433441719ac9a3fba440b13",
+ "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028",
+ "sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca",
+ "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557",
+ "sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832",
+ "sha256:3169b1eefae027567d1ce6ee7cae382c57fe26e82775f460f0b2778beaad66c0",
+ "sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b",
+ "sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579",
+ "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a",
+ "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c",
+ "sha256:48032821bbdf20f5799ff537c7ac3d1fba0ba032cfc06194faffa8cda8b560ff",
+ "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c",
+ "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22",
+ "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094",
+ "sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb",
+ "sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e",
+ "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5",
+ "sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a",
+ "sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d",
+ "sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a",
+ "sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b",
+ "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8",
+ "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225",
+ "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c",
+ "sha256:88b49a3b9ff31e19998750c38e030fc7bb937398b1f78cfa599aaef92d693144",
+ "sha256:8c4e8c3ce11e1f92f6536ff07154f9d49677ebaaafc32db9db4620bc11ed480f",
+ "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87",
+ "sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d",
+ "sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93",
+ "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf",
+ "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158",
+ "sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84",
+ "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb",
+ "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48",
+ "sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171",
+ "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c",
+ "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6",
+ "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd",
+ "sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d",
+ "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1",
+ "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d",
+ "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca",
+ "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a",
+ "sha256:cfad01eed2c2e0c01fd0ecd2ef42c492f7f93902e39a42fc9ee1692961443a29",
+ "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe",
+ "sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798",
+ "sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c",
+ "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8",
+ "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f",
+ "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f",
+ "sha256:eaa0a10b7f72326f1372a713e73c3f739b524b3af41feb43e4921cb529f5929a",
+ "sha256:eb7972a85c54febfb25b5c4b4f3af4dcc731994c7da0d8a0b4a6eb0640e1d178",
+ "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0",
+ "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79",
+ "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430",
+ "sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50"
+ ],
+ "markers": "python_version >= '3.9'",
+ "version": "==3.0.2"
},
"mergedeep": {
"hashes": [
@@ -287,12 +287,12 @@
},
"mkdocs-include-markdown-plugin": {
"hashes": [
- "sha256:d293950f6499d2944291ca7b9bc4a60e652bbfd3e3a42b564f6cceee268694e7",
- "sha256:f2bd5026650492a581d2fd44be6c22f90391910d76582b96a34c264f2d17875d"
+ "sha256:a986967594da6789226798e3c41c70bc17130fadb92b4313f42bd3defdac0adc",
+ "sha256:d0b96edee45e7fda5eb189e63331cfaf1bf1fbdbebbd08371f1daa77045d3ae9"
],
"index": "pypi",
- "markers": "python_version >= '3.8'",
- "version": "==6.2.2"
+ "markers": "python_version >= '3.9'",
+ "version": "==7.1.5"
},
"mkdocs-markdownextradata-plugin": {
"hashes": [
@@ -322,11 +322,11 @@
},
"packaging": {
"hashes": [
- "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002",
- "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"
+ "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484",
+ "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f"
],
"markers": "python_version >= '3.8'",
- "version": "==24.1"
+ "version": "==25.0"
},
"paginate": {
"hashes": [
@@ -344,11 +344,11 @@
},
"platformdirs": {
"hashes": [
- "sha256:2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee",
- "sha256:38b7b51f512eed9e84a22788b4bce1de17c0adb134d6becb09836e37d8654cd3"
+ "sha256:a03875334331946f13c549dbd8f4bac7a13a50a895a0eb1e8c6a8ace80d40a94",
+ "sha256:eb437d586b6a0986388f0d6f74aa0cde27b48d0e3d66843640bfb6bdcdb6e351"
],
- "markers": "python_version >= '3.8'",
- "version": "==4.2.2"
+ "markers": "python_version >= '3.9'",
+ "version": "==4.3.7"
},
"pygments": {
"hashes": [
@@ -371,7 +371,7 @@
"sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3",
"sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"
],
- "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'",
"version": "==2.9.0.post0"
},
"pytz": {
@@ -545,11 +545,11 @@
},
"six": {
"hashes": [
- "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
- "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
+ "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274",
+ "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"
],
- "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
- "version": "==1.16.0"
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'",
+ "version": "==1.17.0"
},
"urllib3": {
"hashes": [
@@ -562,52 +562,47 @@
},
"watchdog": {
"hashes": [
- "sha256:0b4359067d30d5b864e09c8597b112fe0a0a59321a0f331498b013fb097406b4",
- "sha256:0d8a7e523ef03757a5aa29f591437d64d0d894635f8a50f370fe37f913ce4e19",
- "sha256:0e83619a2d5d436a7e58a1aea957a3c1ccbf9782c43c0b4fed80580e5e4acd1a",
- "sha256:10b6683df70d340ac3279eff0b2766813f00f35a1d37515d2c99959ada8f05fa",
- "sha256:132937547a716027bd5714383dfc40dc66c26769f1ce8a72a859d6a48f371f3a",
- "sha256:1cdcfd8142f604630deef34722d695fb455d04ab7cfe9963055df1fc69e6727a",
- "sha256:2d468028a77b42cc685ed694a7a550a8d1771bb05193ba7b24006b8241a571a1",
- "sha256:32be97f3b75693a93c683787a87a0dc8db98bb84701539954eef991fb35f5fbc",
- "sha256:770eef5372f146997638d737c9a3c597a3b41037cfbc5c41538fc27c09c3a3f9",
- "sha256:7c7d4bf585ad501c5f6c980e7be9c4f15604c7cc150e942d82083b31a7548930",
- "sha256:88456d65f207b39f1981bf772e473799fcdc10801062c36fd5ad9f9d1d463a73",
- "sha256:914285126ad0b6eb2258bbbcb7b288d9dfd655ae88fa28945be05a7b475a800b",
- "sha256:936acba76d636f70db8f3c66e76aa6cb5136a936fc2a5088b9ce1c7a3508fc83",
- "sha256:980b71510f59c884d684b3663d46e7a14b457c9611c481e5cef08f4dd022eed7",
- "sha256:984306dc4720da5498b16fc037b36ac443816125a3705dfde4fd90652d8028ef",
- "sha256:a2cffa171445b0efa0726c561eca9a27d00a1f2b83846dbd5a4f639c4f8ca8e1",
- "sha256:aa160781cafff2719b663c8a506156e9289d111d80f3387cf3af49cedee1f040",
- "sha256:b2c45f6e1e57ebb4687690c05bc3a2c1fb6ab260550c4290b8abb1335e0fd08b",
- "sha256:b4dfbb6c49221be4535623ea4474a4d6ee0a9cef4a80b20c28db4d858b64e270",
- "sha256:baececaa8edff42cd16558a639a9b0ddf425f93d892e8392a56bf904f5eff22c",
- "sha256:bcfd02377be80ef3b6bc4ce481ef3959640458d6feaae0bd43dd90a43da90a7d",
- "sha256:c0b14488bd336c5b1845cee83d3e631a1f8b4e9c5091ec539406e4a324f882d8",
- "sha256:c100d09ac72a8a08ddbf0629ddfa0b8ee41740f9051429baa8e31bb903ad7508",
- "sha256:c344453ef3bf875a535b0488e3ad28e341adbd5a9ffb0f7d62cefacc8824ef2b",
- "sha256:c50f148b31b03fbadd6d0b5980e38b558046b127dc483e5e4505fcef250f9503",
- "sha256:c82253cfc9be68e3e49282831afad2c1f6593af80c0daf1287f6a92657986757",
- "sha256:cd67c7df93eb58f360c43802acc945fa8da70c675b6fa37a241e17ca698ca49b",
- "sha256:d7ab624ff2f663f98cd03c8b7eedc09375a911794dfea6bf2a359fcc266bff29",
- "sha256:e252f8ca942a870f38cf785aef420285431311652d871409a64e2a0a52a2174c",
- "sha256:ede7f010f2239b97cc79e6cb3c249e72962404ae3865860855d5cbe708b0fd22",
- "sha256:eeea812f38536a0aa859972d50c76e37f4456474b02bd93674d1947cf1e39578",
- "sha256:f15edcae3830ff20e55d1f4e743e92970c847bcddc8b7509bcd172aa04de506e",
- "sha256:f5315a8c8dd6dd9425b974515081fc0aadca1d1d61e078d2246509fd756141ee",
- "sha256:f6ee8dedd255087bc7fe82adf046f0b75479b989185fb0bdf9a98b612170eac7",
- "sha256:f7c739888c20f99824f7aa9d31ac8a97353e22d0c0e54703a547a218f6637eb3"
- ],
- "markers": "python_version >= '3.8'",
- "version": "==4.0.2"
+ "sha256:07df1fdd701c5d4c8e55ef6cf55b8f0120fe1aef7ef39a1c6fc6bc2e606d517a",
+ "sha256:20ffe5b202af80ab4266dcd3e91aae72bf2da48c0d33bdb15c66658e685e94e2",
+ "sha256:212ac9b8bf1161dc91bd09c048048a95ca3a4c4f5e5d4a7d1b1a7d5752a7f96f",
+ "sha256:2cce7cfc2008eb51feb6aab51251fd79b85d9894e98ba847408f662b3395ca3c",
+ "sha256:490ab2ef84f11129844c23fb14ecf30ef3d8a6abafd3754a6f75ca1e6654136c",
+ "sha256:6eb11feb5a0d452ee41f824e271ca311a09e250441c262ca2fd7ebcf2461a06c",
+ "sha256:6f10cb2d5902447c7d0da897e2c6768bca89174d0c6e1e30abec5421af97a5b0",
+ "sha256:7607498efa04a3542ae3e05e64da8202e58159aa1fa4acddf7678d34a35d4f13",
+ "sha256:76aae96b00ae814b181bb25b1b98076d5fc84e8a53cd8885a318b42b6d3a5134",
+ "sha256:7a0e56874cfbc4b9b05c60c8a1926fedf56324bb08cfbc188969777940aef3aa",
+ "sha256:82dc3e3143c7e38ec49d61af98d6558288c415eac98486a5c581726e0737c00e",
+ "sha256:9041567ee8953024c83343288ccc458fd0a2d811d6a0fd68c4c22609e3490379",
+ "sha256:90c8e78f3b94014f7aaae121e6b909674df5b46ec24d6bebc45c44c56729af2a",
+ "sha256:9513f27a1a582d9808cf21a07dae516f0fab1cf2d7683a742c498b93eedabb11",
+ "sha256:9ddf7c82fda3ae8e24decda1338ede66e1c99883db93711d8fb941eaa2d8c282",
+ "sha256:a175f755fc2279e0b7312c0035d52e27211a5bc39719dd529625b1930917345b",
+ "sha256:a1914259fa9e1454315171103c6a30961236f508b9b623eae470268bbcc6a22f",
+ "sha256:afd0fe1b2270917c5e23c2a65ce50c2a4abb63daafb0d419fde368e272a76b7c",
+ "sha256:bc64ab3bdb6a04d69d4023b29422170b74681784ffb9463ed4870cf2f3e66112",
+ "sha256:bdd4e6f14b8b18c334febb9c4425a878a2ac20efd1e0b231978e7b150f92a948",
+ "sha256:c7ac31a19f4545dd92fc25d200694098f42c9a8e391bc00bdd362c5736dbf881",
+ "sha256:c7c15dda13c4eb00d6fb6fc508b3c0ed88b9d5d374056b239c4ad1611125c860",
+ "sha256:c897ac1b55c5a1461e16dae288d22bb2e412ba9807df8397a635d88f671d36c3",
+ "sha256:cbafb470cf848d93b5d013e2ecb245d4aa1c8fd0504e863ccefa32445359d680",
+ "sha256:d1cdb490583ebd691c012b3d6dae011000fe42edb7a82ece80965b42abd61f26",
+ "sha256:e3df4cbb9a450c6d49318f6d14f4bbc80d763fa587ba46ec86f99f9e6876bb26",
+ "sha256:e6439e374fc012255b4ec786ae3c4bc838cd7309a540e5fe0952d03687d8804e",
+ "sha256:e6f0e77c9417e7cd62af82529b10563db3423625c5fce018430b249bf977f9e8",
+ "sha256:e7631a77ffb1f7d2eefa4445ebbee491c720a5661ddf6df3498ebecae5ed375c",
+ "sha256:ef810fbf7b781a5a593894e4f439773830bdecb885e6880d957d5b9382a960d2"
+ ],
+ "markers": "python_version >= '3.9'",
+ "version": "==6.0.0"
},
"wcmatch": {
"hashes": [
- "sha256:567d66b11ad74384954c8af86f607857c3bdf93682349ad32066231abd556c92",
- "sha256:af25922e2b6dbd1550fa37a4c8de7dd558d6c1bb330c641de9b907b9776cb3c4"
+ "sha256:0dd927072d03c0a6527a20d2e6ad5ba8d0380e60870c383bc533b71744df7b7a",
+ "sha256:e72f0de09bba6a04e0de70937b0cf06e55f36f37b3deb422dfaf854b867b840a"
],
"markers": "python_version >= '3.8'",
- "version": "==9.0"
+ "version": "==10.0"
},
"zipp": {
"hashes": [
diff --git a/vendor/github.com/testcontainers/testcontainers-go/commons-test.mk b/vendor/github.com/testcontainers/testcontainers-go/commons-test.mk
index a7a214d..43c55b0 100644
--- a/vendor/github.com/testcontainers/testcontainers-go/commons-test.mk
+++ b/vendor/github.com/testcontainers/testcontainers-go/commons-test.mk
@@ -6,7 +6,7 @@ define go_install
endef
$(GOBIN)/golangci-lint:
- $(call go_install,github.com/golangci/golangci-lint/cmd/golangci-lint@v1.63.4)
+ $(call go_install,github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.0.2)
$(GOBIN)/gotestsum:
$(call go_install,gotest.tools/gotestsum@latest)
diff --git a/vendor/github.com/testcontainers/testcontainers-go/container.go b/vendor/github.com/testcontainers/testcontainers-go/container.go
index f1d2a78..1977632 100644
--- a/vendor/github.com/testcontainers/testcontainers-go/container.go
+++ b/vendor/github.com/testcontainers/testcontainers-go/container.go
@@ -141,17 +141,17 @@ type ContainerRequest struct {
Tmpfs map[string]string
RegistryCred string // Deprecated: Testcontainers will detect registry credentials automatically
WaitingFor wait.Strategy
- Name string // for specifying container name
- Hostname string
- WorkingDir string // specify the working directory of the container
+ Name string // for specifying container name
+ Hostname string // Deprecated: Use [ConfigModifier] instead. S
+ WorkingDir string // Deprecated: Use [ConfigModifier] instead. Specify the working directory of the container
ExtraHosts []string // Deprecated: Use HostConfigModifier instead
- Privileged bool // For starting privileged container
+ Privileged bool // Deprecated: Use [HostConfigModifier] instead. For starting privileged container
Networks []string // for specifying network names
NetworkAliases map[string][]string // for specifying network aliases
NetworkMode container.NetworkMode // Deprecated: Use HostConfigModifier instead
Resources container.Resources // Deprecated: Use HostConfigModifier instead
Files []ContainerFile // files which will be copied when container starts
- User string // for specifying uid:gid
+ User string // Deprecated: Use [ConfigModifier] instead. For specifying uid:gid
SkipReaper bool // Deprecated: The reaper is globally controlled by the .testcontainers.properties file or the TESTCONTAINERS_RYUK_DISABLED environment variable
ReaperImage string // Deprecated: use WithImageName ContainerOption instead. Alternative reaper image
ReaperOptions []ContainerOption // Deprecated: the reaper is configured at the properties level, for an entire test session
@@ -159,7 +159,7 @@ type ContainerRequest struct {
AlwaysPullImage bool // Always pull image
ImagePlatform string // ImagePlatform describes the platform which the image runs on.
Binds []string // Deprecated: Use HostConfigModifier instead
- ShmSize int64 // Amount of memory shared with the host (in bytes)
+ ShmSize int64 // Deprecated: Use [HostConfigModifier] instead. Amount of memory shared with the host (in bytes)
CapAdd []string // Deprecated: Use HostConfigModifier instead. Add Linux capabilities
CapDrop []string // Deprecated: Use HostConfigModifier instead. Drop Linux capabilities
ConfigModifier func(*container.Config) // Modifier for the config before container creation
@@ -285,37 +285,37 @@ func parseDockerIgnore(targetDir string) (bool, []string, error) {
// GetBuildArgs returns the env args to be used when creating from Dockerfile
func (c *ContainerRequest) GetBuildArgs() map[string]*string {
- return c.FromDockerfile.BuildArgs
+ return c.BuildArgs
}
// GetDockerfile returns the Dockerfile from the ContainerRequest, defaults to "Dockerfile".
// Sets FromDockerfile.Dockerfile to the default if blank.
func (c *ContainerRequest) GetDockerfile() string {
- if c.FromDockerfile.Dockerfile == "" {
- c.FromDockerfile.Dockerfile = "Dockerfile"
+ if c.Dockerfile == "" {
+ c.Dockerfile = "Dockerfile"
}
- return c.FromDockerfile.Dockerfile
+ return c.Dockerfile
}
// GetRepo returns the Repo label for image from the ContainerRequest, defaults to UUID.
// Sets FromDockerfile.Repo to the default value if blank.
func (c *ContainerRequest) GetRepo() string {
- if c.FromDockerfile.Repo == "" {
- c.FromDockerfile.Repo = uuid.NewString()
+ if c.Repo == "" {
+ c.Repo = uuid.NewString()
}
- return strings.ToLower(c.FromDockerfile.Repo)
+ return strings.ToLower(c.Repo)
}
// GetTag returns the Tag label for image from the ContainerRequest, defaults to UUID.
// Sets FromDockerfile.Tag to the default value if blank.
func (c *ContainerRequest) GetTag() string {
- if c.FromDockerfile.Tag == "" {
- c.FromDockerfile.Tag = uuid.NewString()
+ if c.Tag == "" {
+ c.Tag = uuid.NewString()
}
- return strings.ToLower(c.FromDockerfile.Tag)
+ return strings.ToLower(c.Tag)
}
// Deprecated: Testcontainers will detect registry credentials automatically, and it will be removed in the next major release.
@@ -343,13 +343,13 @@ func (c *ContainerRequest) dockerFileImages() ([]string, error) {
// Source is an archive, we need to read it to get the Dockerfile.
dockerFile := c.GetDockerfile()
- tr := tar.NewReader(c.FromDockerfile.ContextArchive)
+ tr := tar.NewReader(c.ContextArchive)
for {
hdr, err := tr.Next()
if err != nil {
if errors.Is(err, io.EOF) {
- return nil, fmt.Errorf("Dockerfile %q not found in context archive", dockerFile)
+ return nil, fmt.Errorf("dockerfile %q not found in context archive", dockerFile)
}
return nil, fmt.Errorf("reading tar archive: %w", err)
@@ -405,22 +405,24 @@ func getAuthConfigsFromDockerfile(c *ContainerRequest) (map[string]registry.Auth
}
func (c *ContainerRequest) ShouldBuildImage() bool {
- return c.FromDockerfile.Context != "" || c.FromDockerfile.ContextArchive != nil
+ return c.Context != "" || c.ContextArchive != nil
}
func (c *ContainerRequest) ShouldKeepBuiltImage() bool {
- return c.FromDockerfile.KeepImage
+ return c.KeepImage
}
// BuildLogWriter returns the io.Writer for output of log when building a Docker image from
// a Dockerfile. It returns the BuildLogWriter from the ContainerRequest, defaults to io.Discard.
// For backward compatibility, if BuildLogWriter is default and PrintBuildLog is true,
// the function returns os.Stderr.
+//
+//nolint:staticcheck //FIXME
func (c *ContainerRequest) BuildLogWriter() io.Writer {
if c.FromDockerfile.BuildLogWriter != nil {
return c.FromDockerfile.BuildLogWriter
}
- if c.FromDockerfile.PrintBuildLog {
+ if c.PrintBuildLog {
c.FromDockerfile.BuildLogWriter = os.Stderr
} else {
c.FromDockerfile.BuildLogWriter = io.Discard
@@ -437,8 +439,8 @@ func (c *ContainerRequest) BuildOptions() (types.ImageBuildOptions, error) {
ForceRemove: true,
}
- if c.FromDockerfile.BuildOptionsModifier != nil {
- c.FromDockerfile.BuildOptionsModifier(&buildOptions)
+ if c.BuildOptionsModifier != nil {
+ c.BuildOptionsModifier(&buildOptions)
}
// apply mandatory values after the modifier
@@ -505,7 +507,7 @@ func (c *ContainerRequest) BuildOptions() (types.ImageBuildOptions, error) {
}
func (c *ContainerRequest) validateContextAndImage() error {
- if c.FromDockerfile.Context != "" && c.Image != "" {
+ if c.Context != "" && c.Image != "" {
return errors.New("you cannot specify both an Image and Context in a ContainerRequest")
}
@@ -513,7 +515,7 @@ func (c *ContainerRequest) validateContextAndImage() error {
}
func (c *ContainerRequest) validateContextOrImageIsSpecified() error {
- if c.FromDockerfile.Context == "" && c.FromDockerfile.ContextArchive == nil && c.Image == "" {
+ if c.Context == "" && c.ContextArchive == nil && c.Image == "" {
return errors.New("you must specify either a build context or an image")
}
diff --git a/vendor/github.com/testcontainers/testcontainers-go/docker.go b/vendor/github.com/testcontainers/testcontainers-go/docker.go
index 774a364..c578796 100644
--- a/vendor/github.com/testcontainers/testcontainers-go/docker.go
+++ b/vendor/github.com/testcontainers/testcontainers-go/docker.go
@@ -186,7 +186,7 @@ func (c *DockerContainer) MappedPort(ctx context.Context, port nat.Port) (nat.Po
if err != nil {
return "", fmt.Errorf("inspect: %w", err)
}
- if inspect.ContainerJSONBase.HostConfig.NetworkMode == "host" {
+ if inspect.HostConfig.NetworkMode == "host" {
return port, nil
}
@@ -1153,15 +1153,10 @@ func (p *DockerProvider) CreateContainer(ctx context.Context, req ContainerReque
Env: env,
Labels: req.Labels,
Cmd: req.Cmd,
- Hostname: req.Hostname,
- User: req.User,
- WorkingDir: req.WorkingDir,
}
hostConfig := &container.HostConfig{
- Privileged: req.Privileged,
- ShmSize: req.ShmSize,
- Tmpfs: req.Tmpfs,
+ Tmpfs: req.Tmpfs,
}
networkingConfig := &network.NetworkingConfig{}
@@ -1271,7 +1266,7 @@ func (p *DockerProvider) findContainerByName(ctx context.Context, name string) (
// Note that, 'name' filter will use regex to find the containers
filter := filters.NewArgs(filters.Arg("name", fmt.Sprintf("^%s$", name)))
- containers, err := p.client.ContainerList(ctx, container.ListOptions{Filters: filter})
+ containers, err := p.client.ContainerList(ctx, container.ListOptions{All: true, Filters: filter})
if err != nil {
return nil, fmt.Errorf("container list: %w", err)
}
@@ -1369,6 +1364,23 @@ func (p *DockerProvider) ReuseOrCreateContainer(ctx context.Context, req Contain
lifecycleHooks: []ContainerLifecycleHooks{combineContainerHooks(defaultHooks, req.LifecycleHooks)},
}
+ // If a container was stopped programmatically, we want to ensure the container
+ // is running again, but only if it is not paused, as it's not possible to start
+ // a paused container. The Docker Engine returns the "cannot start a paused container,
+ // try unpause instead" error.
+ switch c.State {
+ case "running":
+ // cannot re-start a running container, but we still need
+ // to call the startup hooks.
+ case "paused":
+ // TODO: we should unpause the container here.
+ return nil, fmt.Errorf("cannot start a paused container: %w", errors.ErrUnsupported)
+ default:
+ if err := dc.Start(ctx); err != nil {
+ return dc, fmt.Errorf("start container %s in state %s: %w", req.Name, c.State, err)
+ }
+ }
+
err = dc.startedHook(ctx)
if err != nil {
return nil, err
@@ -1619,7 +1631,7 @@ func (p *DockerProvider) getGatewayIP(ctx context.Context, defaultNetwork string
}
}
if ip == "" {
- return "", errors.New("Failed to get gateway IP from network settings")
+ return "", errors.New("failed to get gateway IP from network settings")
}
return ip, nil
diff --git a/vendor/github.com/testcontainers/testcontainers-go/docker_client.go b/vendor/github.com/testcontainers/testcontainers-go/docker_client.go
index dd6d90e..e9eea1e 100644
--- a/vendor/github.com/testcontainers/testcontainers-go/docker_client.go
+++ b/vendor/github.com/testcontainers/testcontainers-go/docker_client.go
@@ -76,7 +76,7 @@ func (c *DockerClient) Info(ctx context.Context) (system.Info, error) {
log.Printf(infoMessage, packagePath,
dockerInfo.ServerVersion,
- c.Client.ClientVersion(),
+ c.ClientVersion(),
dockerInfo.OperatingSystem, dockerInfo.MemTotal/1024/1024,
infoLabels,
internal.Version,
diff --git a/vendor/github.com/testcontainers/testcontainers-go/docker_mounts.go b/vendor/github.com/testcontainers/testcontainers-go/docker_mounts.go
index 7954b2b..9609d92 100644
--- a/vendor/github.com/testcontainers/testcontainers-go/docker_mounts.go
+++ b/vendor/github.com/testcontainers/testcontainers-go/docker_mounts.go
@@ -1,6 +1,9 @@
package testcontainers
import (
+ "errors"
+ "path/filepath"
+
"github.com/docker/docker/api/types/mount"
"github.com/testcontainers/testcontainers-go/log"
@@ -11,6 +14,7 @@ var mountTypeMapping = map[MountType]mount.Type{
MountTypeVolume: mount.TypeVolume,
MountTypeTmpfs: mount.TypeTmpfs,
MountTypePipe: mount.TypeNamedPipe,
+ MountTypeImage: mount.TypeImage,
}
// Deprecated: use Files or HostConfigModifier in the ContainerRequest, or copy files container APIs to make containers portable across Docker environments
@@ -32,6 +36,12 @@ type TmpfsMounter interface {
GetTmpfsOptions() *mount.TmpfsOptions
}
+// ImageMounter can optionally be implemented by mount sources
+// to support advanced scenarios based on mount.ImageOptions
+type ImageMounter interface {
+ ImageOptions() *mount.ImageOptions
+}
+
// Deprecated: use Files or HostConfigModifier in the ContainerRequest, or copy files container APIs to make containers portable across Docker environments
type DockerBindMountSource struct {
*mount.BindOptions
@@ -85,6 +95,48 @@ func (s DockerTmpfsMountSource) GetTmpfsOptions() *mount.TmpfsOptions {
return s.TmpfsOptions
}
+// DockerImageMountSource is a mount source for an image
+type DockerImageMountSource struct {
+ // imageName is the image name
+ imageName string
+
+ // subpath is the subpath to mount the image into
+ subpath string
+}
+
+// NewDockerImageMountSource creates a new DockerImageMountSource
+func NewDockerImageMountSource(imageName string, subpath string) DockerImageMountSource {
+ return DockerImageMountSource{
+ imageName: imageName,
+ subpath: subpath,
+ }
+}
+
+// Validate validates the source of the mount, ensuring that the subpath is a relative path
+func (s DockerImageMountSource) Validate() error {
+ if !filepath.IsLocal(s.subpath) {
+ return errors.New("image mount source must be a local path")
+ }
+ return nil
+}
+
+// ImageOptions returns the image options for the image mount
+func (s DockerImageMountSource) ImageOptions() *mount.ImageOptions {
+ return &mount.ImageOptions{
+ Subpath: s.subpath,
+ }
+}
+
+// Source returns the image name for the image mount
+func (s DockerImageMountSource) Source() string {
+ return s.imageName
+}
+
+// Type returns the mount type for the image mount
+func (s DockerImageMountSource) Type() MountType {
+ return MountTypeImage
+}
+
// PrepareMounts maps the given []ContainerMount to the corresponding
// []mount.Mount for further processing
func (m ContainerMounts) PrepareMounts() []mount.Mount {
@@ -118,6 +170,8 @@ func mapToDockerMounts(containerMounts ContainerMounts) []mount.Mount {
containerMount.VolumeOptions = typedMounter.GetVolumeOptions()
case TmpfsMounter:
containerMount.TmpfsOptions = typedMounter.GetTmpfsOptions()
+ case ImageMounter:
+ containerMount.ImageOptions = typedMounter.ImageOptions()
case BindMounter:
log.Printf("Mount type %s is not supported by Testcontainers for Go", m.Source.Type())
default:
diff --git a/vendor/github.com/testcontainers/testcontainers-go/generic.go b/vendor/github.com/testcontainers/testcontainers-go/generic.go
index a081b52..9663b03 100644
--- a/vendor/github.com/testcontainers/testcontainers-go/generic.go
+++ b/vendor/github.com/testcontainers/testcontainers-go/generic.go
@@ -117,3 +117,34 @@ func AddGenericLabels(target map[string]string) {
target[k] = v
}
}
+
+// Run is a convenience function that creates a new container and starts it.
+// It calls the GenericContainer function and returns a concrete DockerContainer type.
+func Run(ctx context.Context, img string, opts ...ContainerCustomizer) (*DockerContainer, error) {
+ req := ContainerRequest{
+ Image: img,
+ }
+
+ genericContainerReq := GenericContainerRequest{
+ ContainerRequest: req,
+ Started: true,
+ }
+
+ for _, opt := range opts {
+ if err := opt.Customize(&genericContainerReq); err != nil {
+ return nil, fmt.Errorf("customize: %w", err)
+ }
+ }
+
+ ctr, err := GenericContainer(ctx, genericContainerReq)
+ var c *DockerContainer
+ if ctr != nil {
+ c = ctr.(*DockerContainer)
+ }
+
+ if err != nil {
+ return c, fmt.Errorf("generic container: %w", err)
+ }
+
+ return c, nil
+}
diff --git a/vendor/github.com/testcontainers/testcontainers-go/internal/core/bootstrap.go b/vendor/github.com/testcontainers/testcontainers-go/internal/core/bootstrap.go
index 201d4b0..d249d9b 100644
--- a/vendor/github.com/testcontainers/testcontainers-go/internal/core/bootstrap.go
+++ b/vendor/github.com/testcontainers/testcontainers-go/internal/core/bootstrap.go
@@ -84,7 +84,7 @@ func init() {
}
hasher := sha256.New()
- _, err = hasher.Write([]byte(fmt.Sprintf(sessionIDPlaceholder, parentPid, createTime)))
+ _, err = fmt.Fprintf(hasher, sessionIDPlaceholder, parentPid, createTime)
if err != nil {
sessionID = uuid.New().String()
return
diff --git a/vendor/github.com/testcontainers/testcontainers-go/internal/version.go b/vendor/github.com/testcontainers/testcontainers-go/internal/version.go
index 7e6da64..6dba727 100644
--- a/vendor/github.com/testcontainers/testcontainers-go/internal/version.go
+++ b/vendor/github.com/testcontainers/testcontainers-go/internal/version.go
@@ -1,4 +1,4 @@
package internal
// Version is the next development version of the application
-const Version = "0.36.0"
+const Version = "0.37.0"
diff --git a/vendor/github.com/testcontainers/testcontainers-go/lifecycle.go b/vendor/github.com/testcontainers/testcontainers-go/lifecycle.go
index b6d8e25..72363cc 100644
--- a/vendor/github.com/testcontainers/testcontainers-go/lifecycle.go
+++ b/vendor/github.com/testcontainers/testcontainers-go/lifecycle.go
@@ -521,6 +521,20 @@ func (c ContainerLifecycleHooks) Terminated(ctx context.Context) func(container
}
func (p *DockerProvider) preCreateContainerHook(ctx context.Context, req ContainerRequest, dockerInput *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig) error {
+ var mountErrors []error
+ for _, m := range req.Mounts {
+ // validate only the mount sources that implement the Validator interface
+ if v, ok := m.Source.(Validator); ok {
+ if err := v.Validate(); err != nil {
+ mountErrors = append(mountErrors, err)
+ }
+ }
+ }
+
+ if len(mountErrors) > 0 {
+ return errors.Join(mountErrors...)
+ }
+
// prepare mounts
hostConfig.Mounts = mapToDockerMounts(req.Mounts)
@@ -548,9 +562,10 @@ func (p *DockerProvider) preCreateContainerHook(ctx context.Context, req Contain
}
}
- if req.ConfigModifier != nil {
- req.ConfigModifier(dockerInput)
+ if req.ConfigModifier == nil {
+ req.ConfigModifier = defaultConfigModifier(req)
}
+ req.ConfigModifier(dockerInput)
if req.HostConfigModifier == nil {
req.HostConfigModifier = defaultHostConfigModifier(req)
@@ -658,6 +673,15 @@ func mergePortBindings(configPortMap, exposedPortMap nat.PortMap, exposedPorts [
}
// defaultHostConfigModifier provides a default modifier including the deprecated fields
+func defaultConfigModifier(req ContainerRequest) func(config *container.Config) {
+ return func(config *container.Config) {
+ config.Hostname = req.Hostname
+ config.WorkingDir = req.WorkingDir
+ config.User = req.User
+ }
+}
+
+// defaultHostConfigModifier provides a default modifier including the deprecated fields
func defaultHostConfigModifier(req ContainerRequest) func(hostConfig *container.HostConfig) {
return func(hostConfig *container.HostConfig) {
hostConfig.AutoRemove = req.AutoRemove
@@ -667,5 +691,7 @@ func defaultHostConfigModifier(req ContainerRequest) func(hostConfig *container.
hostConfig.ExtraHosts = req.ExtraHosts
hostConfig.NetworkMode = req.NetworkMode
hostConfig.Resources = req.Resources
+ hostConfig.Privileged = req.Privileged
+ hostConfig.ShmSize = req.ShmSize
}
}
diff --git a/vendor/github.com/testcontainers/testcontainers-go/mkdocs.yml b/vendor/github.com/testcontainers/testcontainers-go/mkdocs.yml
index 8668ef5..99e8f4a 100644
--- a/vendor/github.com/testcontainers/testcontainers-go/mkdocs.yml
+++ b/vendor/github.com/testcontainers/testcontainers-go/mkdocs.yml
@@ -68,6 +68,8 @@ nav:
- Walk: features/wait/walk.md
- Modules:
- modules/index.md
+ - modules/aerospike.md
+ - modules/arangodb.md
- modules/artemis.md
- modules/azure.md
- modules/azurite.md
@@ -79,10 +81,12 @@ nav:
- modules/couchbase.md
- modules/databend.md
- modules/dind.md
+ - modules/dockermodelrunner.md
- modules/dolt.md
- modules/dynamodb.md
- modules/elasticsearch.md
- modules/etcd.md
+ - modules/firebase.md
- modules/gcloud.md
- modules/grafana-lgtm.md
- modules/inbucket.md
@@ -114,7 +118,9 @@ nav:
- modules/redpanda.md
- modules/registry.md
- modules/scylladb.md
+ - modules/socat.md
- modules/surrealdb.md
+ - modules/toxiproxy.md
- modules/valkey.md
- modules/vault.md
- modules/vearch.md
@@ -123,7 +129,6 @@ nav:
- Examples:
- examples/index.md
- examples/nginx.md
- - examples/toxiproxy.md
- System Requirements:
- system_requirements/index.md
- system_requirements/docker.md
@@ -140,8 +145,9 @@ nav:
- system_requirements/using_colima.md
- system_requirements/using_podman.md
- system_requirements/rancher.md
+ - Dependabot: dependabot.md
- Contributing: contributing.md
- Getting help: getting_help.md
edit_uri: edit/main/docs/
extra:
- latest_version: v0.36.0
+ latest_version: v0.37.0
diff --git a/vendor/github.com/testcontainers/testcontainers-go/mounts.go b/vendor/github.com/testcontainers/testcontainers-go/mounts.go
index a68e468..2e1d2c7 100644
--- a/vendor/github.com/testcontainers/testcontainers-go/mounts.go
+++ b/vendor/github.com/testcontainers/testcontainers-go/mounts.go
@@ -1,12 +1,16 @@
package testcontainers
-import "errors"
+import (
+ "errors"
+ "path/filepath"
+)
const (
MountTypeBind MountType = iota // Deprecated: Use MountTypeVolume instead
MountTypeVolume
MountTypeTmpfs
MountTypePipe
+ MountTypeImage
)
var (
@@ -18,6 +22,7 @@ var (
_ ContainerMountSource = (*GenericBindMountSource)(nil) // Deprecated: use Files or HostConfigModifier in the ContainerRequest, or copy files container APIs to make containers portable across Docker environments
_ ContainerMountSource = (*GenericVolumeMountSource)(nil)
_ ContainerMountSource = (*GenericTmpfsMountSource)(nil)
+ _ ContainerMountSource = (*GenericImageMountSource)(nil)
)
type (
@@ -110,6 +115,15 @@ func VolumeMount(volumeName string, mountTarget ContainerMountTarget) ContainerM
}
}
+// ImageMount returns a new ContainerMount with a GenericImageMountSource as source
+// This is a convenience method to cover typical use cases.
+func ImageMount(imageName string, subpath string, mountTarget ContainerMountTarget) ContainerMount {
+ return ContainerMount{
+ Source: NewGenericImageMountSource(imageName, subpath),
+ Target: mountTarget,
+ }
+}
+
// Mounts returns a ContainerMounts to support a more fluent API
func Mounts(mounts ...ContainerMount) ContainerMounts {
return mounts
@@ -124,3 +138,38 @@ type ContainerMount struct {
// ReadOnly determines if the mount should be read-only
ReadOnly bool
}
+
+// GenericImageMountSource implements ContainerMountSource and represents an image mount
+type GenericImageMountSource struct {
+ // imageName refers to the name of the image to be mounted
+ // the same image might be mounted to multiple locations within a single container
+ imageName string
+ // subpath is the path within the image to be mounted
+ subpath string
+}
+
+// NewGenericImageMountSource creates a new GenericImageMountSource
+func NewGenericImageMountSource(imageName string, subpath string) GenericImageMountSource {
+ return GenericImageMountSource{
+ imageName: imageName,
+ subpath: subpath,
+ }
+}
+
+// Source returns the name of the image to be mounted
+func (s GenericImageMountSource) Source() string {
+ return s.imageName
+}
+
+// Type returns the type of the mount
+func (GenericImageMountSource) Type() MountType {
+ return MountTypeImage
+}
+
+// Validate validates the source of the mount
+func (s GenericImageMountSource) Validate() error {
+ if !filepath.IsLocal(s.subpath) {
+ return errors.New("image mount source must be a local path")
+ }
+ return nil
+}
diff --git a/vendor/github.com/testcontainers/testcontainers-go/options.go b/vendor/github.com/testcontainers/testcontainers-go/options.go
index f17de88..9afbcd7 100644
--- a/vendor/github.com/testcontainers/testcontainers-go/options.go
+++ b/vendor/github.com/testcontainers/testcontainers-go/options.go
@@ -2,6 +2,7 @@ package testcontainers
import (
"context"
+ "errors"
"fmt"
"net/url"
"time"
@@ -41,6 +42,15 @@ func CustomizeRequest(src GenericContainerRequest) CustomizeRequestOption {
}
}
+// WithDockerfile allows to build a container from a Dockerfile
+func WithDockerfile(df FromDockerfile) CustomizeRequestOption {
+ return func(req *GenericContainerRequest) error {
+ req.FromDockerfile = df
+
+ return nil
+ }
+}
+
// WithConfigModifier allows to override the default container config
func WithConfigModifier(modifier func(config *container.Config)) CustomizeRequestOption {
return func(req *GenericContainerRequest) error {
@@ -96,7 +106,19 @@ func WithHostPortAccess(ports ...int) CustomizeRequestOption {
}
}
-// Deprecated: the modules API forces passing the image as part of the signature of the Run function.
+// WithReuseByName will mark a container to be reused if it exists or create a new one if it doesn't.
+// A container name must be provided to identify the container to be reused.
+func WithReuseByName(containerName string) CustomizeRequestOption {
+ return func(req *GenericContainerRequest) error {
+ if containerName == "" {
+ return errors.New("container name must be provided for reuse")
+ }
+ req.Name = containerName
+ req.Reuse = true
+ return nil
+ }
+}
+
// WithImage sets the image for a container
func WithImage(image string) CustomizeRequestOption {
return func(req *GenericContainerRequest) error {
@@ -334,3 +356,104 @@ func WithWaitStrategyAndDeadline(deadline time.Duration, strategies ...wait.Stra
return nil
}
}
+
+// WithImageMount mounts an image to a container, passing the source image name,
+// the relative subpath to mount in that image, and the mount point in the target container.
+// This option validates that the subpath is a relative path, raising an error otherwise.
+func WithImageMount(source string, subpath string, target ContainerMountTarget) CustomizeRequestOption {
+ return func(req *GenericContainerRequest) error {
+ src := NewDockerImageMountSource(source, subpath)
+
+ if err := src.Validate(); err != nil {
+ return fmt.Errorf("validate image mount source: %w", err)
+ }
+
+ req.Mounts = append(req.Mounts, ContainerMount{
+ Source: src,
+ Target: target,
+ })
+ return nil
+ }
+}
+
+// WithEntrypoint completely replaces the entrypoint of a container
+func WithEntrypoint(entrypoint ...string) CustomizeRequestOption {
+ return func(req *GenericContainerRequest) error {
+ req.Entrypoint = entrypoint
+ return nil
+ }
+}
+
+// WithEntrypointArgs appends the entrypoint arguments to the entrypoint of a container
+func WithEntrypointArgs(entrypointArgs ...string) CustomizeRequestOption {
+ return func(req *GenericContainerRequest) error {
+ req.Entrypoint = append(req.Entrypoint, entrypointArgs...)
+ return nil
+ }
+}
+
+// WithExposedPorts appends the ports to the exposed ports for a container
+func WithExposedPorts(ports ...string) CustomizeRequestOption {
+ return func(req *GenericContainerRequest) error {
+ req.ExposedPorts = append(req.ExposedPorts, ports...)
+ return nil
+ }
+}
+
+// WithCmd completely replaces the command for a container
+func WithCmd(cmd ...string) CustomizeRequestOption {
+ return func(req *GenericContainerRequest) error {
+ req.Cmd = cmd
+ return nil
+ }
+}
+
+// WithCmdArgs appends the command arguments to the command for a container
+func WithCmdArgs(cmdArgs ...string) CustomizeRequestOption {
+ return func(req *GenericContainerRequest) error {
+ req.Cmd = append(req.Cmd, cmdArgs...)
+ return nil
+ }
+}
+
+// WithLabels appends the labels to the labels for a container
+func WithLabels(labels map[string]string) CustomizeRequestOption {
+ return func(req *GenericContainerRequest) error {
+ if req.Labels == nil {
+ req.Labels = make(map[string]string)
+ }
+ for k, v := range labels {
+ req.Labels[k] = v
+ }
+ return nil
+ }
+}
+
+// WithMounts appends the mounts to the mounts for a container
+func WithMounts(mounts ...ContainerMount) CustomizeRequestOption {
+ return func(req *GenericContainerRequest) error {
+ req.Mounts = append(req.Mounts, mounts...)
+ return nil
+ }
+}
+
+// WithTmpfs appends the tmpfs mounts to the tmpfs mounts for a container
+func WithTmpfs(tmpfs map[string]string) CustomizeRequestOption {
+ return func(req *GenericContainerRequest) error {
+ if req.Tmpfs == nil {
+ req.Tmpfs = make(map[string]string)
+ }
+ for k, v := range tmpfs {
+ req.Tmpfs[k] = v
+ }
+ return nil
+ }
+}
+
+// WithFiles appends the files to the files for a container
+func WithFiles(files ...ContainerFile) CustomizeRequestOption {
+ return func(req *GenericContainerRequest) error {
+ req.Files = append(req.Files, files...)
+ return nil
+ }
+}
diff --git a/vendor/github.com/testcontainers/testcontainers-go/port_forwarding.go b/vendor/github.com/testcontainers/testcontainers-go/port_forwarding.go
index b9fc970..cd82361 100644
--- a/vendor/github.com/testcontainers/testcontainers-go/port_forwarding.go
+++ b/vendor/github.com/testcontainers/testcontainers-go/port_forwarding.go
@@ -172,7 +172,7 @@ func exposeHostPorts(ctx context.Context, req *ContainerRequest, ports ...int) (
return sshdContainer.exposeHostPort(ctx, req.HostAccessPorts...)
},
},
- PreStops: stopHooks,
+ PostStops: stopHooks,
PreTerminates: stopHooks,
}
diff --git a/vendor/github.com/testcontainers/testcontainers-go/reaper.go b/vendor/github.com/testcontainers/testcontainers-go/reaper.go
index 7b2d8b9..26cac14 100644
--- a/vendor/github.com/testcontainers/testcontainers-go/reaper.go
+++ b/vendor/github.com/testcontainers/testcontainers-go/reaper.go
@@ -382,13 +382,13 @@ func (r *reaperSpawner) newReaper(ctx context.Context, sessionID string, provide
Image: config.ReaperDefaultImage,
ExposedPorts: []string{string(port)},
Labels: core.DefaultLabels(sessionID),
- Privileged: tcConfig.RyukPrivileged,
WaitingFor: wait.ForListeningPort(port),
Name: reaperContainerNameFromSessionID(sessionID),
HostConfigModifier: func(hc *container.HostConfig) {
hc.AutoRemove = true
hc.Binds = []string{dockerHostMount + ":/var/run/docker.sock"}
hc.NetworkMode = Bridge
+ hc.Privileged = tcConfig.RyukPrivileged
},
Env: map[string]string{},
}
diff --git a/vendor/github.com/testcontainers/testcontainers-go/runtime.txt b/vendor/github.com/testcontainers/testcontainers-go/runtime.txt
index cc1923a..24ee5b1 100644
--- a/vendor/github.com/testcontainers/testcontainers-go/runtime.txt
+++ b/vendor/github.com/testcontainers/testcontainers-go/runtime.txt
@@ -1 +1 @@
-3.8
+3.13
diff --git a/vendor/github.com/testcontainers/testcontainers-go/testing.go b/vendor/github.com/testcontainers/testcontainers-go/testing.go
index 017f1a4..1f41913 100644
--- a/vendor/github.com/testcontainers/testcontainers-go/testing.go
+++ b/vendor/github.com/testcontainers/testcontainers-go/testing.go
@@ -53,6 +53,21 @@ func SkipIfDockerDesktop(t *testing.T, ctx context.Context) {
}
}
+// SkipIfNotDockerDesktop is a utility function capable of skipping tests
+// if tests are not run using Docker Desktop.
+func SkipIfNotDockerDesktop(t *testing.T, ctx context.Context) {
+ t.Helper()
+ cli, err := NewDockerClientWithOpts(ctx)
+ require.NoErrorf(t, err, "failed to create docker client: %s", err)
+
+ info, err := cli.Info(ctx)
+ require.NoErrorf(t, err, "failed to get docker info: %s", err)
+
+ if info.OperatingSystem != "Docker Desktop" {
+ t.Skip("Skipping test that needs Docker Desktop")
+ }
+}
+
// exampleLogConsumer {
// StdoutLogConsumer is a LogConsumer that prints the log to stdout
diff --git a/vendor/github.com/testcontainers/testcontainers-go/validator.go b/vendor/github.com/testcontainers/testcontainers-go/validator.go
new file mode 100644
index 0000000..a888586
--- /dev/null
+++ b/vendor/github.com/testcontainers/testcontainers-go/validator.go
@@ -0,0 +1,7 @@
+package testcontainers
+
+// Validator is an interface that can be implemented by types that need to validate their state.
+type Validator interface {
+ // Validate validates the state of the type.
+ Validate() error
+}
diff --git a/vendor/github.com/testcontainers/testcontainers-go/wait/all.go b/vendor/github.com/testcontainers/testcontainers-go/wait/all.go
index fb7eb4e..9bf4cbe 100644
--- a/vendor/github.com/testcontainers/testcontainers-go/wait/all.go
+++ b/vendor/github.com/testcontainers/testcontainers-go/wait/all.go
@@ -3,6 +3,7 @@ package wait
import (
"context"
"errors"
+ "reflect"
"time"
)
@@ -62,6 +63,13 @@ func (ms *MultiStrategy) WaitUntilReady(ctx context.Context, target StrategyTarg
}
for _, strategy := range ms.Strategies {
+ if strategy == nil || reflect.ValueOf(strategy).IsNil() {
+ // A module could be appending strategies after part of the container initialization,
+ // and use wait.ForAll on a not initialized strategy.
+ // In this case, we just skip the nil strategy.
+ continue
+ }
+
strategyCtx := ctx
// Set default Timeout when strategy implements StrategyTimeout
diff --git a/vendor/github.com/testcontainers/testcontainers-go/wait/http.go b/vendor/github.com/testcontainers/testcontainers-go/wait/http.go
index 2c7c655..32dc877 100644
--- a/vendor/github.com/testcontainers/testcontainers-go/wait/http.go
+++ b/vendor/github.com/testcontainers/testcontainers-go/wait/http.go
@@ -208,7 +208,7 @@ func (ws *HTTPStrategy) WaitUntilReady(ctx context.Context, target StrategyTarge
}
if lowestPort == "" {
- return errors.New("No exposed tcp ports or mapped ports - cannot wait for status")
+ return errors.New("no exposed tcp ports or mapped ports - cannot wait for status")
}
mappedPort, _ = nat.NewPort(lowestPort.Proto(), hostPort)
@@ -229,7 +229,7 @@ func (ws *HTTPStrategy) WaitUntilReady(ctx context.Context, target StrategyTarge
}
if mappedPort.Proto() != "tcp" {
- return errors.New("Cannot use HTTP client on non-TCP ports")
+ return errors.New("cannot use HTTP client on non-TCP ports")
}
}
diff --git a/vendor/github.com/testcontainers/testcontainers-go/wait/walk.go b/vendor/github.com/testcontainers/testcontainers-go/wait/walk.go
index 4685e50..009e563 100644
--- a/vendor/github.com/testcontainers/testcontainers-go/wait/walk.go
+++ b/vendor/github.com/testcontainers/testcontainers-go/wait/walk.go
@@ -5,18 +5,24 @@ import (
)
var (
- // VisitStop is used as a return value from [VisitFunc] to stop the walk.
+ // ErrVisitStop is used as a return value from [VisitFunc] to stop the walk.
// It is not returned as an error by any function.
- VisitStop = errors.New("stop the walk")
+ ErrVisitStop = errors.New("stop the walk")
- // VisitRemove is used as a return value from [VisitFunc] to have the current node removed.
+ // Deprecated: use [ErrVisitStop] instead.
+ VisitStop = ErrVisitStop
+
+ // ErrVisitRemove is used as a return value from [VisitFunc] to have the current node removed.
// It is not returned as an error by any function.
- VisitRemove = errors.New("remove this strategy")
+ ErrVisitRemove = errors.New("remove this strategy")
+
+ // Deprecated: use [ErrVisitRemove] instead.
+ VisitRemove = ErrVisitRemove
)
// VisitFunc is a function that visits a strategy node.
-// If it returns [VisitStop], the walk stops.
-// If it returns [VisitRemove], the current node is removed.
+// If it returns [ErrVisitStop], the walk stops.
+// If it returns [ErrVisitRemove], the current node is removed.
type VisitFunc func(root Strategy) error
// Walk walks the strategies tree and calls the visit function for each node.
@@ -26,7 +32,7 @@ func Walk(root *Strategy, visit VisitFunc) error {
}
if err := walk(root, visit); err != nil {
- if errors.Is(err, VisitRemove) || errors.Is(err, VisitStop) {
+ if errors.Is(err, ErrVisitRemove) || errors.Is(err, ErrVisitStop) {
return nil
}
return err
@@ -45,7 +51,7 @@ func walk(root *Strategy, visit VisitFunc) error {
// Allow the visit function to customize the behaviour of the walk before visiting the children.
if err := visit(*root); err != nil {
- if errors.Is(err, VisitRemove) {
+ if errors.Is(err, ErrVisitRemove) {
*root = nil
}
@@ -56,7 +62,7 @@ func walk(root *Strategy, visit VisitFunc) error {
var i int
for range s.Strategies {
if err := walk(&s.Strategies[i], visit); err != nil {
- if errors.Is(err, VisitRemove) {
+ if errors.Is(err, ErrVisitRemove) {
s.Strategies = append(s.Strategies[:i], s.Strategies[i+1:]...)
if errors.Is(err, VisitStop) {
return VisitStop