playwright-ruby-client 1.57.2.alpha1 → 1.58.1.alpha1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/AGENTS.md +4 -0
- data/CLAUDE/api_generation.md +28 -0
- data/CLAUDE/ci_expectations.md +23 -0
- data/CLAUDE/gem_release_flow.md +39 -0
- data/CLAUDE/past_upgrade_pr_patterns.md +42 -0
- data/CLAUDE/playwright_upgrade_workflow.md +35 -0
- data/CLAUDE/rspec_debugging.md +30 -0
- data/CLAUDE/unimplemented_examples.md +18 -0
- data/CLAUDE.md +32 -0
- data/documentation/docs/api/browser_type.md +1 -2
- data/documentation/docs/api/locator.md +1 -1
- data/documentation/docs/api/locator_assertions.md +1 -1
- data/documentation/docs/api/route.md +4 -1
- data/documentation/docs/article/getting_started.md +1 -1
- data/documentation/docs/article/guides/inspector.md +1 -1
- data/documentation/docs/article/guides/launch_browser.md +5 -5
- data/documentation/docs/article/guides/rails_integration.md +1 -1
- data/documentation/docs/article/guides/recording_video.md +2 -2
- data/documentation/docs/article/guides/semi_automation.md +1 -1
- data/documentation/docs/include/api_coverage.md +1 -0
- data/lib/playwright/channel_owners/browser_type.rb +2 -1
- data/lib/playwright/channel_owners/page.rb +4 -1
- data/lib/playwright/channel_owners/tracing.rb +15 -6
- data/lib/playwright/locator_assertions_impl.rb +1 -1
- data/lib/playwright/page_assertions_impl.rb +1 -1
- data/lib/playwright/version.rb +2 -2
- data/lib/playwright_api/browser_type.rb +4 -5
- data/lib/playwright_api/locator.rb +1 -1
- data/lib/playwright_api/locator_assertions.rb +1 -1
- data/lib/playwright_api/page.rb +5 -5
- data/lib/playwright_api/request.rb +12 -0
- data/lib/playwright_api/route.rb +4 -1
- data/sig/playwright.rbs +4 -4
- metadata +11 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 78c64e38b462ad2449eda1349128c44ae6dbe7adae66570b76cd886e005f418f
|
|
4
|
+
data.tar.gz: d410ab0adf418bbf8f43925984a95663b7f947519b85e9afa93bec64daf76f06
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 319787778e82280859a291247e01b4fc5626b12974e9d7e08fd7331beb596696f15cc83c09d9b6f2cb5a76c15ef30308cc9e9eb7f2f16462188d08bc72546ddc
|
|
7
|
+
data.tar.gz: df5b988a9124a42006720bee860c3ebc91804ebc9ce396a922b0dbd0e1a1c81798912cd42530f91dcde49da83432b60be17cded55408548d7e795a7991b8276b
|
data/AGENTS.md
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# API Generation
|
|
2
|
+
|
|
3
|
+
## Source of generated artifacts
|
|
4
|
+
|
|
5
|
+
- Input: `development/api.json`
|
|
6
|
+
- Generator script: `development/generate_api.rb`
|
|
7
|
+
|
|
8
|
+
## Generated outputs
|
|
9
|
+
|
|
10
|
+
- `lib/playwright_api/*.rb`
|
|
11
|
+
- `documentation/docs/api/**/*.md`
|
|
12
|
+
- `documentation/docs/include/api_coverage.md`
|
|
13
|
+
- `sig/playwright.rbs`
|
|
14
|
+
- `development/unimplemented_examples.md`
|
|
15
|
+
|
|
16
|
+
## Critical rules
|
|
17
|
+
|
|
18
|
+
- `lib/playwright_api/` is not tracked by Git (`lib/playwright_api/.gitignore` only).
|
|
19
|
+
- Do not manually edit `lib/playwright_api/*.rb`.
|
|
20
|
+
- Re-run `development/generate_api.rb` whenever API specs change.
|
|
21
|
+
|
|
22
|
+
## Typical command set
|
|
23
|
+
|
|
24
|
+
```sh
|
|
25
|
+
rm lib/playwright_api/*.rb
|
|
26
|
+
find documentation/docs -name "*.md" | grep -v documentation/docs/article/ | xargs rm
|
|
27
|
+
bundle exec ruby development/generate_api.rb
|
|
28
|
+
```
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# CI Expectations
|
|
2
|
+
|
|
3
|
+
## Main guardrails
|
|
4
|
+
|
|
5
|
+
`/.github/workflows/check.yml` detects stale generated artifacts.
|
|
6
|
+
|
|
7
|
+
Checked paths:
|
|
8
|
+
|
|
9
|
+
- `development/api.json`
|
|
10
|
+
- `documentation/docs/**`
|
|
11
|
+
- `development/unimplemented_examples.md`
|
|
12
|
+
|
|
13
|
+
## Practical implication
|
|
14
|
+
|
|
15
|
+
- If API-related code changes, regenerate artifacts before finishing.
|
|
16
|
+
- If you open a PR without regeneration, `check.yml` will likely fail.
|
|
17
|
+
|
|
18
|
+
## Related workflows
|
|
19
|
+
|
|
20
|
+
- `/.github/workflows/rspec.yml`
|
|
21
|
+
- `/.github/workflows/deploy.yml`
|
|
22
|
+
|
|
23
|
+
These workflows also depend on `bundle exec ruby development/generate_api.rb`.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Gem Release Flow
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Pushing a Git tag triggers `.github/workflows/deploy.yml`, which builds and publishes the gem to RubyGems.
|
|
6
|
+
|
|
7
|
+
## Tag format
|
|
8
|
+
|
|
9
|
+
The deploy workflow triggers on tags matching these patterns:
|
|
10
|
+
|
|
11
|
+
- `X.Y.Z` — stable release (e.g. `1.58.0`)
|
|
12
|
+
- `X.Y.betaN` — beta release (e.g. `1.58.beta1`)
|
|
13
|
+
- `X.Y.Z.alphaN` — alpha release (e.g. `1.58.1.alpha1`)
|
|
14
|
+
|
|
15
|
+
## Steps to release
|
|
16
|
+
|
|
17
|
+
1. Update `lib/playwright/version.rb`:
|
|
18
|
+
- Set `Playwright::VERSION` to the target version string.
|
|
19
|
+
- `COMPATIBLE_PLAYWRIGHT_VERSION` stays at the base Playwright version.
|
|
20
|
+
|
|
21
|
+
2. Commit the version change.
|
|
22
|
+
|
|
23
|
+
3. Create and push a Git tag matching the version exactly:
|
|
24
|
+
```sh
|
|
25
|
+
git tag 1.58.1.alpha1
|
|
26
|
+
git push origin 1.58.1.alpha1
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
4. The deploy workflow will:
|
|
30
|
+
- Check out the tagged commit.
|
|
31
|
+
- Verify `Playwright::VERSION == RELEASE_TAG` (must match exactly).
|
|
32
|
+
- Run `bundle exec ruby development/generate_api.rb` to generate API code.
|
|
33
|
+
- Run `rake build` to build the gem.
|
|
34
|
+
- Push the gem to RubyGems using the `RUBYGEMS_API_KEY` secret.
|
|
35
|
+
|
|
36
|
+
## Important notes
|
|
37
|
+
|
|
38
|
+
- The `Playwright::VERSION` in `lib/playwright/version.rb` **must exactly match** the Git tag name. If they differ, the deploy job fails at the version check step.
|
|
39
|
+
- Alpha/beta tags do NOT require a separate branch — they can be tagged on any commit.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Past Upgrade PR Patterns
|
|
2
|
+
|
|
3
|
+
Common patterns observed from `Update Playwright driver to 1.xx.x` PRs reviewed with `gh`.
|
|
4
|
+
|
|
5
|
+
## PR sample
|
|
6
|
+
|
|
7
|
+
- `#366` (1.58.0)
|
|
8
|
+
- `#360` (1.57.0)
|
|
9
|
+
- `#354` (1.56.1)
|
|
10
|
+
- `#348` (1.55.0)
|
|
11
|
+
- `#341` (1.54.1)
|
|
12
|
+
- `#336` (1.53.0)
|
|
13
|
+
- `#331` (1.52.0)
|
|
14
|
+
- `#327` (1.51.0)
|
|
15
|
+
|
|
16
|
+
## Frequently changed files
|
|
17
|
+
|
|
18
|
+
Almost every time:
|
|
19
|
+
|
|
20
|
+
- `development/CLI_VERSION`
|
|
21
|
+
- `development/api.json`
|
|
22
|
+
- `lib/playwright/version.rb`
|
|
23
|
+
|
|
24
|
+
High frequency:
|
|
25
|
+
|
|
26
|
+
- `documentation/docs/api/*.md`
|
|
27
|
+
- `documentation/docs/include/api_coverage.md`
|
|
28
|
+
- `development/generate_api/example_codes.rb`
|
|
29
|
+
- `spec/integration/example_spec.rb`
|
|
30
|
+
- `lib/playwright/channel_owners/page.rb`
|
|
31
|
+
- `lib/playwright/locator_impl.rb`
|
|
32
|
+
|
|
33
|
+
Sometimes:
|
|
34
|
+
|
|
35
|
+
- `development/generate_api.rb`
|
|
36
|
+
- `development/unimplemented_examples.md`
|
|
37
|
+
|
|
38
|
+
## Work style trend
|
|
39
|
+
|
|
40
|
+
- The first commit often updates version files and generated API artifacts.
|
|
41
|
+
- Follow-up commits often add/update specs and then implement `lib/playwright/**` changes.
|
|
42
|
+
- Broader upstream changes usually increase docs/example/assets updates.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Playwright Upgrade Workflow
|
|
2
|
+
|
|
3
|
+
## Scope
|
|
4
|
+
|
|
5
|
+
Standard process for `Update Playwright driver to 1.xx.x` tasks.
|
|
6
|
+
|
|
7
|
+
## Order (Do not reorder)
|
|
8
|
+
|
|
9
|
+
1. Update versions
|
|
10
|
+
- `development/CLI_VERSION`
|
|
11
|
+
- `lib/playwright/version.rb` (`VERSION`, `COMPATIBLE_PLAYWRIGHT_VERSION`)
|
|
12
|
+
|
|
13
|
+
2. Update API definition
|
|
14
|
+
- Set `PLAYWRIGHT_CLI_EXECUTABLE_PATH`
|
|
15
|
+
- `$PLAYWRIGHT_CLI_EXECUTABLE_PATH print-api-json | jq . > development/api.json`
|
|
16
|
+
|
|
17
|
+
3. Clean before generation + regenerate
|
|
18
|
+
- `rm lib/playwright_api/*.rb`
|
|
19
|
+
- `find documentation/docs -name "*.md" | grep -v documentation/docs/article/ | xargs rm`
|
|
20
|
+
- `bundle exec ruby development/generate_api.rb`
|
|
21
|
+
|
|
22
|
+
4. Update tests first
|
|
23
|
+
- Add/update `spec/` changes that represent upstream behavior differences.
|
|
24
|
+
|
|
25
|
+
5. Implement
|
|
26
|
+
- Apply minimal implementation changes in `lib/playwright/**`.
|
|
27
|
+
|
|
28
|
+
6. Run tests
|
|
29
|
+
- `bundle exec rspec`
|
|
30
|
+
- Run focused specs first while iterating, then run the full suite.
|
|
31
|
+
|
|
32
|
+
## Notes
|
|
33
|
+
|
|
34
|
+
- During upgrade work, prefer the steps in `development/README.md`.
|
|
35
|
+
- `development/update_playwright_driver.sh` can be used as a helper script.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# RSpec Debugging
|
|
2
|
+
|
|
3
|
+
## Critical execution rule
|
|
4
|
+
|
|
5
|
+
- Run RSpec via `rbenv exec`.
|
|
6
|
+
- Some environments fail with plain `bundle exec rspec`, so always use `rbenv exec bundle exec rspec ...`.
|
|
7
|
+
|
|
8
|
+
## Debug rule when spec fails
|
|
9
|
+
|
|
10
|
+
- On failure, rerun with `DEBUG=1`.
|
|
11
|
+
- Use `DEBUG=1` output to inspect Playwright protocol logs and isolate the issue.
|
|
12
|
+
|
|
13
|
+
## Example
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
rbenv exec bundle exec rspec spec/integration/page/aria_snapshot_ai_spec.rb
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
```sh
|
|
20
|
+
DEBUG=1 rbenv exec bundle exec rspec spec/integration/page/aria_snapshot_ai_spec.rb
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Node.js Playwright protocol log
|
|
24
|
+
|
|
25
|
+
- Node.js Playwright protocol logs can be captured with `DEBUG=pw:*`.
|
|
26
|
+
- This is useful when comparing behavior against the Ruby client.
|
|
27
|
+
|
|
28
|
+
```sh
|
|
29
|
+
DEBUG=pw:* node script.mjs 2>&1 | head -200
|
|
30
|
+
```
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# unimplemented_examples.md
|
|
2
|
+
|
|
3
|
+
## What it is
|
|
4
|
+
|
|
5
|
+
- `development/unimplemented_examples.md` is a generated artifact.
|
|
6
|
+
- It lists examples from API docs that could not be converted to Ruby examples.
|
|
7
|
+
|
|
8
|
+
## How examples are converted
|
|
9
|
+
|
|
10
|
+
- Source: API doc comments
|
|
11
|
+
- Conversion rules: `development/generate_api/example_codes.rb`
|
|
12
|
+
- Unmapped examples remain in Python in docs and are listed in `development/unimplemented_examples.md`.
|
|
13
|
+
|
|
14
|
+
## When this file changes
|
|
15
|
+
|
|
16
|
+
1. Review the diff to identify unmapped examples.
|
|
17
|
+
2. Add conversion mappings to `development/generate_api/example_codes.rb` when needed.
|
|
18
|
+
3. Re-run `bundle exec ruby development/generate_api.rb`.
|
data/CLAUDE.md
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file contains only the checks that must be verified first.
|
|
4
|
+
For detailed rules, see `CLAUDE/*.md`.
|
|
5
|
+
|
|
6
|
+
## Must Check First
|
|
7
|
+
|
|
8
|
+
1. Determine first whether the task is a Playwright version upgrade.
|
|
9
|
+
2. Confirm generated-code handling.
|
|
10
|
+
- `lib/playwright_api/*.rb` is auto-generated by `development/generate_api.rb`.
|
|
11
|
+
- `lib/playwright_api/` is not tracked by Git. Do not edit generated files manually.
|
|
12
|
+
3. Confirm change order.
|
|
13
|
+
- For version upgrade work, update tests first, then implement `lib/playwright/**`.
|
|
14
|
+
4. Confirm generation and diff consistency.
|
|
15
|
+
- Update `development/api.json`, run generation, and verify generated diffs.
|
|
16
|
+
5. Confirm CI-required generated files.
|
|
17
|
+
- `development/api.json`
|
|
18
|
+
- `documentation/docs/**`
|
|
19
|
+
- `development/unimplemented_examples.md`
|
|
20
|
+
6. Confirm RSpec execution mode (critical).
|
|
21
|
+
- Run RSpec via `rbenv exec`.
|
|
22
|
+
- On failure, rerun with `DEBUG=1` and inspect protocol logs.
|
|
23
|
+
|
|
24
|
+
## Topic Docs
|
|
25
|
+
|
|
26
|
+
- `CLAUDE/playwright_upgrade_workflow.md`
|
|
27
|
+
- `CLAUDE/api_generation.md`
|
|
28
|
+
- `CLAUDE/unimplemented_examples.md`
|
|
29
|
+
- `CLAUDE/ci_expectations.md`
|
|
30
|
+
- `CLAUDE/past_upgrade_pr_patterns.md`
|
|
31
|
+
- `CLAUDE/rspec_debugging.md`
|
|
32
|
+
- `CLAUDE/gem_release_flow.md`
|
|
@@ -25,6 +25,7 @@ end
|
|
|
25
25
|
def connect_over_cdp(
|
|
26
26
|
endpointURL,
|
|
27
27
|
headers: nil,
|
|
28
|
+
isLocal: nil,
|
|
28
29
|
slowMo: nil,
|
|
29
30
|
timeout: nil,
|
|
30
31
|
&block)
|
|
@@ -63,7 +64,6 @@ def launch(
|
|
|
63
64
|
args: nil,
|
|
64
65
|
channel: nil,
|
|
65
66
|
chromiumSandbox: nil,
|
|
66
|
-
devtools: nil,
|
|
67
67
|
downloadsPath: nil,
|
|
68
68
|
env: nil,
|
|
69
69
|
executablePath: nil,
|
|
@@ -126,7 +126,6 @@ def launch_persistent_context(
|
|
|
126
126
|
colorScheme: nil,
|
|
127
127
|
contrast: nil,
|
|
128
128
|
deviceScaleFactor: nil,
|
|
129
|
-
devtools: nil,
|
|
130
129
|
downloadsPath: nil,
|
|
131
130
|
env: nil,
|
|
132
131
|
executablePath: nil,
|
|
@@ -343,7 +343,7 @@ def description
|
|
|
343
343
|
```
|
|
344
344
|
|
|
345
345
|
|
|
346
|
-
Returns locator description previously set with [Locator#describe](./locator#describe). Returns `null` if no custom description has been set.
|
|
346
|
+
Returns locator description previously set with [Locator#describe](./locator#describe). Returns `null` if no custom description has been set.
|
|
347
347
|
|
|
348
348
|
**Usage**
|
|
349
349
|
|
|
@@ -524,7 +524,7 @@ Let's see how we can use the assertion:
|
|
|
524
524
|
|
|
525
525
|
```ruby
|
|
526
526
|
# ✓ Contains the right items in the right order
|
|
527
|
-
expect(page.locator("ul > li")).to contain_text(["Text 1", "Text 3"
|
|
527
|
+
expect(page.locator("ul > li")).to contain_text(["Text 1", "Text 3"])
|
|
528
528
|
|
|
529
529
|
# ✖ Wrong order
|
|
530
530
|
expect(page.locator("ul > li")).to contain_text(["Text 3", "Text 2"])
|
|
@@ -49,7 +49,10 @@ The `headers` option applies to both the routed request and any redirects it ini
|
|
|
49
49
|
|
|
50
50
|
[Route#continue](./route#continue) will immediately send the request to the network, other matching handlers won't be invoked. Use [Route#fallback](./route#fallback) If you want next matching handler in the chain to be invoked.
|
|
51
51
|
|
|
52
|
-
**NOTE**:
|
|
52
|
+
**NOTE**: Some request headers are **forbidden** and cannot be overridden (for example, `Cookie`, `Host`, `Content-Length` and others, see [this MDN page](https://developer.mozilla.org/en-US/docs/Glossary/Forbidden_request_header) for full list).
|
|
53
|
+
If an override is provided for a forbidden header, it will be ignored and the original request header will be used.
|
|
54
|
+
|
|
55
|
+
To set custom cookies, use [BrowserContext#add_cookies](./browser_context#add_cookies).
|
|
53
56
|
|
|
54
57
|
## fallback
|
|
55
58
|
|
|
@@ -19,7 +19,7 @@ $ npx playwright install
|
|
|
19
19
|
|
|
20
20
|
and then set `playwright_cli_executable_path: "npx playwright"` into `Playwright.create`.
|
|
21
21
|
|
|
22
|
-
Other methods of installation
|
|
22
|
+
Other methods of installation are also available. See the detail in [Download Playwright driver](./guides/download_playwright_driver)
|
|
23
23
|
|
|
24
24
|
## Enjoy with examples
|
|
25
25
|
|
|
@@ -8,7 +8,7 @@ sidebar_position: 2
|
|
|
8
8
|
|
|
9
9
|
## Create Playwright session
|
|
10
10
|
|
|
11
|
-
In
|
|
11
|
+
In order to launch browser, it is required to create Playwright session.
|
|
12
12
|
|
|
13
13
|
In previous examples,
|
|
14
14
|
|
|
@@ -18,7 +18,7 @@ Playwright.create(playwright_cli_executable_path: 'npx playwright') do |playwrig
|
|
|
18
18
|
end
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
-
this is the exact procedure for creating Playwright session. Choose either
|
|
21
|
+
this is the exact procedure for creating Playwright session. Choose either method for creating the session.
|
|
22
22
|
|
|
23
23
|
### Define scoped Playwright session with block
|
|
24
24
|
|
|
@@ -28,13 +28,13 @@ Playwright.create(playwright_cli_executable_path: 'npx playwright') do |playwrig
|
|
|
28
28
|
end
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
-
As
|
|
31
|
+
As described repeatedly, this is the recommended way for creating a Playwright session. Even when any exception happens, Playwright session is safely ended on leaving the block.
|
|
32
32
|
|
|
33
33
|
Internally `playwright run-driver` session is alive during the block.
|
|
34
34
|
|
|
35
35
|
### Define start/end of the Playwright session separately without block.
|
|
36
36
|
|
|
37
|
-
Sometimes we have to define
|
|
37
|
+
Sometimes we have to define separate start/end definitions. `playwright-ruby-client` also allows it.
|
|
38
38
|
|
|
39
39
|
```rb
|
|
40
40
|
class SomeClass
|
|
@@ -103,7 +103,7 @@ Also we can use `Browser#new_page` to create a new window and new tab at once.
|
|
|
103
103
|
|
|
104
104
|
```rb
|
|
105
105
|
Playwright.create(playwright_cli_executable_path: 'npx playwright') do |playwright|
|
|
106
|
-
playwright.chromium.launch(headless: false) do |browser| # Chromium task icon
|
|
106
|
+
playwright.chromium.launch(headless: false) do |browser| # Chromium task icon appears.
|
|
107
107
|
context = browser.new_context # Prepare new window.
|
|
108
108
|
page = context.new_page # Open new window and new tab here. (about:blank)
|
|
109
109
|
page.goto('https://example.com') # Navigate to a site.
|
|
@@ -217,7 +217,7 @@ before do |example|
|
|
|
217
217
|
end
|
|
218
218
|
```
|
|
219
219
|
|
|
220
|
-

|
|
221
221
|
|
|
222
222
|
For more details, refer [Recording video](./recording_video.md#using-screen-recording-from-capybara-driver)
|
|
223
223
|
|
|
@@ -33,7 +33,7 @@ playwright.chromium.launch do |browser|
|
|
|
33
33
|
|
|
34
34
|
Playwright puts videos on the directory specified at `record_video_dir`.
|
|
35
35
|
|
|
36
|
-
The previous example uses [Dir#mktmpdir](https://docs.ruby-lang.org/ja/latest/method/Dir/s/mktmpdir.html) for storing videos into a
|
|
36
|
+
The previous example uses [Dir#mktmpdir](https://docs.ruby-lang.org/ja/latest/method/Dir/s/mktmpdir.html) for storing videos into a temporary directory. Also we simply specify a relative or absolute path like `./my_videos/` or `/path/to/videos`.
|
|
37
37
|
|
|
38
38
|
## Getting video path and recorded video
|
|
39
39
|
|
|
@@ -42,7 +42,7 @@ This is really confusing for beginners, but in Playwright
|
|
|
42
42
|
* We can get the video path **only when page is alive (before calling BrowserContext#close or Page#close)**
|
|
43
43
|
* We can acquire the completely saved video **only after calling BrowserContext#close**
|
|
44
44
|
|
|
45
|
-
So in most
|
|
45
|
+
So in most cases, we have to store the video path in advance, and handle the saved video after BrowserContext is closed, as shown in the previous example code.
|
|
46
46
|
|
|
47
47
|
### Using `video#save_as(path)`
|
|
48
48
|
|
|
@@ -5,7 +5,7 @@ sidebar_position: 20
|
|
|
5
5
|
# Semi-automation
|
|
6
6
|
|
|
7
7
|
Playwright Browser context is isolated and not persisted by default. But we can also use persistent browser context using [BrowserType#launch_persistent_context](/docs/api/browser_type#launch_persistent_context).
|
|
8
|
-
This
|
|
8
|
+
This allows us to intervene in automation, for example
|
|
9
9
|
|
|
10
10
|
* Authenticate with OAuth2 manually before automation
|
|
11
11
|
* Testing a page after some chrome extensions are installed manually
|
|
@@ -60,12 +60,13 @@ module Playwright
|
|
|
60
60
|
end
|
|
61
61
|
end
|
|
62
62
|
|
|
63
|
-
def connect_over_cdp(endpointURL, headers: nil, slowMo: nil, timeout: nil, &block)
|
|
63
|
+
def connect_over_cdp(endpointURL, headers: nil, isLocal: nil, slowMo: nil, timeout: nil, &block)
|
|
64
64
|
raise 'Connecting over CDP is only supported in Chromium.' unless name == 'chromium'
|
|
65
65
|
|
|
66
66
|
params = {
|
|
67
67
|
endpointURL: endpointURL,
|
|
68
68
|
headers: headers,
|
|
69
|
+
isLocal: isLocal,
|
|
69
70
|
slowMo: slowMo,
|
|
70
71
|
timeout: @timeout_settings.timeout(timeout),
|
|
71
72
|
}.compact
|
|
@@ -98,7 +98,7 @@ module Playwright
|
|
|
98
98
|
|
|
99
99
|
private def on_route(route)
|
|
100
100
|
route.send(:update_context, self)
|
|
101
|
-
|
|
101
|
+
return if @close_was_called
|
|
102
102
|
# It is not desired to use PlaywrightApi.wrap directly.
|
|
103
103
|
# However it is a little difficult to define wrapper for `handler` parameter in generate_api.
|
|
104
104
|
# Just a workaround...
|
|
@@ -508,6 +508,9 @@ module Playwright
|
|
|
508
508
|
|
|
509
509
|
def close(runBeforeUnload: nil, reason: nil)
|
|
510
510
|
@close_reason = reason
|
|
511
|
+
unless runBeforeUnload
|
|
512
|
+
@close_was_called = true
|
|
513
|
+
end
|
|
511
514
|
if @owned_context
|
|
512
515
|
@owned_context.close
|
|
513
516
|
else
|
|
@@ -23,7 +23,8 @@ module Playwright
|
|
|
23
23
|
@is_tracing = true
|
|
24
24
|
@connection.set_in_tracing(true)
|
|
25
25
|
end
|
|
26
|
-
|
|
26
|
+
local_utils = @connection.local_utils
|
|
27
|
+
@stacks_id = local_utils&.tracing_started(@traces_dir, trace_name)
|
|
27
28
|
end
|
|
28
29
|
|
|
29
30
|
def stop_chunk(path: nil)
|
|
@@ -40,20 +41,26 @@ module Playwright
|
|
|
40
41
|
@is_tracing = false
|
|
41
42
|
@connection.set_in_tracing(false)
|
|
42
43
|
end
|
|
44
|
+
local_utils = @connection.local_utils
|
|
43
45
|
|
|
44
46
|
unless file_path
|
|
45
47
|
# Not interested in any artifacts
|
|
46
48
|
@channel.send_message_to_server('tracingStopChunk', mode: 'discard')
|
|
47
49
|
if @stacks_id
|
|
48
|
-
|
|
50
|
+
local_utils.trace_discarded(@stacks_id) if local_utils
|
|
49
51
|
end
|
|
50
52
|
|
|
51
53
|
return
|
|
52
54
|
end
|
|
53
55
|
|
|
54
|
-
|
|
56
|
+
is_local = !@connection.remote?
|
|
57
|
+
if is_local
|
|
58
|
+
unless local_utils
|
|
59
|
+
raise 'Cannot save trace because localUtils is unavailable.'
|
|
60
|
+
end
|
|
61
|
+
|
|
55
62
|
result = @channel.send_message_to_server_result('tracingStopChunk', mode: 'entries')
|
|
56
|
-
|
|
63
|
+
local_utils.zip(
|
|
57
64
|
zipFile: file_path,
|
|
58
65
|
entries: result['entries'],
|
|
59
66
|
stacksId: @stacks_id,
|
|
@@ -69,7 +76,7 @@ module Playwright
|
|
|
69
76
|
# The artifact may be missing if the browser closed while stopping tracing.
|
|
70
77
|
unless result['artifact']
|
|
71
78
|
if @stacks_id
|
|
72
|
-
|
|
79
|
+
local_utils.trace_discarded(@stacks_id) if local_utils
|
|
73
80
|
end
|
|
74
81
|
|
|
75
82
|
return
|
|
@@ -80,7 +87,9 @@ module Playwright
|
|
|
80
87
|
artifact.save_as(file_path)
|
|
81
88
|
artifact.delete
|
|
82
89
|
|
|
83
|
-
|
|
90
|
+
return unless local_utils
|
|
91
|
+
|
|
92
|
+
local_utils.zip(
|
|
84
93
|
zipFile: file_path,
|
|
85
94
|
entries: [],
|
|
86
95
|
stacksId: @stacks_id,
|
|
@@ -21,7 +21,7 @@ module Playwright
|
|
|
21
21
|
private def expect_impl(expression, expect_options, expected, message, title)
|
|
22
22
|
expect_options[:timeout] ||= @default_expect_timeout
|
|
23
23
|
expect_options[:isNot] = @is_not
|
|
24
|
-
message.gsub
|
|
24
|
+
message = message.gsub("expected to", "not expected to") if @is_not
|
|
25
25
|
expect_options.delete(:useInnerText) if expect_options.key?(:useInnerText) && expect_options[:useInnerText].nil?
|
|
26
26
|
|
|
27
27
|
result = @locator.expect(expression, expect_options, title)
|
|
@@ -22,7 +22,7 @@ module Playwright
|
|
|
22
22
|
private def expect_impl(expression, expect_options, expected, message, title)
|
|
23
23
|
expect_options[:timeout] ||= @default_expect_timeout
|
|
24
24
|
expect_options[:isNot] = @is_not
|
|
25
|
-
message.gsub
|
|
25
|
+
message = message.gsub("expected to", "not expected to") if @is_not
|
|
26
26
|
expect_options.delete(:useInnerText) if expect_options.key?(:useInnerText) && expect_options[:useInnerText].nil?
|
|
27
27
|
|
|
28
28
|
result = @frame.expect(nil, expression, expect_options, title)
|
data/lib/playwright/version.rb
CHANGED
|
@@ -51,10 +51,11 @@ module Playwright
|
|
|
51
51
|
def connect_over_cdp(
|
|
52
52
|
endpointURL,
|
|
53
53
|
headers: nil,
|
|
54
|
+
isLocal: nil,
|
|
54
55
|
slowMo: nil,
|
|
55
56
|
timeout: nil,
|
|
56
57
|
&block)
|
|
57
|
-
wrap_impl(@impl.connect_over_cdp(unwrap_impl(endpointURL), headers: unwrap_impl(headers), slowMo: unwrap_impl(slowMo), timeout: unwrap_impl(timeout), &wrap_block_call(block)))
|
|
58
|
+
wrap_impl(@impl.connect_over_cdp(unwrap_impl(endpointURL), headers: unwrap_impl(headers), isLocal: unwrap_impl(isLocal), slowMo: unwrap_impl(slowMo), timeout: unwrap_impl(timeout), &wrap_block_call(block)))
|
|
58
59
|
end
|
|
59
60
|
|
|
60
61
|
#
|
|
@@ -95,7 +96,6 @@ module Playwright
|
|
|
95
96
|
args: nil,
|
|
96
97
|
channel: nil,
|
|
97
98
|
chromiumSandbox: nil,
|
|
98
|
-
devtools: nil,
|
|
99
99
|
downloadsPath: nil,
|
|
100
100
|
env: nil,
|
|
101
101
|
executablePath: nil,
|
|
@@ -110,7 +110,7 @@ module Playwright
|
|
|
110
110
|
timeout: nil,
|
|
111
111
|
tracesDir: nil,
|
|
112
112
|
&block)
|
|
113
|
-
wrap_impl(@impl.launch(args: unwrap_impl(args), channel: unwrap_impl(channel), chromiumSandbox: unwrap_impl(chromiumSandbox),
|
|
113
|
+
wrap_impl(@impl.launch(args: unwrap_impl(args), channel: unwrap_impl(channel), chromiumSandbox: unwrap_impl(chromiumSandbox), downloadsPath: unwrap_impl(downloadsPath), env: unwrap_impl(env), executablePath: unwrap_impl(executablePath), firefoxUserPrefs: unwrap_impl(firefoxUserPrefs), handleSIGHUP: unwrap_impl(handleSIGHUP), handleSIGINT: unwrap_impl(handleSIGINT), handleSIGTERM: unwrap_impl(handleSIGTERM), headless: unwrap_impl(headless), ignoreDefaultArgs: unwrap_impl(ignoreDefaultArgs), proxy: unwrap_impl(proxy), slowMo: unwrap_impl(slowMo), timeout: unwrap_impl(timeout), tracesDir: unwrap_impl(tracesDir), &wrap_block_call(block)))
|
|
114
114
|
end
|
|
115
115
|
|
|
116
116
|
#
|
|
@@ -130,7 +130,6 @@ module Playwright
|
|
|
130
130
|
colorScheme: nil,
|
|
131
131
|
contrast: nil,
|
|
132
132
|
deviceScaleFactor: nil,
|
|
133
|
-
devtools: nil,
|
|
134
133
|
downloadsPath: nil,
|
|
135
134
|
env: nil,
|
|
136
135
|
executablePath: nil,
|
|
@@ -171,7 +170,7 @@ module Playwright
|
|
|
171
170
|
userAgent: nil,
|
|
172
171
|
viewport: nil,
|
|
173
172
|
&block)
|
|
174
|
-
wrap_impl(@impl.launch_persistent_context(unwrap_impl(userDataDir), acceptDownloads: unwrap_impl(acceptDownloads), args: unwrap_impl(args), baseURL: unwrap_impl(baseURL), bypassCSP: unwrap_impl(bypassCSP), channel: unwrap_impl(channel), chromiumSandbox: unwrap_impl(chromiumSandbox), clientCertificates: unwrap_impl(clientCertificates), colorScheme: unwrap_impl(colorScheme), contrast: unwrap_impl(contrast), deviceScaleFactor: unwrap_impl(deviceScaleFactor),
|
|
173
|
+
wrap_impl(@impl.launch_persistent_context(unwrap_impl(userDataDir), acceptDownloads: unwrap_impl(acceptDownloads), args: unwrap_impl(args), baseURL: unwrap_impl(baseURL), bypassCSP: unwrap_impl(bypassCSP), channel: unwrap_impl(channel), chromiumSandbox: unwrap_impl(chromiumSandbox), clientCertificates: unwrap_impl(clientCertificates), colorScheme: unwrap_impl(colorScheme), contrast: unwrap_impl(contrast), deviceScaleFactor: unwrap_impl(deviceScaleFactor), downloadsPath: unwrap_impl(downloadsPath), env: unwrap_impl(env), executablePath: unwrap_impl(executablePath), extraHTTPHeaders: unwrap_impl(extraHTTPHeaders), firefoxUserPrefs: unwrap_impl(firefoxUserPrefs), forcedColors: unwrap_impl(forcedColors), geolocation: unwrap_impl(geolocation), handleSIGHUP: unwrap_impl(handleSIGHUP), handleSIGINT: unwrap_impl(handleSIGINT), handleSIGTERM: unwrap_impl(handleSIGTERM), hasTouch: unwrap_impl(hasTouch), headless: unwrap_impl(headless), httpCredentials: unwrap_impl(httpCredentials), ignoreDefaultArgs: unwrap_impl(ignoreDefaultArgs), ignoreHTTPSErrors: unwrap_impl(ignoreHTTPSErrors), isMobile: unwrap_impl(isMobile), javaScriptEnabled: unwrap_impl(javaScriptEnabled), locale: unwrap_impl(locale), noViewport: unwrap_impl(noViewport), offline: unwrap_impl(offline), permissions: unwrap_impl(permissions), proxy: unwrap_impl(proxy), record_har_content: unwrap_impl(record_har_content), record_har_mode: unwrap_impl(record_har_mode), record_har_omit_content: unwrap_impl(record_har_omit_content), record_har_path: unwrap_impl(record_har_path), record_har_url_filter: unwrap_impl(record_har_url_filter), record_video_dir: unwrap_impl(record_video_dir), record_video_size: unwrap_impl(record_video_size), reducedMotion: unwrap_impl(reducedMotion), screen: unwrap_impl(screen), serviceWorkers: unwrap_impl(serviceWorkers), slowMo: unwrap_impl(slowMo), strictSelectors: unwrap_impl(strictSelectors), timeout: unwrap_impl(timeout), timezoneId: unwrap_impl(timezoneId), tracesDir: unwrap_impl(tracesDir), userAgent: unwrap_impl(userAgent), viewport: unwrap_impl(viewport), &wrap_block_call(block)))
|
|
175
174
|
end
|
|
176
175
|
|
|
177
176
|
#
|
|
@@ -291,7 +291,7 @@ module Playwright
|
|
|
291
291
|
end
|
|
292
292
|
|
|
293
293
|
#
|
|
294
|
-
# Returns locator description previously set with [`method: Locator.describe`]. Returns `null` if no custom description has been set.
|
|
294
|
+
# Returns locator description previously set with [`method: Locator.describe`]. Returns `null` if no custom description has been set.
|
|
295
295
|
#
|
|
296
296
|
# **Usage**
|
|
297
297
|
#
|
|
@@ -413,7 +413,7 @@ module Playwright
|
|
|
413
413
|
# from playwright.sync_api import expect
|
|
414
414
|
#
|
|
415
415
|
# # ✓ Contains the right items in the right order
|
|
416
|
-
# expect(page.locator("ul > li")).to_contain_text(["Text 1", "Text 3"
|
|
416
|
+
# expect(page.locator("ul > li")).to_contain_text(["Text 1", "Text 3"])
|
|
417
417
|
#
|
|
418
418
|
# # ✖ Wrong order
|
|
419
419
|
# expect(page.locator("ul > li")).to_contain_text(["Text 3", "Text 2"])
|
data/lib/playwright_api/page.rb
CHANGED
|
@@ -1827,11 +1827,6 @@ module Playwright
|
|
|
1827
1827
|
wrap_impl(@impl.start_js_coverage(resetOnNavigation: unwrap_impl(resetOnNavigation), reportAnonymousScripts: unwrap_impl(reportAnonymousScripts)))
|
|
1828
1828
|
end
|
|
1829
1829
|
|
|
1830
|
-
# @nodoc
|
|
1831
|
-
def stop_css_coverage
|
|
1832
|
-
wrap_impl(@impl.stop_css_coverage)
|
|
1833
|
-
end
|
|
1834
|
-
|
|
1835
1830
|
# @nodoc
|
|
1836
1831
|
def stop_js_coverage
|
|
1837
1832
|
wrap_impl(@impl.stop_js_coverage)
|
|
@@ -1847,6 +1842,11 @@ module Playwright
|
|
|
1847
1842
|
wrap_impl(@impl.owned_context=(unwrap_impl(req)))
|
|
1848
1843
|
end
|
|
1849
1844
|
|
|
1845
|
+
# @nodoc
|
|
1846
|
+
def stop_css_coverage
|
|
1847
|
+
wrap_impl(@impl.stop_css_coverage)
|
|
1848
|
+
end
|
|
1849
|
+
|
|
1850
1850
|
# -- inherited from EventEmitter --
|
|
1851
1851
|
# @nodoc
|
|
1852
1852
|
def once(event, callback)
|
|
@@ -166,6 +166,18 @@ module Playwright
|
|
|
166
166
|
wrap_impl(@impl.response)
|
|
167
167
|
end
|
|
168
168
|
|
|
169
|
+
#
|
|
170
|
+
# The Service `Worker` that is performing the request.
|
|
171
|
+
#
|
|
172
|
+
# **Details**
|
|
173
|
+
#
|
|
174
|
+
# This method is Chromium only. It's safe to call when using other browsers, but it will always be `null`.
|
|
175
|
+
#
|
|
176
|
+
# Requests originated in a Service Worker do not have a [`method: Request.frame`] available.
|
|
177
|
+
def service_worker
|
|
178
|
+
raise NotImplementedError.new('service_worker is not implemented yet.')
|
|
179
|
+
end
|
|
180
|
+
|
|
169
181
|
#
|
|
170
182
|
# Returns resource size information for given request.
|
|
171
183
|
def sizes
|
data/lib/playwright_api/route.rb
CHANGED
|
@@ -36,7 +36,10 @@ module Playwright
|
|
|
36
36
|
#
|
|
37
37
|
# [`method: Route.continue`] will immediately send the request to the network, other matching handlers won't be invoked. Use [`method: Route.fallback`] If you want next matching handler in the chain to be invoked.
|
|
38
38
|
#
|
|
39
|
-
# **NOTE**:
|
|
39
|
+
# **NOTE**: Some request headers are **forbidden** and cannot be overridden (for example, `Cookie`, `Host`, `Content-Length` and others, see [this MDN page](https://developer.mozilla.org/en-US/docs/Glossary/Forbidden_request_header) for full list).
|
|
40
|
+
# If an override is provided for a forbidden header, it will be ignored and the original request header will be used.
|
|
41
|
+
#
|
|
42
|
+
# To set custom cookies, use [`method: BrowserContext.addCookies`].
|
|
40
43
|
def continue(headers: nil, method: nil, postData: nil, url: nil)
|
|
41
44
|
wrap_impl(@impl.continue(headers: unwrap_impl(headers), method: unwrap_impl(method), postData: unwrap_impl(postData), url: unwrap_impl(url)))
|
|
42
45
|
end
|
data/sig/playwright.rbs
CHANGED
|
@@ -237,7 +237,7 @@ module Playwright
|
|
|
237
237
|
def location: -> Hash[untyped, untyped]
|
|
238
238
|
def page: -> (nil | Page)
|
|
239
239
|
def text: -> String
|
|
240
|
-
def type: -> ("log" | "debug" | "info" | "error" | "warning" | "dir" | "dirxml" | "table" | "trace" | "clear" | "startGroup" | "startGroupCollapsed" | "endGroup" | "assert" | "profile" | "profileEnd" | "count" | "timeEnd")
|
|
240
|
+
def type: -> ("log" | "debug" | "info" | "error" | "warning" | "dir" | "dirxml" | "table" | "trace" | "clear" | "startGroup" | "startGroupCollapsed" | "endGroup" | "assert" | "profile" | "profileEnd" | "count" | "time" | "timeEnd")
|
|
241
241
|
def worker: -> (nil | Worker)
|
|
242
242
|
end
|
|
243
243
|
|
|
@@ -431,10 +431,10 @@ module Playwright
|
|
|
431
431
|
end
|
|
432
432
|
|
|
433
433
|
class BrowserType
|
|
434
|
-
def connect_over_cdp: (String endpointURL, ?headers: Hash[untyped, untyped], ?slowMo: Float, ?timeout: Float) ?{ (untyped) -> untyped } -> Browser
|
|
434
|
+
def connect_over_cdp: (String endpointURL, ?headers: Hash[untyped, untyped], ?isLocal: bool, ?slowMo: Float, ?timeout: Float) ?{ (untyped) -> untyped } -> Browser
|
|
435
435
|
def executable_path: -> String
|
|
436
|
-
def launch: (?args: Array[untyped], ?channel: String, ?chromiumSandbox: bool, ?
|
|
437
|
-
def launch_persistent_context: ((String | File) userDataDir, ?acceptDownloads: bool, ?args: Array[untyped], ?baseURL: String, ?bypassCSP: bool, ?channel: String, ?chromiumSandbox: bool, ?clientCertificates: Array[untyped], ?colorScheme: ("light" | "dark" | "no-preference" | "null"), ?contrast: ("no-preference" | "more" | "null"), ?deviceScaleFactor: Float, ?
|
|
436
|
+
def launch: (?args: Array[untyped], ?channel: String, ?chromiumSandbox: bool, ?downloadsPath: (String | File), ?env: Hash[untyped, untyped], ?executablePath: (String | File), ?firefoxUserPrefs: Hash[untyped, untyped], ?handleSIGHUP: bool, ?handleSIGINT: bool, ?handleSIGTERM: bool, ?headless: bool, ?ignoreDefaultArgs: (bool | Array[untyped]), ?proxy: Hash[untyped, untyped], ?slowMo: Float, ?timeout: Float, ?tracesDir: (String | File)) ?{ (Browser) -> untyped } -> Browser
|
|
437
|
+
def launch_persistent_context: ((String | File) userDataDir, ?acceptDownloads: bool, ?args: Array[untyped], ?baseURL: String, ?bypassCSP: bool, ?channel: String, ?chromiumSandbox: bool, ?clientCertificates: Array[untyped], ?colorScheme: ("light" | "dark" | "no-preference" | "null"), ?contrast: ("no-preference" | "more" | "null"), ?deviceScaleFactor: Float, ?downloadsPath: (String | File), ?env: Hash[untyped, untyped], ?executablePath: (String | File), ?extraHTTPHeaders: Hash[untyped, untyped], ?firefoxUserPrefs: Hash[untyped, untyped], ?forcedColors: ("active" | "none" | "null"), ?geolocation: Hash[untyped, untyped], ?handleSIGHUP: bool, ?handleSIGINT: bool, ?handleSIGTERM: bool, ?hasTouch: bool, ?headless: bool, ?httpCredentials: Hash[untyped, untyped], ?ignoreDefaultArgs: (bool | Array[untyped]), ?ignoreHTTPSErrors: bool, ?isMobile: bool, ?javaScriptEnabled: bool, ?locale: String, ?noViewport: bool, ?offline: bool, ?permissions: Array[untyped], ?proxy: Hash[untyped, untyped], ?record_har_content: ("omit" | "embed" | "attach"), ?record_har_mode: ("full" | "minimal"), ?record_har_omit_content: bool, ?record_har_path: (String | File), ?record_har_url_filter: (String | Regexp), ?record_video_dir: (String | File), ?record_video_size: Hash[untyped, untyped], ?reducedMotion: ("reduce" | "no-preference" | "null"), ?screen: Hash[untyped, untyped], ?serviceWorkers: ("allow" | "block"), ?slowMo: Float, ?strictSelectors: bool, ?timeout: Float, ?timezoneId: String, ?tracesDir: (String | File), ?userAgent: String, ?viewport: (nil | Hash[untyped, untyped])) ?{ (untyped) -> untyped } -> BrowserContext
|
|
438
438
|
def name: -> String
|
|
439
439
|
end
|
|
440
440
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: playwright-ruby-client
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.58.1.alpha1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- YusukeIwaki
|
|
@@ -226,6 +226,15 @@ extensions: []
|
|
|
226
226
|
extra_rdoc_files: []
|
|
227
227
|
files:
|
|
228
228
|
- ".rspec"
|
|
229
|
+
- AGENTS.md
|
|
230
|
+
- CLAUDE.md
|
|
231
|
+
- CLAUDE/api_generation.md
|
|
232
|
+
- CLAUDE/ci_expectations.md
|
|
233
|
+
- CLAUDE/gem_release_flow.md
|
|
234
|
+
- CLAUDE/past_upgrade_pr_patterns.md
|
|
235
|
+
- CLAUDE/playwright_upgrade_workflow.md
|
|
236
|
+
- CLAUDE/rspec_debugging.md
|
|
237
|
+
- CLAUDE/unimplemented_examples.md
|
|
229
238
|
- CODE_OF_CONDUCT.md
|
|
230
239
|
- CONTRIBUTING.md
|
|
231
240
|
- Gemfile
|
|
@@ -435,5 +444,5 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
435
444
|
requirements: []
|
|
436
445
|
rubygems_version: 3.6.9
|
|
437
446
|
specification_version: 4
|
|
438
|
-
summary: The Ruby binding of playwright driver 1.
|
|
447
|
+
summary: The Ruby binding of playwright driver 1.58.0
|
|
439
448
|
test_files: []
|