microsoft / playwright-python

Python version of the Playwright testing and automation library.
https://playwright.dev/python/
Apache License 2.0
11.54k stars 881 forks source link

[BUG]stuck with get_by_role .click #1944

Closed wanghaisheng closed 1 year ago

wanghaisheng commented 1 year ago

Context:

Code Snippet

Help us help you! Put down a short code snippet that illustrates your bug and that we can run and debug locally.

            await page.get_by_role("button", name="Show more").is_visible() 
            print('click more get_by_role')           
            await page.get_by_role("button", name="Show more").click()  
            print('click more locator')    
            MORE_OPTIONS_CONTAINER = "#toggle-button > div:nth-child(2)"

            await page.locator(MORE_OPTIONS_CONTAINER).click()
            await page.get_by_role("button", name="Upload thumbnail").set_input_files(get_path(thumbnail))

Describe the bug

if i use get_by_role and it wont click at all, and no log if i use a traditional locator, it works well

for the thumnail input ,

playwright._impl._api_types.Error: Error: Node is not an HTMLInputElement
=========================== logs ===========================
waiting for get_by_role("button", name="Upload thumbnail")
  locator resolved to <button class="remove-default-style style-scope ytcp-thu…>…</button>
============================================================

this is the codegen script against youtube.com

from playwright.sync_api import Playwright, sync_playwright, expect

def run(playwright: Playwright) -> None:
    browser = playwright.firefox.launch(headless=False)
    context = browser.new_context(locale="en-GB")
    page = context.new_page()
    page.goto("https://www.youtube.com/")

    page.locator("ytd-identity-prompt-footer-renderer").click()
    page.locator("ytd-simple-menu-header-renderer").click()
    page.get_by_text("fastlanegonewild").click()

    page.get_by_role("link", name="English (US)").click()
    page.get_by_role("button", name="Account menu").click()
    page.get_by_role("link", name="Language: English").click()
    page.get_by_role("button", name="Back").click()
    page.get_by_text("All Gaming Live Music Podcasts Trailers Comedy Puzzle games Tina Turner Chill-ou").click()
    page.get_by_role("button", name="Account menu").click()
    page.get_by_role("link", name="YouTube Studio").get_by_role("link", name="YouTube Studio", exact=True).filter(has_text="YouTube Studio").click()
    page.get_by_role("heading", name="Channel dashboard").click()
    page.locator("#upload-button").click()
    page.get_by_role("button", name="Select files").click()
    page.get_by_role("button", name="Select files").set_input_files("3D Infant Pose Estimation from RGB Video using Deep Learning.mp4")
    page.get_by_text("Checks will begin when SD processing completes Upload complete ... Processing wi").click()
    page.get_by_text("Checks will begin when SD processing completes Upload complete ... Processing wi").click()
    page.get_by_text("Upload complete ... Processing will begin shortly").click()
    page.get_by_role("button", name="Details", exact=True).click()
    page.locator("div").filter(has_text="Video elements").nth(3).click()
    page.get_by_role("button", name="Checks").click()
    page.get_by_role("button", name="Visibility").click()
    page.get_by_role("button", name="Details").click()
    page.locator("#title-textarea #outer").click()
    page.locator("#description-textarea #outer").click()
    page.locator("#title-textarea").get_by_text("3D Infant Pose Estimation from RGB Video using Deep Learning").click()
    page.locator("#description-textarea #textbox").click()
    page.locator("#description-textarea #textbox").click()
    page.get_by_text("Description Writing descriptions with keywords can help viewers find your videos").click()
    page.get_by_role("button", name="Upload thumbnail").click()
    page.get_by_role("button", name="Upload thumbnail").set_input_files("企业微信截图_16665999853431.png")
    page.get_by_text("Playlists", exact=True).click()
    page.get_by_text("Playlists", exact=True).click()
    page.locator(".right-container").click()
    page.get_by_role("button", name="Done").click()
    page.get_by_text("Audience", exact=True).click()
    page.get_by_role("radio", name="Yes, it's made for kids . Features like personalized ads and notifications won’t be available on videos made for kids. Videos that are set as made for kids by you are more likely to be recommended alongside other kids’ videos. Learn more").click()
    page.get_by_role("radio", name="No, it's not made for kids").click()
    page.get_by_role("button", name="Age restriction (advanced)").click()
    page.get_by_role("button", name="Show more").click()
    page.get_by_role("button", name="Age restriction (advanced)").click()
    page.get_by_role("radio", name="Yes, restrict my video to viewers over 18").click()
    page.get_by_role("radio", name="No, don't restrict my video to viewers over 18 only").click()
    page.get_by_text("Paid promotion", exact=True).click()
    page.get_by_text("Paid promotion", exact=True).click()
    page.get_by_role("checkbox", name="My video contains paid promotion like a product placement, sponsorship, or endorsement").click()
    page.get_by_role("checkbox", name="My video contains paid promotion like a product placement, sponsorship, or endorsement").click()
    page.get_by_text("Automatic chapters", exact=True).click()
    page.get_by_role("checkbox", name="Allow automatic chapters and key moments").click()
    page.get_by_role("checkbox", name="Allow automatic chapters and key moments").click()
    page.get_by_text("Featured places").click()
    page.get_by_role("checkbox", name="Allow automatic places").click()
    page.get_by_role("checkbox", name="Allow automatic places").click()
    page.get_by_text("Tags", exact=True).click()
    page.get_by_text("Tags", exact=True).click()
    page.get_by_placeholder("Add tag").click()
    page.get_by_placeholder("Add tag").fill("babala,")
    page.get_by_text("Language and captions certification").click()
    page.locator("#language-input tp-yt-iron-icon").click()
    page.get_by_role("dialog").nth(1).click()
    page.get_by_role("dialog").nth(1).dblclick()
    page.get_by_role("dialog").nth(1).click()
    page.locator("tp-yt-iron-overlay-backdrop").nth(2).click()
    page.locator("#uncaptioned-reason tp-yt-iron-icon").nth(1).click()
    page.get_by_text("This content has never aired on television in the U.S.").click()
    page.locator("#uncaptioned-reason tp-yt-iron-icon").nth(1).click()
    page.get_by_role("option", name="None").locator("div").nth(1).click()
    page.locator("#recorded-date tp-yt-iron-icon").click()
    page.locator("#input-1").get_by_role("textbox").click()
    page.locator("#input-1").get_by_role("textbox").click()
    page.locator("#input-1").get_by_role("textbox").press("ArrowLeft")
    page.locator("#input-1").get_by_role("textbox").press("ArrowLeft")
    page.locator("#input-1").get_by_role("textbox").press("ArrowLeft")
    page.locator("#input-1").get_by_role("textbox").press("ArrowLeft")
    page.locator("#input-1").get_by_role("textbox").press("ArrowLeft")
    page.locator("#input-1").get_by_role("textbox").press("ArrowRight")
    page.locator("#input-1").get_by_role("textbox").press("ArrowRight")
    page.locator("#input-1").get_by_role("textbox").press("ArrowRight")
    page.locator("#input-1").get_by_role("textbox").press("ArrowRight")
    page.locator("#input-1").get_by_role("textbox").fill("May 23,2023")
    page.locator("#input-1").get_by_role("textbox").press("Enter")
    page.locator("#input-1").get_by_role("textbox").press("ArrowLeft")
    page.locator("#input-1").get_by_role("textbox").press("ArrowLeft")
    page.locator("#input-1").get_by_role("textbox").press("ArrowLeft")
    page.locator("#input-1").get_by_role("textbox").press("ArrowLeft")
    page.locator("#input-1").get_by_role("textbox").press("ArrowLeft")
    page.locator("#input-1").get_by_role("textbox").press("ArrowRight")
    page.locator("#input-1").get_by_role("textbox").fill("May 23, 2023")
    page.locator("#input-1").get_by_role("textbox").press("Enter")
    page.get_by_placeholder("None").click()
    page.get_by_text("Video location").click()
    page.get_by_placeholder("Search", exact=True).click()
    page.get_by_placeholder("Search", exact=True).dblclick()
    page.get_by_placeholder("Search", exact=True).fill("lake")
    page.get_by_text("License").first.click()
    page.get_by_text("License").first.click()
    page.locator("#license tp-yt-iron-icon").click()
    page.get_by_role("option", name="Standard YouTube License").get_by_text("Standard YouTube License").click()
    page.locator("#license tp-yt-iron-icon").click()
    page.get_by_text("Creative Commons - Attribution").click()
    page.get_by_role("checkbox", name="Allow embedding").click()
    page.get_by_role("checkbox", name="Allow embedding").click()
    page.get_by_role("checkbox", name="Publish to subscriptions feed and notify subscribers").click()
    page.get_by_role("checkbox", name="Publish to subscriptions feed and notify subscribers").click()
    page.get_by_text("Shorts remixing").click()
    page.get_by_role("radio", name="Allow video and audio remixing").click()
    page.get_by_role("radio", name="Allow only audio remixing").click()
    page.get_by_role("radio", name="Don’t allow remixing").click()
    page.get_by_text("Category", exact=True).click()
    page.locator("#category tp-yt-iron-icon").click()
    page.get_by_role("option", name="Autos & Vehicles").locator("div").nth(1).click()
    page.locator("#category tp-yt-iron-icon").click()
    page.get_by_role("option", name="Comedy").locator("div").nth(1).click()
    page.locator("#category tp-yt-iron-icon").click()
    page.get_by_role("option", name="Education").locator("div").nth(1).click()
    page.locator("#category tp-yt-iron-icon").click()
    page.get_by_role("option", name="Entertainment").locator("div").nth(1).click()
    page.locator("#category tp-yt-iron-icon").click()
    page.get_by_role("option", name="Entertainment").locator("div").nth(1).click()
    page.locator("#category tp-yt-iron-icon").click()
    page.get_by_role("option", name="Film & Animation").locator("div").nth(1).click()
    page.get_by_text("Comments and ratings").click()
    page.get_by_role("radio", name="Allow all comments").click()
    page.get_by_role("radio", name="Hold potentially inappropriate comments for review").click()
    page.get_by_role("checkbox", name="Increase strictness").click()
    page.get_by_role("checkbox", name="Increase strictness").click()
    page.get_by_role("radio", name="Hold all comments for review").click()
    page.get_by_role("radio", name="Disable comments").click()
    page.get_by_role("radio", name="Allow all comments").click()
    page.get_by_text("Video upload complete Video processingProcessing complete Copyright check comple").click()
    page.get_by_text("Video link").click()
    with page.expect_popup() as page1_info:
        page.locator("div").filter(has_text="https://youtu.be/4-WqSxzi7GY").nth(4).click()
    page1 = page1_info.value
    page1.close()
    page.get_by_role("button", name="Next", exact=True).click()
    page.get_by_role("button", name="Next", exact=True).click()
    page.locator("#content").click()
    page.get_by_role("button", name="Next", exact=True).click()
    page.get_by_role("radio", name="Save or publish").click()
    page.get_by_role("radio", name="Schedule").click()
    page.get_by_role("radio", name="Save or publish").click()
    page.get_by_role("radio", name="Private").click()
    page.get_by_text("Private Only you and people you choose can watch your video Share privately Unli").click()
    page.get_by_role("radio", name="Unlisted").click()
    page.get_by_role("radio", name="Public").click()
    page.get_by_role("checkbox", name="Set as instant Premiere").click()
    page.get_by_role("radio", name="Schedule").click()
    page.locator("#datepicker-trigger tp-yt-iron-icon").click()
    page.locator("#input-4").get_by_role("textbox").click(click_count=3)
    page.locator("#input-4").get_by_role("textbox").fill("May28, 2023")
    page.locator("#input-4").get_by_role("textbox").press("Enter")
    page.locator("#input-4").get_by_role("textbox").press("ArrowLeft")
    page.locator("#input-4").get_by_role("textbox").press("ArrowLeft")
    page.locator("#input-4").get_by_role("textbox").press("ArrowLeft")
    page.locator("#input-4").get_by_role("textbox").press("ArrowLeft")
    page.locator("#input-4").get_by_role("textbox").press("ArrowLeft")
    page.locator("#input-4").get_by_role("textbox").fill("May28 , 2023")
    page.locator("#input-4").get_by_role("textbox").press("ArrowRight")
    page.locator("#input-4").get_by_role("textbox").press("Enter")
    page.locator("#input-4").get_by_role("textbox").press("ArrowLeft")
    page.locator("#input-4").get_by_role("textbox").press("ArrowLeft")
    page.locator("#input-4").get_by_role("textbox").press("ArrowLeft")
    page.locator("#input-4").get_by_role("textbox").press("ArrowLeft")
    page.locator("#input-4").get_by_role("textbox").press("ArrowLeft")
    page.locator("#input-4").get_by_role("textbox").press("ArrowRight")
    page.locator("#input-4").get_by_role("textbox").fill("May 28 , 2023")
    page.locator("#input-4").get_by_role("textbox").press("ArrowRight")
    page.locator("#input-4").get_by_role("textbox").press("ArrowRight")
    page.locator("#input-4").get_by_role("textbox").press("ArrowRight")
    page.locator("#input-4").get_by_role("textbox").fill("May 28, 2023")
    page.locator("#input-4").get_by_role("textbox").press("Enter")
    page.locator("#input-3").get_by_role("textbox").click()
    page.locator("#input-3").get_by_role("textbox").press("ArrowRight")
    page.locator("#input-3").get_by_role("textbox").press("ArrowRight")
    page.locator("#input-3").get_by_role("textbox").fill("08:15 AM")
    page.locator("#input-3").get_by_role("textbox").press("Enter")
    page.get_by_role("checkbox", name="Set as Premiere").click()
    page.get_by_role("checkbox", name="Set as Premiere").click()
    page.get_by_role("button", name="Schedule").click()
    page.get_by_role("heading", name="Video published").click()
    page.get_by_role("dialog", name="Video published").locator("div").filter(has_text="Video link https://youtu.be/4-WqSxzi7GY").nth(2).click()
    with page.expect_popup() as page2_info:
        page.get_by_role("dialog", name="Video published").get_by_role("link", name="https://youtu.be/4-WqSxzi7GY").click()
    page2 = page2_info.value
    page2.close()
    page.get_by_role("dialog", name="Video published").locator("#close-button").click()
    page.get_by_role("button", name="Content").click()
    page.get_by_role("button", name="Options").click()
    page.get_by_placeholder("Filter").click()
    page.locator("#page-title-container").click()
    page.locator("#html-body").press("Escape")
    page.get_by_role("heading", name="Channel content").click()
    page.locator("#html-body").press("Escape")
    page.get_by_role("button", name="Details").click()
    page.get_by_role("button", name="Subtitles").click()
    page.get_by_role("checkbox", name="Make this the default for my channel").click()
    page.get_by_role("checkbox", name="Make this the default for my channel").click()
    page.locator(".right-container").click()
    page.locator("tp-yt-iron-overlay-backdrop").nth(2).click()
    page.locator("#trigger").get_by_text("Set language").click()
    page.get_by_role("dialog").click()
    page.locator("tp-yt-iron-overlay-backdrop").nth(2).click()
    page.locator("#no-language div").filter(has_text="Confirm").first.click()
    page.locator(".right-container").click()
    page.goto("https://studio.youtube.com/video/4-WqSxzi7GY/translations")

    # ---------------------
    context.close()
    browser.close()

with sync_playwright() as playwright:
    run(playwright)
wanghaisheng commented 1 year ago

more info here I use to get the expression hints

        await page.get_by_text("Schedule").click()
Error: strict mode violation: get_by_text("Schedule") resolved to 4 elements:
    1) <span dir="auto" style-target="bold" class="bold style…>The date you uploaded, scheduled, or published yo…</span> aka get_by_text("The date you uploaded, scheduled, or published your video")
    2) <yt-formatted-string class="style-scope ytcp-paper-tooltip-body">You’ll see the upload date if your video is priva…</yt-formatted-string> aka get_by_text("You’ll see the upload date if your video is private, or unlisted. If your video ")
    3) <div id="radioLabel" style-target="label" class="styl…>Schedule</div> aka get_by_role("radio", name="Schedule")
    4) <div class="label style-scope ytcp-button">Schedule</div> aka get_by_role("button", name="Schedule")

the 4th is the button what I want to click,so

        await page.get_by_role("button", name="Schedule").click()

error I got ``` playwright._impl._api_types.TimeoutError: Timeout 30000ms exceeded. =========================== logs =========================== waiting for get_by_role("button", name="Schedule") locator resolved to <ytcp-button disabled type="filled" tabindex="-1" role="butto…>…
attempting click action waiting for element to be visible, enabled and stable element is not enabled - waiting... element is visible, enabled and stable scrolling into view if needed done scrolling

intercepts pointer events retrying click action, attempt #1 waiting for element to be visible, enabled and stable ``` ```
Schedule
```
wanghaisheng commented 1 year ago

try xpath expression, still stuck

=========================== logs ===========================
waiting for locator("xpath=//*[@id='done-button']")
  locator resolved to <ytcp-button tabindex="0" type="filled" role="button" track-c…>…</ytcp-button>      
attempting click action
  waiting for element to be visible, enabled and stable
  element is visible, enabled and stable
  scrolling into view if needed
  done scrolling
  <tp-yt-iron-overlay-backdrop opened="" class="opened">…</tp-yt-iron-overlay-backdrop> intercepts pointer events
retrying click action, attempt #1
  waiting for element to be visible, enabled and stable
  element is visible, enabled and stable
  scrolling into view if needed
  done scrolling
  <tp-yt-iron-overlay-backdrop opened="" class="opened">…</tp-yt-iron-overlay-backdrop> intercepts pointer events
retrying click action, attempt #2
  waiting 20ms
  waiting for element to be visible, enabled and stable
  element is visible, enabled and stable
  scrolling into view if needed
  done scrolling
  <tp-yt-iron-overlay-backdrop opened="" class="opened">…</tp-yt-iron-overlay-backdrop> intercepts pointer events
retrying click action, attempt #3
  waiting 100ms
  waiting for element to be visible, enabled and stable
wanghaisheng commented 1 year ago

PWDEBUG =1 and provide a short video for this https://youtu.be/3-anQ7XSpIY https://youtu.be/DhybEFFKbMo @mxschmitt

mxschmitt commented 1 year ago

This is a very involved reproduction. Looking at

if i use get_by_role and it wont click at all, and no log if i use a traditional locator, it works well

this sounds reasonable. Probably the wrong element is located when clicking? If you get a strict mode violation, you need to make your selector more specific.

wanghaisheng commented 1 year ago

@mxschmitt. other element the above saying works

but the last schedule button in the video is not clickable at all as you can say there is a red shot above the button when debug

I just learn how to debug playwright, but right now it seems not that helpful

Tomorrow I can try to use inspect on the pwdebug mode to copy selector

wanghaisheng commented 1 year ago

@mxschmitt

I fix this . all the issue not related to selector. before click the button ,i got a keyboard input without press enter. I dont give this detail a shit before. can you add hint to doc for any other

    await page.keyboard.type(hour_to_publish)

    await page.keyboard.press("Enter")