Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Visible radio button cannot be clicked ("element is outside of the viewport") #3688

Closed
ghost opened this issue Aug 29, 2020 · 5 comments
Closed

Comments

@ghost
Copy link

ghost commented Aug 29, 2020

Context:

  • Playwright Version: 1.3.0
  • Operating System: MacOS Catalina
  • Node.js version: 14.7.0
  • Browser: Chromium

Code Snippet

The objective is to click/select the radio button with the label "JA" via its ID "existing-customer-input-0":

const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch({headless: false}, {slowMo: 50});
  // ...
  await page.click('#existing-customer-input-0');
})();

Describe the bug

The problematic section of the tested web page consists of a radio button group with two buttons:
image
The corresponding HTML source code:

<div class="c-button-group">
  <label class="c-button-group__item" for="existing-customer-input-0">
    <input class="c-button-group__input" type="radio" id="existing-customer-input-0" name="existingCustomer" 
    value="yes">
    <span class="c-button-group__label">ja</span>
  </label>
  <label class="c-button-group__item" for="existing-customer-input-1">
    <input class="c-button-group__input" type="radio" id="existing-customer-input-1" name="existingCustomer" 
    value="no">
    <span class="c-button-group__label">nein</span>
  </label>
</div>

Expected behavior:
Button "JA" is found and clicked/selected.

Actual behavior:
Playwright can't successfully select the element referenced by the above ID and throws the following error message:

TimeoutError: page.click: Timeout 30000ms exceeded.
=========================== logs ===========================
[api] waiting for selector "#existing-customer-input-0"
[api] selector resolved to visible <input value="yes" type="radio" name="existingCustomer"…/>
[api] attempting click action
[api] waiting for element to be visible, enabled and not moving
[api] element is visible, enabled and does not move
[api] scrolling into view if needed
[api] done scrolling
[api] element is outside of the viewport
[api] retrying click action
[...]
It keeps retrying with the same messages as above until the timeout kicks in.

Regarding "element is outside of the viewport": Not sure what this exactly implies but the element with the ID "existing-customer-input-0" is clearly visible and not overshadowed/hidden during a headful test.

@ghost ghost changed the title [BUG] [BUG] Visible radio button cannot be clicked ("element is outside of the viewport") Aug 29, 2020
@arjunattam
Copy link
Contributor

Thanks @KLctrl. Is this a public website? It's hard to tell for sure without looking at the css of the html.

Looking at the screenshot, my guess is that the radio button circle is hidden with css and playwright is waiting for the circle to be visible. Couple of alternatives you could try:

  1. Force the click to bypass these checks page.click('#existing-customer-input-0', { force: true} ) (this might have other side-effects)
  2. Click the parent element with page.click('[for=existing-customer-input-0]')

If you can share a link to the page or a repro case with css, we could find a better solution.

@ghost
Copy link
Author

ghost commented Aug 30, 2020

Thanks for your feedback, @arjun27.

I have sent the URL to you directly.

Re 1.: This still leads to the same error, however this time there is no automatic retry.

Error: page.click: Element is outside of the viewport
=========================== logs ===========================
[api] waiting for selector "#existing-customer-input-0"
[api] selector resolved to visible <input value="yes" type="radio" name="existingCustomer"…/>
[api] attempting click action
[api] scrolling into view if needed
[api] done scrolling
============================================================
Note: use DEBUG=pw:api environment variable and rerun to capture Playwright logs.
at ElementHandle._retryPointerAction (node_modules/playwright/lib/dom.js:252:27)
at /[...]/node_modules/playwright/lib/frames.js:674:32
at ProgressController.run (node_modules/playwright/lib/progress.js:75:28)
at Frame.click (node_modules/playwright/lib/frames.js:686:9)
-- ASYNC --
at Frame.click (node_modules/playwright/lib/helper.js:79:23)
at /[...]/node_modules/playwright/lib/page.js:377:61
at Page._attributeToPage (node_modules/playwright/lib/page.js:370:20)
at Page.click (node_modules/playwright/lib/page.js:377:21)
at Page.click (node_modules/playwright/lib/helper.js:80:31)
at /[...]/test/e2e-dcc.ts:56:24
at step (test/e2e-dcc.ts:33:23)
at Object.next (test/e2e-dcc.ts:14:53)
at /[...]/test/e2e-dcc.ts:8:71
at new Promise ()
at __awaiter (test/e2e-dcc.ts:4:12)
at Context. (test/e2e-dcc.ts:55:47)
at processImmediate (internal/timers.js:458:21)

Re 2.: This works.

Interestingly, it also works when using the following text-based selector:

await page.click('text="ja"');

Normally, I always try to use text-based selectors to avoid having to use details from a page's source code (also, strictly speaking, for this text-based selector I had to look at the source code because using "JA" (capital letters, as it gets displayed on the page) won't lead to the button getting selected but also won't produce an error), but in this case the text-based selector is not ideal because there's another button with the same text further below on the page. Therefore, I want to ensure that definitely the right button gets clicked at this point.

@arjunattam
Copy link
Contributor

Thanks for sharing the link on email. I noticed that the radio button has the following styles and is therefore not located on the page.

left: -9999px;
position: absolute;

I understand how using the text-based selector feels unreliable because of the other element on the page. Do you think we could combine the text selector with another text selector localize the search (text=Parent >> text=Child) into a part of the page? It might also be worth to get your thoughts on #2370

@arjunattam
Copy link
Contributor

I'll close the issue for now since this isn't a bug. We can continue the discussion to find an ideal selector to choose.

@ghost
Copy link
Author

ghost commented Sep 1, 2020

Combining several text selectors to localize the search is a nice suggestion that I wasn't aware of. However, in this particular case and since that kind of text selector combination does indeed only work in case of parent >> child scenarios, I haven't found a way to localize it given the following html code:

<fieldset class="o-fieldset u-mb-large">
<div class="o-fieldset__row">
<div class=" o-layout">
<div class="o-layout__item u-1/1">
<label><span>Wir sind gesetzlich dazu verpflichtet, Ihre Identität zu überprüfen. Die Legitimation können Sie direkt nach dem Abschluss bequem online durchführen. Falls Sie in den letzten drei Jahren Kunde waren, ist keine Legitimation erforderlich.&nbsp;*</span></label>
<div class="c-button-group">
<label class="c-button-group__item" for="existing-customer-input-0">
<input class="c-button-group__input" type="radio" id="existing-customer-input-0" name="existingCustomer" value="yes">
<span class="c-button-group__label">ja</span></label>
<label class="c-button-group__item" for="existing-customer-input-1">
<input class="c-button-group__input" type="radio" id="existing-customer-input-1" name="existingCustomer" value="no" checked="">
<span class="c-button-group__label">nein</span></label>
</div></div></div></div>
</fieldset>

If there were another operator than >> that would not only look at the parent's child but also check the same level in the tree as the parent is in (my wording may be wrong, I'm not deep into HTML, DOM, etc.) -- or maybe an option to that operator -- then something like this could have worked (which I actually tried out in the hope that the string after the operator doesn't necessarily have to be a child node):
await page.click('text=Wir sind gesetzlich dazu verpflichtet >> text="ja"');

Such a feature would IMHO touch the broader issue of proximity/relative selectors (see #2877 and #3667). That, in my view, would be the ultimate goal: having the option to write your tests w/o having to look at the HTML source code and even w/o having to know much about HTML, CSS, etc.

#2370 sounds like an interesting enhancement but for my usual use cases I prefer using simple APIs that can be easily understood after a short look at them, which makes both the creation and the maintenance of test code easier and keeps efforts low. That's why I like text-based selectors.

@ghost ghost changed the title [BUG] Visible radio button cannot be clicked ("element is outside of the viewport") Visible radio button cannot be clicked ("element is outside of the viewport") Sep 3, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant