-
Notifications
You must be signed in to change notification settings - Fork 815
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
Restrict Pilot.click to visible area #3349
Comments
(Not sure why it shows my face in the first comment; that was written by Will.) |
The app below shows an example of a click that doesn't land on the widget we want because the widget is scrolled out of view. I think it makes sense to do something if the user tries to click/hover something outside of the screen. Code showing a click that doesn't land on the target.import asyncio
from textual.app import App
from textual.widgets import Button, Label
class MyApp(App):
clicked = False
def compose(self):
for idx in range(200):
yield Label(str(idx))
yield Button()
def on_button_pressed(self):
self.clicked = True
async def main():
app = MyApp()
async with app.run_test(size=(80, 24)) as pilot:
await pilot.click(Button, offset=(1, 1))
assert not app.clicked
if __name__ == "__main__":
asyncio.run(main()) |
Regarding the methods Furthermore, I propose that both methods return a Boolean value indicating whether the action made it to the intended widget. |
The methods click/hover will now raise an error if they target a region that is outside of the target widget or completely outside of the screen. Then, they return a Boolean that indicates whether the click/hover hit the intended widget or not. Related issue: #3349.
Given the review feedback received, the new proposal is as follows:
|
What is the purpose of
Can you give me an example of a test that uses this? |
|
I don't like the change of name, as it doesn't suggest what it is. Making it a keyword arg also makes it more verbose to write tests. It's also more common to click a thing with no offset, so it seems to be in the wrong order now.
Yes, but can I have an example? I would like to see how a dev would benefit from this in a practical example. |
It says exactly what it is: the widget to which the provided offset is relative to.
I'm happy to implement a
from textual.app import App, ComposeResult
from textual.widgets import Static
class LayersExample(App):
CSS = """
Screen {
layers: below above;
}
#box1 {
layer: above;
}
#box2 {
layer: below;
}
"""
def compose(self) -> ComposeResult:
yield Static("box1 (layer = above)", id="box1")
yield Static("box2 (layer = below)", id="box2")
async def test_clicks_target_first_layer():
app = LayersExample()
async with app.run_test() as pilot:
box_above = app.query_one("#box1")
assert (await pilot.click((1, 1), "#box2")) is box_above
class ThisAppHasAButton(App):
...
async def test_hover_pseudo_class_applied_on_hover():
app = ThisAppHasAButton()
async with app.run_test() as pilot:
button = app.query_one(Button)
assert (await pilot.click_widget(Button)) is button # sanity check
assert "hover" in button.get_pseudo_classes() |
After some more talking, we'll just clear up the wording of docstrings and return a Boolean value indicating whether the click/hover happened to hit the selected widget. |
Don't forget to star the repository! Follow @textualizeio for Textual updates. |
I suspect that
Pilot.click
will allow clicking of widgets that may not be in the visible area of the screen.Since we are simulating a real user operating the mouse, we should make that not work. Probably by throwing an exception.
It also looks like it is possible to supply an
offset
that would click outside of the visible area. This should probably also result in an exception.The text was updated successfully, but these errors were encountered: