playwright-ruby-client 1.14.beta3 → 1.14.0
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/documentation/docs/api/element_handle.md +3 -4
- data/documentation/docs/api/locator.md +25 -38
- data/documentation/docs/api/worker.md +12 -11
- data/documentation/docs/article/guides/inspector.md +1 -1
- data/documentation/docs/article/guides/playwright_on_alpine_linux.md +1 -1
- data/documentation/docs/article/guides/semi_automation.md +1 -1
- data/documentation/docs/article/guides/use_storage_state.md +78 -0
- data/lib/playwright/version.rb +1 -1
- metadata +5 -4
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: d6f164b2d4296ab3f30bfb22cd5fbec86ab522df916913ab19731dd452c55efa
         | 
| 4 | 
            +
              data.tar.gz: 56371e88f29c8a7e7e398582a7cda693f45d8ebbb5bf6ce6e3fa0e748a2175bc
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: d97fd45d76a1cf4202be4aae7527974b01d8f90fd1de5e4fb4ed1267d3d3eeb601d5dddc49eb70559688c6bc816df82bc8c667e6aec7d2226ce078a2e0182a25
         | 
| 7 | 
            +
              data.tar.gz: 602c97a88eb16aab95590391ae26f7ba777904668d4e270e3e24fe05122606d3f23d68901e529bb28b23a91458cdf7ce165de0c87621e0ad4ef9f8a711ccaf5f
         | 
| @@ -641,12 +641,11 @@ become visible/hidden). If at the moment of calling the method `selector` alread | |
| 641 641 | 
             
            will return immediately. If the selector doesn't satisfy the condition for the `timeout` milliseconds, the function will
         | 
| 642 642 | 
             
            throw.
         | 
| 643 643 |  | 
| 644 | 
            -
            ``` | 
| 645 | 
            -
            page. | 
| 644 | 
            +
            ```ruby
         | 
| 645 | 
            +
            page.content = "<div><span></span></div>"
         | 
| 646 646 | 
             
            div = page.query_selector("div")
         | 
| 647 647 | 
             
            # waiting for the "span" selector relative to the div.
         | 
| 648 | 
            -
            span = div.wait_for_selector("span", state | 
| 649 | 
            -
             | 
| 648 | 
            +
            span = div.wait_for_selector("span", state: "attached")
         | 
| 650 649 | 
             
            ```
         | 
| 651 650 |  | 
| 652 651 | 
             
            > NOTE: This method does not work across navigations, use [Page#wait_for_selector](./page#wait_for_selector) instead.
         | 
| @@ -7,10 +7,9 @@ sidebar_position: 10 | |
| 7 7 | 
             
            Locator represents a view to the element(s) on the page. It captures the logic sufficient to retrieve the element at any
         | 
| 8 8 | 
             
            given moment. Locator can be created with the [Page#locator](./page#locator) method.
         | 
| 9 9 |  | 
| 10 | 
            -
            ``` | 
| 10 | 
            +
            ```ruby
         | 
| 11 11 | 
             
            locator = page.locator("text=Submit")
         | 
| 12 | 
            -
            locator.click | 
| 13 | 
            -
             | 
| 12 | 
            +
            locator.click
         | 
| 14 13 | 
             
            ```
         | 
| 15 14 |  | 
| 16 15 | 
             
            The difference between the Locator and [ElementHandle](./element_handle) is that the latter points to a particular element, while Locator
         | 
| @@ -72,10 +71,12 @@ Elements from child frames return the bounding box relative to the main frame, u | |
| 72 71 | 
             
            Assuming the page is static, it is safe to use bounding box coordinates to perform input. For example, the following
         | 
| 73 72 | 
             
            snippet should click the center of the element.
         | 
| 74 73 |  | 
| 75 | 
            -
            ``` | 
| 76 | 
            -
            box = element.bounding_box | 
| 77 | 
            -
            page.mouse.click( | 
| 78 | 
            -
             | 
| 74 | 
            +
            ```ruby
         | 
| 75 | 
            +
            box = element.bounding_box
         | 
| 76 | 
            +
            page.mouse.click(
         | 
| 77 | 
            +
              box["x"] + box["width"] / 2,
         | 
| 78 | 
            +
              box["y"] + box["height"] / 2,
         | 
| 79 | 
            +
            )
         | 
| 79 80 | 
             
            ```
         | 
| 80 81 |  | 
| 81 82 |  | 
| @@ -177,9 +178,8 @@ The snippet below dispatches the `click` event on the element. Regardless of the | |
| 177 178 | 
             
            `click` is dispatched. This is equivalent to calling
         | 
| 178 179 | 
             
            [element.click()](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/click).
         | 
| 179 180 |  | 
| 180 | 
            -
            ``` | 
| 181 | 
            +
            ```ruby
         | 
| 181 182 | 
             
            element.dispatch_event("click")
         | 
| 182 | 
            -
             | 
| 183 183 | 
             
            ```
         | 
| 184 184 |  | 
| 185 185 | 
             
            Under the hood, it creates an instance of an event based on the given `type`, initializes it with `eventInit` properties
         | 
| @@ -196,11 +196,10 @@ Since `eventInit` is event-specific, please refer to the events documentation fo | |
| 196 196 |  | 
| 197 197 | 
             
            You can also specify [JSHandle](./js_handle) as the property value if you want live objects to be passed into the event:
         | 
| 198 198 |  | 
| 199 | 
            -
            ``` | 
| 199 | 
            +
            ```ruby
         | 
| 200 200 | 
             
            # note you can only create data_transfer in chromium and firefox
         | 
| 201 201 | 
             
            data_transfer = page.evaluate_handle("new DataTransfer()")
         | 
| 202 | 
            -
            element.dispatch_event(" | 
| 203 | 
            -
             | 
| 202 | 
            +
            element.dispatch_event("dragstart", eventInit: { dataTransfer: data_transfer })
         | 
| 204 203 | 
             
            ```
         | 
| 205 204 |  | 
| 206 205 |  | 
| @@ -236,10 +235,9 @@ If `expression` returns a [Promise](https://developer.mozilla.org/en-US/docs/Web | |
| 236 235 |  | 
| 237 236 | 
             
            Examples:
         | 
| 238 237 |  | 
| 239 | 
            -
            ``` | 
| 240 | 
            -
             | 
| 241 | 
            -
             | 
| 242 | 
            -
             | 
| 238 | 
            +
            ```ruby
         | 
| 239 | 
            +
            tweet = page.query_selector(".tweet .retweets")
         | 
| 240 | 
            +
            tweet.evaluate("node => node.innerText") # => "10 retweets"
         | 
| 243 241 | 
             
            ```
         | 
| 244 242 |  | 
| 245 243 |  | 
| @@ -258,10 +256,9 @@ return its value. | |
| 258 256 |  | 
| 259 257 | 
             
            Examples:
         | 
| 260 258 |  | 
| 261 | 
            -
            ``` | 
| 259 | 
            +
            ```ruby
         | 
| 262 260 | 
             
            elements = page.locator("div")
         | 
| 263 | 
            -
             | 
| 264 | 
            -
             | 
| 261 | 
            +
            elements.evaluate_all("(divs, min) => divs.length >= min", arg: 10)
         | 
| 265 262 | 
             
            ```
         | 
| 266 263 |  | 
| 267 264 |  | 
| @@ -518,26 +515,18 @@ Returns the array of option values that have been successfully selected. | |
| 518 515 |  | 
| 519 516 | 
             
            Triggers a `change` and `input` event once all the provided options have been selected.
         | 
| 520 517 |  | 
| 521 | 
            -
            ``` | 
| 518 | 
            +
            ```ruby
         | 
| 522 519 | 
             
            # single selection matching the value
         | 
| 523 | 
            -
            element.select_option("blue")
         | 
| 520 | 
            +
            element.select_option(value: "blue")
         | 
| 524 521 | 
             
            # single selection matching both the label
         | 
| 525 | 
            -
            element.select_option(label | 
| 522 | 
            +
            element.select_option(label: "blue")
         | 
| 526 523 | 
             
            # multiple selection
         | 
| 527 | 
            -
            element.select_option(value | 
| 528 | 
            -
             | 
| 524 | 
            +
            element.select_option(value: ["red", "green", "blue"])
         | 
| 529 525 | 
             
            ```
         | 
| 530 526 |  | 
| 531 | 
            -
            ``` | 
| 532 | 
            -
            # single selection matching the value
         | 
| 533 | 
            -
            element.select_option("blue")
         | 
| 534 | 
            -
            # single selection matching both the value and the label
         | 
| 535 | 
            -
            element.select_option(label="blue")
         | 
| 536 | 
            -
            # multiple selection
         | 
| 537 | 
            -
            element.select_option("red", "green", "blue")
         | 
| 527 | 
            +
            ```ruby
         | 
| 538 528 | 
             
            # multiple selection for blue, red and second option
         | 
| 539 | 
            -
            element.select_option(value | 
| 540 | 
            -
             | 
| 529 | 
            +
            element.select_option(value: "blue", index: 2, label: "red")
         | 
| 541 530 | 
             
            ```
         | 
| 542 531 |  | 
| 543 532 |  | 
| @@ -607,19 +596,17 @@ Focuses the element, and then sends a `keydown`, `keypress`/`input`, and `keyup` | |
| 607 596 |  | 
| 608 597 | 
             
            To press a special key, like `Control` or `ArrowDown`, use [Locator#press](./locator#press).
         | 
| 609 598 |  | 
| 610 | 
            -
            ``` | 
| 599 | 
            +
            ```ruby
         | 
| 611 600 | 
             
            element.type("hello") # types instantly
         | 
| 612 | 
            -
            element.type("world", delay | 
| 613 | 
            -
             | 
| 601 | 
            +
            element.type("world", delay: 100) # types slower, like a user
         | 
| 614 602 | 
             
            ```
         | 
| 615 603 |  | 
| 616 604 | 
             
            An example of typing into a text field and then submitting the form:
         | 
| 617 605 |  | 
| 618 | 
            -
            ``` | 
| 606 | 
            +
            ```ruby
         | 
| 619 607 | 
             
            element = page.locator("input")
         | 
| 620 608 | 
             
            element.type("some text")
         | 
| 621 609 | 
             
            element.press("Enter")
         | 
| 622 | 
            -
             | 
| 623 610 | 
             
            ```
         | 
| 624 611 |  | 
| 625 612 |  | 
| @@ -8,17 +8,18 @@ The Worker class represents a [WebWorker](https://developer.mozilla.org/en-US/do | |
| 8 8 | 
             
            event is emitted on the page object to signal a worker creation. `close` event is emitted on the worker object when the
         | 
| 9 9 | 
             
            worker is gone.
         | 
| 10 10 |  | 
| 11 | 
            -
            ``` | 
| 12 | 
            -
            def handle_worker(worker) | 
| 13 | 
            -
             | 
| 14 | 
            -
             | 
| 15 | 
            -
             | 
| 16 | 
            -
             | 
| 17 | 
            -
             | 
| 18 | 
            -
             | 
| 19 | 
            -
             | 
| 20 | 
            -
             | 
| 21 | 
            -
             | 
| 11 | 
            +
            ```ruby
         | 
| 12 | 
            +
            def handle_worker(worker)
         | 
| 13 | 
            +
              puts "worker created: #{worker.url}"
         | 
| 14 | 
            +
              worker.once("close", -> (w) { puts "worker destroyed: #{w.url}" })
         | 
| 15 | 
            +
            end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            page.on('worker', method(:handle_worker))
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            puts "current workers:"
         | 
| 20 | 
            +
            page.workers.each do |worker|
         | 
| 21 | 
            +
              puts "    #{worker.url}"
         | 
| 22 | 
            +
            end
         | 
| 22 23 | 
             
            ```
         | 
| 23 24 |  | 
| 24 25 |  | 
| @@ -10,7 +10,7 @@ This allow us to intermediate into automation, for example | |
| 10 10 | 
             
            * Authenticate with OAuth2 manually before automation
         | 
| 11 11 | 
             
            * Testing a page after some chrome extensions are installed manually
         | 
| 12 12 |  | 
| 13 | 
            -
            Keep in mind repeatedly that persistent browser context is NOT RECOMMENDED for most cases because it would bring many side effects.
         | 
| 13 | 
            +
            Keep in mind repeatedly that persistent browser context is NOT RECOMMENDED for most cases because it would bring many side effects. Consider [reusing cookie and local storage](./use_storage_state) when you just want to keep authenticated across browser contexts.
         | 
| 14 14 |  | 
| 15 15 | 
             
            ## Pause automation for manual operation
         | 
| 16 16 |  | 
| @@ -0,0 +1,78 @@ | |
| 1 | 
            +
            ---
         | 
| 2 | 
            +
            sidebar_position: 6
         | 
| 3 | 
            +
            ---
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            # Reuse Cookie and LocalStorage
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            In most cases, authentication state is stored in cookie or local storage. When we just want to keep authenticated, it is a good solution to dump/load 'storage state' (= Cookie + LocalStorage).
         | 
| 8 | 
            +
            https://playwright.dev/docs/next/auth#reuse-authentication-state
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            * Dump storage state using [BrowserContext#storage_state](/docs/api/browser_context#storage_state) with `path: /path/to/state.json`
         | 
| 11 | 
            +
            * Load storage state by specifying the parameter `storageState: /path/to/state.json` into [Browser#new_context](/docs/api/browser#new_context) or [Browser#new_page](/docs/api/browser#new_page)
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            ## Example
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            Generally in browser automation, it is very difficult to bypass 2FA or reCAPTCHA in login screen. In such cases, we would consider
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            * Authenticate manually by hand
         | 
| 18 | 
            +
            * Resume automation with the authentication result
         | 
| 19 | 
            +
             | 
| 20 | 
            +
             | 
| 21 | 
            +
            ```ruby {16,21}
         | 
| 22 | 
            +
            require 'playwright'
         | 
| 23 | 
            +
            require 'pry'
         | 
| 24 | 
            +
             | 
| 25 | 
            +
            force_login = !File.exist?('github_state.json')
         | 
| 26 | 
            +
             | 
| 27 | 
            +
            Playwright.create(playwright_cli_executable_path: 'npx playwright') do |playwright|
         | 
| 28 | 
            +
              if force_login
         | 
| 29 | 
            +
                # Use headful mode for manual operation.
         | 
| 30 | 
            +
                playwright.chromium.launch(headless: false, channel: 'chrome') do |browser|
         | 
| 31 | 
            +
                  page = browser.new_page
         | 
| 32 | 
            +
                  page.goto('https://github.com/login')
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                  # Login manually.
         | 
| 35 | 
            +
                  binding.pry
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                  page.context.storage_state(path: 'github_state.json')
         | 
| 38 | 
            +
                end
         | 
| 39 | 
            +
              end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
              playwright.chromium.launch do |browser|
         | 
| 42 | 
            +
                page = browser.new_page(storageState: 'github_state.json')
         | 
| 43 | 
            +
                page.goto('https://github.com/notifications')
         | 
| 44 | 
            +
                page.screenshot(path: 'github_notification.png')
         | 
| 45 | 
            +
              end
         | 
| 46 | 
            +
            end
         | 
| 47 | 
            +
            ```
         | 
| 48 | 
            +
             | 
| 49 | 
            +
            When we execute this script at the first time (without github_state.json), login screen is shown:
         | 
| 50 | 
            +
             | 
| 51 | 
            +
            
         | 
| 52 | 
            +
             | 
| 53 | 
            +
            and input credentials manually:
         | 
| 54 | 
            +
             | 
| 55 | 
            +
            
         | 
| 56 | 
            +
             | 
| 57 | 
            +
            and hit `exit` in Pry console.
         | 
| 58 | 
            +
             | 
| 59 | 
            +
            ```
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                 9:
         | 
| 62 | 
            +
                10:     # Login manually. Hit `exit` in Pry console after authenticated.
         | 
| 63 | 
            +
                11:     require 'pry'
         | 
| 64 | 
            +
                12:     binding.pry
         | 
| 65 | 
            +
                13:
         | 
| 66 | 
            +
             => 14:     page.context.storage_state(path: 'github_state.json')
         | 
| 67 | 
            +
                15:   end if force_login
         | 
| 68 | 
            +
                16:
         | 
| 69 | 
            +
                17:   playwright.chromium.launch do |browser|
         | 
| 70 | 
            +
                18:     page = browser.new_page(storageState: 'github_state.json')
         | 
| 71 | 
            +
                19:     page.goto('https://github.com/notifications')
         | 
| 72 | 
            +
             | 
| 73 | 
            +
            [1] pry(main)> exit
         | 
| 74 | 
            +
            ```
         | 
| 75 | 
            +
             | 
| 76 | 
            +
            then we can enjoy automation with keeping authenticated. Login screen is never shown until github_state.json is deleted :)
         | 
| 77 | 
            +
             | 
| 78 | 
            +
            
         | 
    
        data/lib/playwright/version.rb
    CHANGED
    
    
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: playwright-ruby-client
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 1.14. | 
| 4 | 
            +
              version: 1.14.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - YusukeIwaki
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: exe
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2021-08- | 
| 11 | 
            +
            date: 2021-08-14 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: concurrent-ruby
         | 
| @@ -250,6 +250,7 @@ files: | |
| 250 250 | 
             
            - documentation/docs/article/guides/rails_integration.md
         | 
| 251 251 | 
             
            - documentation/docs/article/guides/recording_video.md
         | 
| 252 252 | 
             
            - documentation/docs/article/guides/semi_automation.md
         | 
| 253 | 
            +
            - documentation/docs/article/guides/use_storage_state.md
         | 
| 253 254 | 
             
            - documentation/docs/include/api_coverage.md
         | 
| 254 255 | 
             
            - documentation/docusaurus.config.js
         | 
| 255 256 | 
             
            - documentation/package.json
         | 
| @@ -371,9 +372,9 @@ required_ruby_version: !ruby/object:Gem::Requirement | |
| 371 372 | 
             
                  version: '2.4'
         | 
| 372 373 | 
             
            required_rubygems_version: !ruby/object:Gem::Requirement
         | 
| 373 374 | 
             
              requirements:
         | 
| 374 | 
            -
              - - " | 
| 375 | 
            +
              - - ">="
         | 
| 375 376 | 
             
                - !ruby/object:Gem::Version
         | 
| 376 | 
            -
                  version:  | 
| 377 | 
            +
                  version: '0'
         | 
| 377 378 | 
             
            requirements: []
         | 
| 378 379 | 
             
            rubygems_version: 3.2.22
         | 
| 379 380 | 
             
            signing_key: 
         |