# `PlaywrightEx.Page`
[🔗](https://github.com/probably-not/playwright_ex/blob/v0.5.0-fork.2/lib/playwright_ex/channels/page.ex#L1)

Interact with a Playwright `Page`.

There is no official documentation, since this is considered Playwright internal.

Reference: https://github.com/microsoft/playwright/blob/main/packages/playwright-core/src/client/page.ts

# `add_init_script_opt`

```elixir
@type add_init_script_opt() ::
  {:connection, GenServer.name()} | {:timeout, timeout()} | {:source, binary()}
```

# `bring_to_front_opt`

```elixir
@type bring_to_front_opt() :: {:connection, GenServer.name()} | {:timeout, timeout()}
```

# `expect_url_opt`

```elixir
@type expect_url_opt() ::
  {:connection, GenServer.name()}
  | {:timeout, timeout()}
  | {:url, binary() | struct() | (term() -&gt; term())}
  | {:is_not, boolean()}
  | {:ignore_case, boolean()}
```

# `mouse_down_opt`

```elixir
@type mouse_down_opt() ::
  {:connection, GenServer.name()} | {:timeout, timeout()} | {:button, term()}
```

# `mouse_move_opt`

```elixir
@type mouse_move_opt() ::
  {:connection, GenServer.name()}
  | {:timeout, timeout()}
  | {:x, integer() | float()}
  | {:y, integer() | float()}
```

# `mouse_up_opt`

```elixir
@type mouse_up_opt() ::
  {:connection, GenServer.name()} | {:timeout, timeout()} | {:button, term()}
```

# `reload_opt`

```elixir
@type reload_opt() ::
  {:connection, GenServer.name()}
  | {:timeout, timeout()}
  | {:wait_until, term()}
```

# `screenshot_opt`

```elixir
@type screenshot_opt() ::
  {:connection, GenServer.name()}
  | {:timeout, timeout()}
  | {:full_page, boolean()}
  | {:omit_background, boolean()}
```

# `update_subscription_opt`

```elixir
@type update_subscription_opt() ::
  {:connection, GenServer.name()}
  | {:timeout, timeout()}
  | {:event, atom()}
  | {:enabled, boolean()}
```

# `add_init_script`

```elixir
@spec add_init_script(PlaywrightEx.guid(), [
  add_init_script_opt() | PlaywrightEx.unknown_opt()
]) ::
  {:ok, any()} | {:error, any()}
```

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`.

Reference: https://playwright.dev/docs/api/class-page#page-add-init-script

> ### Script Execution Order Is Not Defined {: .info}
>
> The order of evaluation of multiple scripts installed via
> `PlaywrightEx.BrowserContext.add_init_script/2` and
> `PlaywrightEx.Page.add_init_script/2` is not defined.

## Options
* `:connection` (`t:term/0`) - The Connection process name. Defaults to `PlaywrightEx.Supervisor.Connection`. The default value is `PlaywrightEx.Supervisor.Connection`.

* `:timeout` (`t:timeout/0`) - Required. Maximum time for the operation (milliseconds).

* `:source` (`t:String.t/0`) - Required. Raw JavaScript code to be evaluated in all pages before any scripts run.

# `bring_to_front`

```elixir
@spec bring_to_front(PlaywrightEx.guid(), [
  bring_to_front_opt() | PlaywrightEx.unknown_opt()
]) ::
  {:ok, any()} | {:error, any()}
```

Brings page to front (activates tab).

Reference: https://playwright.dev/docs/api/class-page#page-bring-to-front

## Options
* `:connection` (`t:term/0`) - The Connection process name. Defaults to `PlaywrightEx.Supervisor.Connection`. The default value is `PlaywrightEx.Supervisor.Connection`.

* `:timeout` (`t:timeout/0`) - Required. Maximum time for the operation (milliseconds).

# `mouse_down`

```elixir
@spec mouse_down(PlaywrightEx.guid(), [mouse_down_opt() | PlaywrightEx.unknown_opt()]) ::
  {:ok, any()} | {:error, any()}
```

Dispatches a `mousedown` event at the current mouse position.

Reference: https://playwright.dev/docs/api/class-mouse#mouse-down

## Example

    # Perform a manual drag operation
    {:ok, _} = Page.mouse_move(page_id, x: 100, y: 100, timeout: 5000)
    {:ok, _} = Page.mouse_down(page_id, timeout: 5000)
    {:ok, _} = Page.mouse_move(page_id, x: 200, y: 100, timeout: 5000)
    {:ok, _} = Page.mouse_up(page_id, timeout: 5000)

## Options
* `:connection` (`t:term/0`) - The Connection process name. Defaults to `PlaywrightEx.Supervisor.Connection`. The default value is `PlaywrightEx.Supervisor.Connection`.

* `:timeout` (`t:timeout/0`) - Required. Maximum time for the operation (milliseconds).

* `:button` - Defaults to `:left`. The default value is `:left`.

# `mouse_move`

```elixir
@spec mouse_move(PlaywrightEx.guid(), [mouse_move_opt() | PlaywrightEx.unknown_opt()]) ::
  {:ok, any()} | {:error, any()}
```

Moves the mouse to the specified coordinates.

This method dispatches a `mousemove` event. Supports fractional coordinates for precise positioning.

Reference: https://playwright.dev/docs/api/class-mouse#mouse-move

## Example

    # Get element position
    {:ok, result} = Frame.evaluate(frame_id,
      expression: "() => {
        const el = document.querySelector('.slider-handle');
        const box = el.getBoundingClientRect();
        return { x: box.x + box.width / 2, y: box.y + box.height / 2 };
      }",
      is_function: true,
      timeout: 5000
    )

    # Move to element
    {:ok, _} = Page.mouse_move(page_id, x: result["x"], y: result["y"], timeout: 5000)

## Options
* `:connection` (`t:term/0`) - The Connection process name. Defaults to `PlaywrightEx.Supervisor.Connection`. The default value is `PlaywrightEx.Supervisor.Connection`.

* `:timeout` (`t:timeout/0`) - Required. Maximum time for the operation (milliseconds).

* `:x` - Required. `x` coordinate relative to the main frame's viewport in CSS pixels.

* `:y` - Required. `y` coordinate relative to the main frame's viewport in CSS pixels.

# `mouse_up`

```elixir
@spec mouse_up(PlaywrightEx.guid(), [mouse_up_opt() | PlaywrightEx.unknown_opt()]) ::
  {:ok, any()} | {:error, any()}
```

Dispatches a `mouseup` event at the current mouse position.

Reference: https://playwright.dev/docs/api/class-mouse#mouse-up

## Example

    # Right-click at current position
    {:ok, _} = Page.mouse_down(page_id, button: :right, timeout: 5000)
    {:ok, _} = Page.mouse_up(page_id, button: :right, timeout: 5000)

## Options
* `:connection` (`t:term/0`) - The Connection process name. Defaults to `PlaywrightEx.Supervisor.Connection`. The default value is `PlaywrightEx.Supervisor.Connection`.

* `:timeout` (`t:timeout/0`) - Required. Maximum time for the operation (milliseconds).

* `:button` - Defaults to `:left`. The default value is `:left`.

# `reload`

```elixir
@spec reload(PlaywrightEx.guid(), [reload_opt() | PlaywrightEx.unknown_opt()]) ::
  {:ok, any()} | {:error, any()}
```

Reloads the page.

Reference: https://playwright.dev/docs/api/class-page#page-reload

## Options
* `:connection` (`t:term/0`) - The Connection process name. Defaults to `PlaywrightEx.Supervisor.Connection`. The default value is `PlaywrightEx.Supervisor.Connection`.

* `:timeout` (`t:timeout/0`) - Required. Maximum time for the operation (milliseconds).

* `:wait_until` - When to consider operation succeeded, defaults to `load`.

# `screenshot`

```elixir
@spec screenshot(PlaywrightEx.guid(), [screenshot_opt() | PlaywrightEx.unknown_opt()]) ::
  {:ok, binary()} | {:error, any()}
```

Returns a screenshot of the page as binary data.

Reference: https://playwright.dev/docs/api/class-page#page-screenshot

## Options
* `:connection` (`t:term/0`) - The Connection process name. Defaults to `PlaywrightEx.Supervisor.Connection`. The default value is `PlaywrightEx.Supervisor.Connection`.

* `:timeout` (`t:timeout/0`) - Required. Maximum time for the operation (milliseconds).

* `:full_page` (`t:boolean/0`) - When true, takes a screenshot of the full scrollable page, instead of the currently visible viewport. Defaults to `false`.

* `:omit_background` (`t:boolean/0`) - Hides default white background and allows capturing screenshots with transparency. Defaults to `false`. Not applicable to jpeg images.

# `update_subscription`

```elixir
@spec update_subscription(PlaywrightEx.guid(), [
  update_subscription_opt() | PlaywrightEx.unknown_opt()
]) ::
  {:ok, any()} | {:error, any()}
```

Updates the subscription for page events.

Reference: https://github.com/microsoft/playwright/blob/main/packages/playwright-core/src/client/page.ts

## Options
* `:connection` (`t:term/0`) - The Connection process name. Defaults to `PlaywrightEx.Supervisor.Connection`. The default value is `PlaywrightEx.Supervisor.Connection`.

* `:timeout` (`t:timeout/0`) - Required. Maximum time for the operation (milliseconds).

* `:event` (`t:atom/0`) - Required.

* `:enabled` (`t:boolean/0`) - The default value is `true`.

# `expect_url`

```elixir
@spec expect_url(PlaywrightEx.guid(), [expect_url_opt() | PlaywrightEx.unknown_opt()]) ::
  {:ok, boolean()} | {:error, any()}
```

Expects page URL to match the provided expectation.

This library exposes URL assertions as `Page.expect_url/2`.

In the official Playwright JavaScript API, URL assertions are written as
`await expect(page).toHaveURL(...)`. That matcher API is not exposed here.

Matching strategy:
- String/`Regex`: delegates to `PlaywrightEx.Frame.expect/2` with expression `"to.have.url"`, which uses server-side
  assertion polling (`is_not` is passed through for retry semantics).
- Predicate function: delegates to `PlaywrightEx.Frame.wait_for_url/2`, which is navigation-event based
  (waits on `:navigated` + lifecycle events rather than polling page JavaScript).

Returns `true` when the expectation is satisfied and `false` otherwise.

Reference: https://playwright.dev/docs/api/class-pageassertions#page-assertions-to-have-url

## Options
* `:connection` (`t:term/0`) - The Connection process name. Defaults to `PlaywrightEx.Supervisor.Connection`. The default value is `PlaywrightEx.Supervisor.Connection`.

* `:timeout` (`t:timeout/0`) - Required. Maximum time for the operation (milliseconds).

* `:url` - Required. Expected URL as a string, `Regex`, or predicate function `fn URI.t() -> boolean end`.

* `:is_not` (`t:boolean/0`) - Whether to negate the expectation. The default value is `false`.

* `:ignore_case` (`t:boolean/0`) - Whether URL comparison should ignore case. The default value is `false`.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
