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.
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.