=== vrruiz_ is now known as rvr === pgraner-afk is now known as pgraner === chihchun is now known as chihchun_afk === qwebirc539535 is now known as slickymasterWork [18:41] balloons: hey, I tried to write my first autopilot test, but I'm struggling… I tried to write a test for this bug: https://bugs.launchpad.net/ubuntu-calculator-app/+bug/1410986 But I don't know how to access the calculationHistory to do a "longpress" [18:41] Launchpad bug 1410986 in Ubuntu Calculator App "[Autopilot] Test delete multiple calculation from history" [Medium,Confirmed] [18:43] svij, howdy [18:43] let's have a look [18:44] :) === pgraner is now known as pgraner-dr [18:52] svij, so I believe step 2 is basically press and hold on the white screen at the top [18:52] it will let you play with the calculations [18:53] balloons: yes, and I have no idea how to do that [18:53] you should get an action menu and checkboxes.. [18:53] ohh, lol, you mean have AP do that :p [18:53] yeah :D [18:53] sorry. :D [18:53] svij,are you able to find the object ok? [18:54] we can press and hold using https://developer.ubuntu.com/api/autopilot/python/1.5.0/autopilot.input.Touch/ [18:55] balloons: I'm not sure which object it is (I'm not really familiar with qml) [18:56] svij, awesome, so let's talk about how to figure that out [18:56] svij, have you tried using autopilot vis yet? Because that's how we'll figure out the object [18:56] hm, nope [18:57] let me find the docs… [18:58] https://developer.ubuntu.com/api/autopilot/python/1.5.0/guides-running_ap/#visualise-introspection-tree the images are broken :( [18:59] svij, yikes.. we'll have to fix that! [18:59] (it's also broken on a couple of other pages of the autopilot pages) [18:59] right, thanks for pointing it out. I'll file a bug on the site nd get it fixed [19:01] anyways, so right. first lanuch the app, then run vis to have a visual look at the introspection tree [19:01] for calculator I wold do this: [19:01] autopilot launch -i Qt qmlscene app/ubuntu-calculator-app.qml [19:01] autopilot3 vis [19:03] got it [19:03] and selected the calculator app in vis [19:04] excellent. So now you can see the full tree. It's a little odd to browse at first, but you'll get used to it [19:05] look under the MainView and OrientationHelper to get into the app internals [19:05] and then? [19:06] see the yellow button next to the spyglass at the top of the app? [19:06] yes [19:06] if you toggle it, it would highlight the part of the app that the object you select in the tree represents [19:06] this can sometimes be useful [19:06] so now I would try and figure out / understand what objects are in the top of the calculator [19:08] looking through things, I see a PageStack, other Page definitions, and then finally a header and a scrollable view [19:10] the scrollview was hard to find [19:10] scrollable view* [19:10] svij, yes, sometimes the object tree is just a little confusing. In those cases, let me show you another way to grok the tree [19:12] and the QQuickLoader seems to be one item of the calculation history [19:12] check out print_tree() on https://developer.ubuntu.com/api/autopilot/python/1.5.0/autopilot.introspection.ProxyBase/ [19:12] so one thing you can do is launch the app under test in python, then do a dump of the tree if you will to a file, using print_tree on the root node [19:12] does that make sense? [19:13] how do I "launch the app under test in python"? [19:15] svij, that's what is happening in the test cases. So in this case I would add another test case to the test_main.py file, and then have autopilot run it [19:15] oh right [19:15] svij, something tiny, like def test_dump_tree(self): [19:15] self.app.main_view.print_tree() [19:16] trying… [19:16] make sure you redirect the output to a file when you run :-) [19:17] so it doesn't dump to your console [19:18] hehe, yes. [19:19] okay, and now? [19:20] we can review the output. Also, I had a look in the test helpers and noticed there is already a helper for calculationhistory [19:20] do you see it in __init__.py? [19:20] yes [19:22] I also see mainview has a helper method already called get_history [19:22] yes, i see [19:23] if you look inside your dump, you can see this object.. Look for objectName: 'scrollableView' [19:23] anyways, I might suggest that this is exactly what we want to press and hold [19:23] what do you think? [19:23] sure [19:25] but do I need to press and hold that scrollableView or one item in that scrollableView? [19:25] so let's try. First, use the helper method that already exists to get the object, then use autopilot to press and hold it [19:26] when you interact with an object, by default autopilot will try and determine it's coordinates, then press in the middle of the object [19:26] ahh [19:26] so that might work just fine for us [19:26] do I need the "press_and_hold" method from MainView in __init__.py? === jhodapp_ is now known as jhodapp [19:29] svij, no, that's a custom method and by looking at it I can see it's intended to press and hold a button on the keypad [19:29] oh right [19:29] yea, should be more aptly named / commented [19:30] so, I'm getting the object with "self.app.main_view.get_history()" right? [19:31] anyways, so just use autopilot methods themselves to click. [19:31] svij, yes [19:31] so, call ".press()" on that? [19:32] or tap, with a duration… [19:32] svij, yes but I realized that doesn't help you :-) Have a look at https://developer.ubuntu.com/api/autopilot/python/1.5.0/autopilot.input.Pointer/.. You'll see there's a nice method called click_object [19:32] and move_to_object [19:33] otherwise you'd have to read the object properties yourself, then press at the proper position. Easier to simply use the built-in method AP provides to do this [19:35] wait, how do I call that exactly? [19:36] svij, so notice you'll need to creating a pointing device, and these methods are for that class. Now, if you look at the CalculatorApp class in __init__.py, you'll see we've done this in the __init__ method [19:37] err sorry.. we declare a property in the class rather . . . [19:37] um, ok. [19:37] does that make sense to you? [19:38] just know you have a pointing_device ready to go you can use for this stuff under self.app.pointing_device [19:38] so self.app.pointing_device.click_object, self.app.pointing_device.press, etc [19:39] let me check… [19:39] you can learn more about the details of how the app is launched and the objects initialized can come later [19:41] I've got two lines in my test case right now: [19:42] self.app.pointing_device.move_to_object(self.app.main_view.get_history()) [19:42] self.app.pointing_device.click_object(self) [19:42] but that doesn't work [19:43] "ValueError: Object '' does not have any recognised position attributes [19:43] oh wait… [19:44] svij, just fyi the self.app.pointing_device.move_to_object isn't needed as click_object will do that for you [19:44] svij, so here's what I wrote: [19:44] history = self.app.main_view.get_history() [19:44] self.app.pointing_device.click_object(history, 1, 3) [19:45] I got the same error as you, so clearly the object we get from history isn't what is being shown :-) [19:45] since it doesn't have x,y,z coords, it's an internal object. [19:45] okay [19:46] ohh, look at the get_history method again [19:47] it's returning a class [19:48] yes [19:48] so…? [19:49] so, we need an object to pass to AP, not a class [19:49] right [19:50] svij, so notice in __init__, it puts the object in self.app. So we could pass AP the object directly [19:51] history.app. That runs for me, but doesn't quite do what we want [19:51] let me check… [19:51] I hope working through it like this is helping.. I'm going through it slowly with you the same way as I would approach it [19:51] yeah, sure, it helps. :) [19:53] and yes, it doesn't really help us. [19:53] (i mean the code) [19:54] but you now have the knowledge you need to click the object once we find it [19:55] so at this point I would look deeper into scrollable view. It looks like / my guess is the history we see is laid out in rows [19:55] it is [19:56] QQuickLoaders it seems [19:57] so ideally we would enter a calculation, then long press on it's history result I think [19:57] or actually it's asking us to test deleting more than 1 as well [19:59] yes [19:59] but I need to figure out how to access one of those QQuickloaders [19:59] svij, so one thing we can do is use strings to help get us closer to understanding the layout. I would do a print_tree again, but using the calc history object as the root this time. [20:00] Then I would look for a string that is one of the numbers in the history [20:01] doing that gave me an object under /comubuntucalculator/QQuickView/MainView/OrientationHelper/QQuickItem/QQuickItem/PageStack/PageWrapper/PageWithBottomEdge/ScrollableView/QQuickItem/QQuickColumn/QQuickLoader/Screen/QQuickRectangle/QQuickItem/QQuickColumn/QQuickRow/QQuickText [20:03] yes [20:04] so at this point, it seems the layout is under Screen. I would go look at the qml and set an objectname on the object I want, if there isn't one [20:05] ok, let me check… [20:07] balloons: is "screenDelegate" as an objectName okay? [20:07] svij, sure [20:07] good :) [20:08] and now? [20:09] I think I need to add an "_get_screen" function, which returns the screen? [20:09] in __init__.py [20:11] svij, sure we could make a helper class with some methods again [20:11] but I'd get things working first before trying to abstract things [20:11] imho [20:11] oh, right, sure. [20:13] let me try… [20:15] k, I'm looking at / in Screen.qml [20:15] I added objectnames to the results and to the root Screen [20:15] * svij thought that this is a simple autopilot test for the beginning :) [20:16] svij, it's turning a little more difficult because we don't have handy access to the objects we need [20:16] but this is good learning material ;-) [20:16] yeah, definitely [20:17] isn't that documented somewhere? [20:17] what documented? [20:18] how to find and access objects without helper functions [20:19] well, that's more or less what vis and print_tree are for. But there's no magical shortcuts besides simply reading the qml [20:19] oh ok [20:19] that said, I'm happy to hear of docs that would be helpful. Happy to write them [20:20] so the result text has objectName [20:20] but I added an objectname to the root element [20:21] (and I'm happy to help to improve the docs ;) ) [20:24] :-) [20:24] So I noticed Screen.qml uses ListItemWithActions.qml [20:24] yes [20:25] so when I added an objectname there, I see it now :-) [20:25] it's a bit odd [20:25] wait, where do you "see it now"? [20:26] in the dbus tree dumps. I was looking for an objectname under a Screen object [20:27] dbus tree dump was that print_tree() command, right? [20:28] svij, yes, I've been iterating over running dumps using it.. [20:28] ok [20:28] I'm dumping with Screen as the root object [20:29] note, there appears to be 2 Screen objects also [20:29] so [20:29] screens = self.app.main_view.select_many('Screen') [20:29] for screen in screens: [20:29] screen.print_tree() [20:31] ok [20:31] so, my issue to solve at this point is figure out how to make sure I select a specific object in the list. Doing those dumps shows me there are mutliple result objects for instance.. each result is sharing the same objectname [20:32] normally we would fix that by adding a dynamic property to the objectname declaration. So for example, objectName: "listitem" + index [20:33] and in this case (if its not 'normally')? [20:37] balloons: do you mind, if we continue tomorrow? It's getting late here and I'm really tired now and less concentrated… [20:37] svij, well the qml object is custom it seems. So it's more painful [20:37] svij, no worries. I'll figure out how to assign the objectname sanely so we can get back to the actual test [20:37] great! [20:37] if you encounter something like this, the answer is always ask the developer [20:38] what on earth is going on in your custom object :-) [20:38] first I need to figure out what are "normal" and what are "custom" objects [20:38] and how to access them properly ;) [20:38] svij, "normal" is assign the objectname and then see it in the tree and go [20:38] lol [20:39] anyway, thanks so far! I'll ping you tomorrow [20:40] good night! [20:41] thanks [20:41] yw