<p dir="auto"><strong>Context:</strong></p>
<ul dir="auto">
<li>Playwright Version: 1.14.1</li>
<li>Operating System: Windows</li>
<li>Node.js version: 16.1</li>
<li>Browser: Chromium</li>
<li>Extra: Using Browser Library of Robot Framework. <a href="https://marketsquare.github.io/robotframework-browser/Browser.html" rel="nofollow">https://marketsquare.github.io/robotframework-browser/Browser.html</a></li>
</ul>
<p dir="auto"><strong>Describe the bug</strong></p>
<p dir="auto">I am using Robot Framework library called Browser Library which uses Playwright under the hood. It uses same selector strategy so I would imagine this bug is related to Playwright as the selector should be passed on to Playwright to find the element.</p>
<p dir="auto">I have a form with a button that I am trying to locate and click. I would like to use the role attribute to find the element.</p>
<p dir="auto">W3 standards say that the roles for this html should be implicit; however, Playwright is not finding the elements. My assumption is that Playwright only finds the role if it is explicitly provided.</p>
<p dir="auto">The first selector strategy works.<br>
<code class="notranslate">css=#root &gt;&gt; css=form &gt;&gt; css=button</code></p>
<p dir="auto">The second selector strategy does not work.<br>
<code class="notranslate">css=#root &gt;&gt; css=[role=form] &gt;&gt; css=[role=button]</code></p>
<p dir="auto">Example HTML</p>
<div class="highlight highlight-text-html-basic notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="&lt;div id=&quot;root&quot;&gt;
  &lt;form&gt;
    &lt;button&gt;Submit&lt;/button&gt;
  &lt;/form&gt;
&lt;/div&gt;"><pre class="notranslate"><span class="pl-kos">&lt;</span><span class="pl-ent">div</span> <span class="pl-c1">id</span>="<span class="pl-s">root</span>"<span class="pl-kos">&gt;</span>
  <span class="pl-kos">&lt;</span><span class="pl-ent">form</span><span class="pl-kos">&gt;</span>
    <span class="pl-kos">&lt;</span><span class="pl-ent">button</span><span class="pl-kos">&gt;</span>Submit<span class="pl-kos">&lt;/</span><span class="pl-ent">button</span><span class="pl-kos">&gt;</span>
  <span class="pl-kos">&lt;/</span><span class="pl-ent">form</span><span class="pl-kos">&gt;</span>
<span class="pl-kos">&lt;/</span><span class="pl-ent">div</span><span class="pl-kos">&gt;</span></pre></div>
<p dir="auto">Please let me know if I am doing anything wrong. I think this would be necessary you want all implicit and explicate roles to be referenced in searching through selectors.</p>
<p dir="auto">I find dealing with both <code class="notranslate">check()</code> and <code class="notranslate">uncheck()</code> to be cumbersome and would prefer a single <code class="notranslate">check</code> method that can handle both through a parameter.</p>
<p dir="auto">Say I have a checkbox that configures whether a customer is a "gold" member or not. I will be testing both cases so my page object needs to both check and uncheck the checkbox, which, paradoxically, is where I run into bothers.</p>
<p dir="auto">I can either create two methods:</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="def is_gold_member(page):
    page.check('#gold')

def is_not_gold_member(page):
    page.uncheck('#gold')"><pre class="notranslate"><span class="pl-k">def</span> <span class="pl-en">is_gold_member</span>(<span class="pl-s1">page</span>):
    <span class="pl-s1">page</span>.<span class="pl-en">check</span>(<span class="pl-s">'#gold'</span>)

<span class="pl-k">def</span> <span class="pl-en">is_not_gold_member</span>(<span class="pl-s1">page</span>):
    <span class="pl-s1">page</span>.<span class="pl-en">uncheck</span>(<span class="pl-s">'#gold'</span>)</pre></div>
<p dir="auto">Or I can create a single parameterized method that requires logic in the body:</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="def is_gold_member(page, value: bool):
    if value:
        page.check('#gold')
    else:
        page.uncheck('#gold')"><pre class="notranslate"><span class="pl-k">def</span> <span class="pl-en">is_gold_member</span>(<span class="pl-s1">page</span>, <span class="pl-s1">value</span>: <span class="pl-s1">bool</span>):
    <span class="pl-k">if</span> <span class="pl-s1">value</span>:
        <span class="pl-s1">page</span>.<span class="pl-en">check</span>(<span class="pl-s">'#gold'</span>)
    <span class="pl-k">else</span>:
        <span class="pl-s1">page</span>.<span class="pl-en">uncheck</span>(<span class="pl-s">'#gold'</span>)</pre></div>
<p dir="auto">I dislike both of these options because both replicate the selector for the checkbox (which I feel moves me in the wrong direction for maintenance), and I prefer not having logic in my page objects since that is where bugs tend to hide. Parameterizing <code class="notranslate">check</code> would solve both of these woes:</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="def is_gold_member(page, value):
    page.check('#gold', value)"><pre class="notranslate"><span class="pl-k">def</span> <span class="pl-en">is_gold_member</span>(<span class="pl-s1">page</span>, <span class="pl-s1">value</span>):
    <span class="pl-s1">page</span>.<span class="pl-en">check</span>(<span class="pl-s">'#gold'</span>, <span class="pl-s1">value</span>)</pre></div>
<p dir="auto">No duplication and my guys don't need to write logic. Not only do I feel this is a cleaner solution but I think it fits better with the rest of the Playwright API too since most other inputs are also parameterized. Take <code class="notranslate">press</code> for example. It takes a parameter that handles all the cases instead of creating methods for each possible key press:</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="# We don't do this for a reason
def press_enter()

def press_escape()

def press_control_plus_enter()

def press_F1()

# etc"><pre class="notranslate"><span class="pl-c"># We don't do this for a reason</span>
<span class="pl-k">def</span> <span class="pl-s1">press_enter</span>()

<span class="pl-k">def</span> <span class="pl-s1">press_escape</span>()

<span class="pl-s1">def</span> <span class="pl-s1">press_control_plus_enter</span>()

<span class="pl-s1">def</span> <span class="pl-s1">press_F1</span>()

<span class="pl-c"># etc</span></pre></div>
<p dir="auto">This is what <code class="notranslate">check</code> and <code class="notranslate">uncheck</code> are: a method for each possible input. I'd love to see it parameterized instead. Thanks for listening!</p>