MarketSquare / MarketSquare/robotframework-browser

Add `Get Viewport Intersection Ratio` keyword to assert element visibility in the viewport

Open
#5,124 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement
Dominant language
Python
Stars
655
Forks
147
Avg merge
5h 27m
Merged PRs (30d)
59

Description

## Use case

"Is this element actually visible in the viewport right now?" is a common check for lazy-loading images, sticky headers, infinite scrolling, cookie banners and scroll-into-view behavior. The library's element state keywords answer *attached/visible* in the CSS sense, but not whether the element is inside the current viewport, and certainly not *how much* of it is.

Playwright covers this with `toBeInViewport({ ratio })`, backed by `IntersectionObserver`. Browser library has no equivalent: users today must hand-roll an `Evaluate JavaScript` snippet with an `IntersectionObserver`, a Promise and manual polling — boilerplate that is easy to get wrong and gets copy-pasted between suites.

A float getter fits the assertion-engine model perfectly and is strictly more expressive than a boolean keyword: `> 0` reproduces `toBeInViewport`, `== 0` reproduces `not.toBeInViewport`, and `>= 0.5` covers the ratio option that a boolean never could.

## Proposed keyword / arguments

```
Get Viewport Intersection Ratio selector assertion_operator=None assertion_expected=None message=None
```

| Argument | Description |
|---|---|
| `selector` | Element selector, strict mode applies. |
| `assertion_operator` / `assertion_expected` / `message` | Standard assertion-engine arguments with auto-retry; numeric operators (`==`, `>`, `>=`, `<`, `<=`) apply. |

Returns a float between `0.0` (fully outside the viewport) and `1.0` (fully inside), the `IntersectionObserver` intersection ratio of the element versus the viewport.

```robotframework
*** Test Cases ***
Hero Is Visible After Load
New Page ${URL}
Get Viewport Intersection Ratio id=hero > 0

Call To Action Is At Least Half Visible
Scroll To Element id=cta
Get Viewport Intersection Ratio id=cta >= 0.5

Footer Is Not In Viewport Initially
Get Viewport Intersection Ratio css=footer == 0
${ratio} = Get Viewport Intersection Ratio id=banner
```

With `Set Retry Assertions For`, the assertion auto-retries — e.g. waiting until a lazily loaded element scrolls into view.

## Playwright API

- [expect(locator).toBeInViewport](https://playwright.dev/docs/api/class-locatorassertions#locator-assertions-to-be-in-viewport) (including its `ratio` option)

The wrapper computes the same `IntersectionObserver`-based ratio Playwright's assertion uses.

## Implementation notes

- `protobuf/playwright.proto`: new selector-in / float-out RPC (or reuse an existing generic element-request shape).
- `node/playwright-wrapper`: resolve the locator and evaluate the intersection ratio via Playwright's injected utilities (same mechanism as `toBeInViewport`).
- `Browser/keywords/getters.py`: new keyword with `@with_assertion_polling` and `float_str_verify_assertion`-style numeric assertion, tags `Getter, Assertion, PageContent`.
- Docs + `inv build` stub regen, atest with a long scrollable page (element out of view, partially in view, fully in view).

## Backwards compatibility

Purely additive: a new keyword, no changes to any existing keyword.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with protobuf/playwright.proto, the node/playwright-wrapper, and Browser/keywords/getters.py to trace existing element requests, browser evaluation, assertion polling, and numeric verification. Then inspect related documentation, generated stubs, and atest patterns. Done means the new keyword returns the IntersectionObserver ratio, supports the listed assertions and retry behavior, and has coverage for out-of-view, partially visible, and fully visible elements.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
testing
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.