pythonsliderrobotframeworktosca

A puzzle with Robot framework, scroll into view. I can't get a slider of a web element to start scrolling down


A profile LTL on stackoverflow did a great attempt to do the obstacle course of Tosca but then done with Robot framework (real clever to train test automation and you can compare along)

If you're NEW with test automation this is really a nice way to start. It's a really good help to the community.

I took this idea a bit further and put it on a Github repo. Including a beautifull README. But I need the help of the community because I got stuck with one of the puzzles.

So there is this puzzle 99999 scroll into view and the solution how to do it with Tosca is really plain and simple. (3th video)

What I have consists of 2 parts...

The custom Library code I made for that (filename is CustomActionsIntegrated.py)

    from robot.api.deco import keyword

@keyword('Draw Dot and Click At Coordinates')  # New combined keyword
def draw_and_click_at_coordinates(x, y):
    """
    Draw a red dot at the specified coordinates (x, y) for debugging purposes,
    then simulate a click event at the same coordinates, followed by holding the LEFT mouse button,
    scrolling down with the mouse wheel, and moving the mouse down simultaneously.
    """
    # JavaScript to draw the red dot
    draw_script = f"""
    var marker = document.createElement('div');
    marker.style.position = 'absolute';
    marker.style.left = '{x}px';
    marker.style.top = '{y}px';
    marker.style.width = '20px';
    marker.style.height = '20px';
    marker.style.backgroundColor = 'blue';
    marker.style.borderRadius = '50%';
    marker.style.zIndex = '9999';
    marker.style.pointerEvents = 'none';
    marker.style.border = '2px solid black';
    document.body.appendChild(marker);
    """
    
    # JavaScript to simulate the click
    click_script = f"""
    var event = new MouseEvent('click', {{ clientX: {x}, clientY: {y}, bubbles: true, cancelable: true }});
    document.elementFromPoint({x}, {y}).dispatchEvent(event);
    """

    # JavaScript to simulate LEFT mouse button down
    mouse_down_script = f"""
    var mouseDownEvent = new MouseEvent('mousedown', {{
        clientX: {x},
        clientY: {y},
        button: 0,  // 0 = LEFT mouse button
        bubbles: true,
        cancelable: true
    }});
    document.elementFromPoint({x}, {y}).dispatchEvent(mouseDownEvent);
    """

    # JavaScript to simulate mouse wheel scroll down (page down)
    wheel_scroll_script = f"""
    var wheelEvent = new WheelEvent('wheel', {{
        deltaY: 1000,  // Positive value scrolls down
        clientX: {x},
        clientY: {y},
        bubbles: true
    }});
    document.elementFromPoint({x}, {y}).dispatchEvent(wheelEvent);
    """

    # JavaScript to simulate mouse movement down
    mouse_move_script = f"""
    var mouseMoveEvent = new MouseEvent('mousemove', {{
        clientX: {x},
        clientY: {y + 1000},  // Move 1000 pixels down
        bubbles: true,
        cancelable: true
    }});
    document.elementFromPoint({x}, {y}).dispatchEvent(mouseMoveEvent);
    """

    # JavaScript to simulate LEFT mouse button up
    mouse_up_script = f"""
    var mouseUpEvent = new MouseEvent('mouseup', {{
        clientX: {x},
        clientY: {y + 1},  // Release at the new position
        button: 0,  // 0 = LEFT mouse button
        bubbles: true,
        cancelable: true
    }});
    document.elementFromPoint({x}, {y +1}).dispatchEvent(mouseUpEvent);
    """

    # Combine all actions with minimal delays
    return f"""
    {draw_script}
    setTimeout(function() {{
        {click_script}
        setTimeout(function() {{
            {mouse_down_script}
            setTimeout(function() {{
                {wheel_scroll_script}
                {mouse_move_script}
                setTimeout(function() {{
                    {mouse_up_script}
                }}, 50);  // Delay after combined actions before releasing mouse button
            }}, 10);  // Minimal delay after mouse down before combined actions
        }}, 10);  // Minimal delay after click before mouse down
    }}, 10);  // Minimal delay after drawing before click
    """

and the .robot file is this:

    *** Settings ***
Library    SeleniumLibrary
Library    CustomAction1.py  # Import the custom actions file
Library    CustomAction2.py  # Import the custom actions file
Library    CustomActionsIntegrated.py
Variables  variables.py

*** Variables ***
${URL}        https://obstaclecourse.tricentis.com/Obstacles/99999

*** Test Cases ***
Visueel Klikken Onder Submit
    Open Browser    ${URL}   Chrome
    Maximize Browser Window
    Wait Until Element Is Visible    xpath=//*[@id='submit']

    # Get element's position using JavaScript
    ${location}=    Execute JavaScript
    ...    var rect = document.evaluate("//*[@id='submit']", document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue.getBoundingClientRect();
    ...    return [rect.left + (rect.width / 2) + 132, rect.top + window.scrollY + 130];

    # Access the location array using indexes for x and y
    ${click_x}=    Set Variable    ${location}[0]
    ${click_y}=    Set Variable    ${location}[1]

    # Scroll to make the click area visible
    Execute JavaScript    window.scrollTo(0, ${click_y} - 200);
    #Sleep    1s

    # Draw the red dot using the custom keyword
    Draw Red Dot    ${click_x}    ${click_y}
    #Sleep    1s

    # Click the page at the specified coordinates using the custom keyword
    #Click Page At Coordinates  ${click_x}    ${click_y}
    #Sleep    1s
    
    #combined , blue dot
    ${js_code}=    Draw Dot and Click At Coordinates   ${click_x}  ${click_y}
    Execute JavaScript    ${js_code}

    #Draw Dot and Click At Coordinates   ${click_x}  ${click_y}
    #Draw Dot and Click At Coordinates  ${click_x}  ${click_y}

    # Wait for the page to respond before proceeding

     # Click at the exact location (Now with improved visibility)
    #Click Element At Coordinates    xpath=//*[@id='submit']    132    130

    # Wait for the page to respond before proceeding

    # Scroll down to bring up more content (if required)
    #Press Keys     //body   PAGE_DOWN
    Sleep    2s

    # Ensure overlay2 is visible (if needed)
    #Execute JavaScript    document.getElementById('textfield').scrollIntoView()

    # Input text in the text field
    Input Text  xpath=//*[@id='textfield']  Tosca
    Sleep    1s

    # Drag overlay2 down
    #Drag And Drop By Offset    id=overlay2    0    100
    Sleep    2s
    
    # Click the submit button again
    Click Element   xpath=//*[@id='submit'] 

    # Validate success message
    Element Should Contain    xpath=//body    You solved this automation problem.

But I can't get it to work. Maybe I'm thinking way to complex. I tried the help of DeepSeek and ChatGPT, but I didn't find a proper working solution yet.

So if you see any mistakes or you see a solution. please help.

Also if you would like to improve and upgrade this repo to the point that all the puzzles have a solution, let me know then I e-mail you so you can do commits as well.


Solution

  • Here is my solution, but only worked on Firefox.

    *** Settings ***
    Library           SeleniumLibrary
    
    *** Variables ***
    ${URL}            https://obstaclecourse.tricentis.com/Obstacles/99999
    ${BROWSER}        Firefox
    
    *** Test Cases ***
    Scroll Into View And Submit
        Open Browser    ${URL}    ${BROWSER}
        Maximize Browser Window
        Wait Until Element Is Visible    submit
        Select Frame    container
        VAR    ${counter}    0
        WHILE    ${counter} < 4
            Sleep    1s
            Press Keys    //body    ARROW_DOWN
            Execute Javascript    var top = document.body.scrollTop; document.body.scrollTop = 100;
            ${counter}=    Evaluate    ${counter} + 1
            ${result}    ${code}=    Run Keyword And Ignore Error    Wait Until Element Is Enabled    textfield    timeout=1
            IF    "${result}" == "PASS"    BREAK
        END
        Sleep    1s
        # Input text in the text field
        Input Text    textfield    Tosca
        Sleep    1s
        Unselect Frame
        # Click the submit button
        Click Element    submit
        Sleep    1s
        Select Frame    container
        VAR    ${counter}    0
        WHILE    ${counter} < 4
            Sleep    1s
            Press Keys    //body    ARROW_UP
            Execute Javascript    var top = document.body.scrollTop; document.body.scrollTop = -100;
            ${counter}=    Evaluate    ${counter} + 1
            ${result}    ${code}=    Run Keyword And Ignore Error    Wait Until Element Is Enabled    textfield    timeout=1
            IF    "${result}" == "FAIL"    BREAK
        END
        Unselect Frame
        # Validate success message
        # On Firefox fails because is already at next challenge, on Chrome fails because scrolls main window
        Capture Page Screenshot
        # Page Should Contain    You solved this automation problem.