ajinasokan / autopilot

A test driver for Flutter to do QA testing without sharing app source code.
MIT License
108 stars 18 forks source link

Add /scroll-into-view?key=<key> #8

Closed mleonhard closed 1 year ago

mleonhard commented 3 years ago

My app has vertically-scrolling pages. My tests scroll widgets onto the screen and then tap them. Let's add a method for this.

ajinasokan commented 3 years ago

I'm unsure how this can be done. If the list is optimized then widget won't be there in the tree. We will have to scroll in a loop with a delay until key is found. Also there is a problem of scroll direction. It will be difficult for lib to figure out in which direction to scroll, and how to scroll in case of PageViews. In short it is very context specific.

Currently in our app we either use predefined data and place our test widget at the top of the list so that we don't have to scroll. Otherwise we manually scroll using /drag API depending on the type of the scroll/widget in that particular screen.

Let me know your thoughts.

krishaajtak commented 2 years ago

@ajinasokan I agree scrolling is very context specific. But I guess we can use the Scroll Controller in some ways.

ajinasokan commented 2 years ago

@krishaajtak Do you have any specific techniques in mind? Could you demonstrate it in an example project?

krishaajtak commented 1 year ago

Yes @ajinasokan. I am working on it, It would be great if you could also provide some insights on the implementation.

ajinasokan commented 1 year ago

I haven't tried anything other than what I mentioned in my first comment. It is the situation where there are multiple scrolling widgets, may be two ListViews, may be a ListView inside a TabBarView, may be multiple ListViews with different scroll directions, may be the list is reversed, may be it is a raw gesture detector with arbitrary directions. The API will need a generic logic to identify where to scroll and until when.

My experiments lead to the situation where it easier to do just add a keyed element to the list and then call /drag API until the key is visible in the /keys API response.

ajinasokan commented 1 year ago

May be I'm overthinking a lot and we just need a helper API to do:

add a keyed element to the list and then call /drag API until the key is visible in the /keys API response

with more customizable parameters.

CharlVS commented 1 year ago

How does Flutter Appium Driver do it?

ajinasokan commented 1 year ago

@CharlVS It does the same thing as I described above

add a keyed element to the list and then call /drag API until the key is visible in the /keys API response

CharlVS commented 1 year ago

Ah, yeah thanks, that makes sense @ajinasokan. Using Flutter Appium as a standard to meet would be a good approach since their approach is tried and tested.

This is off-topic but I did not see anywhere else that would be better to ask. I'd appreciate your input. Is there any approach you'd suggest for running Autopilot tests on device farms? I'm looking into using AWS's Device Farm with the custom environment mode.

ajinasokan commented 1 year ago

My reluctance is in adding an API that is not deterministic. Every other API is a direct call to internal Flutter APIs but this won't be. This will be a composition of drag, get-keys in a while loop with delays and timeouts. And too many unknowns like type of scrollable, axis, viewport. I do have an implementation that will work in a lot of cases. I will push that anyway in some time since this issue is more than a year old now and I'm out of ideas to make it as good as I want it to be.

I'm unsure about AWS device farm. As long as you have adb access and have a compute instance where you can run your test script you should be fine. All that Autopilot need is its internal HTTP server to be accessible in the test script.

ajinasokan commented 1 year ago

This API is now available in master. I will push the update for v0.3.1 shortly. Usage:

GET /scroll-into?scrollable-key=<key of scrollable>&key=<key of widget>&dx=<dx>&dy=<dy>&delay=<delay between drags in ms>&timeout=<timeout in ms>

Taps inside widget with given scrollable-key and drags (dx, dy) offset until given key is present in the widget tree. If the widget is inside a scrollable it will be made visible.

After one drag action it will pause for delay milliseconds and then check for the key. Default value is 500 ms.

Operation times out after timeout milliseconds. Default value is 5000 ms.

ajinasokan commented 1 year ago

Available in v0.3.1