Merge lp:~nskaggs/ubuntu-rssreader-app/convert-tests-to-sdk into lp:~ubuntu-shorts-dev/ubuntu-rssreader-app/trunk

Proposed by Nicholas Skaggs
Status: Merged
Merged at revision: 36
Proposed branch: lp:~nskaggs/ubuntu-rssreader-app/convert-tests-to-sdk
Merge into: lp:~ubuntu-shorts-dev/ubuntu-rssreader-app/trunk
Diff against target: 1056 lines (+426/-358)
15 files modified
TopicTab.qml (+5/-0)
feeds/AppendFeedPage.qml (+1/-1)
feeds/ChooseTopicPage.qml (+2/-1)
feeds/EditFeed.qml (+2/-1)
feeds/ManageFeedsPage.qml (+1/-0)
feeds/TopicManagement.qml (+2/-0)
listview/ArticleListPage.qml (+1/-1)
listview/FeedListPage.qml (+1/-1)
tests/autopilot/ubuntu_rssreader_app/emulators.py (+123/-0)
tests/autopilot/ubuntu_rssreader_app/emulators/__init__.py (+0/-6)
tests/autopilot/ubuntu_rssreader_app/emulators/main_window.py (+0/-64)
tests/autopilot/ubuntu_rssreader_app/emulators/ubuntusdk.py (+0/-153)
tests/autopilot/ubuntu_rssreader_app/tests/__init__.py (+39/-36)
tests/autopilot/ubuntu_rssreader_app/tests/test_rssreader.py (+246/-94)
ubuntu-rssreader-app.qml (+3/-0)
To merge this branch: bzr merge lp:~nskaggs/ubuntu-rssreader-app/convert-tests-to-sdk
Reviewer Review Type Date Requested Status
Nicholas Skaggs (community) Approve
Review via email: mp+179843@code.launchpad.net

This proposal supersedes a proposal from 2013-08-04.

Commit message

Converted autopilot tests to ubuntu sdk emulator
Merged Carla's restored add and removed feed test

Description of the change

Converted autopilot tests to ubuntu sdk emulator
Merged Carla's restored add and removed feed test

To post a comment you must log in.
Revision history for this message
Nicholas Skaggs (nskaggs) wrote : Posted in a previous version of this proposal

A quick glance at this, I don't see anything that jumps out at me. I'll do a better review tomorrow if it's not merged by then ;-)

Revision history for this message
Nicholas Skaggs (nskaggs) wrote : Posted in a previous version of this proposal

Converting this to the emulator and rebasing to upstream trunk

Revision history for this message
Nicholas Skaggs (nskaggs) wrote : Posted in a previous version of this proposal

Looks good Carla, plenty of asserts in here to make sure timing doesn't bite you :-) Having all those asserts to check each step is really good. A couple things to note;

As you know English strings break things when we run in other languages, like Italian ;-) So, use the .visible property to ensure your on the proper page rather than the page title. This won't break when they rename the pages either! No need to check the title if we got the object (page) and it's visible.

We can also assert when things like text entry boxes come into focus via the .focus property. Pretty handy to make sure our text entry goes in the proper place :-)

These little things could cause issues when run on the devices, but likely doesn't effect the desktop runs, so it doesn't come up while writing.

Revision history for this message
Nicholas Skaggs (nskaggs) wrote : Posted in a previous version of this proposal

One other thing, the proper syntax for a lambda function within an assert is;

self.assertThat(lambda: checkboxBtn, Eventually(NotEquals(None)))

In some cases there were a few that looked like this:

lambda: self.assertThat(checkboxBtn, Eventually(NotEquals(None)))

Revision history for this message
Nicholas Skaggs (nskaggs) wrote : Posted in a previous version of this proposal

This is equivalent

    def get_canonical_feed_labelvisual(self):
        itemList = self.select_many('LabelVisual', text = 'Canonical')
        for item in itemList:
            if item.text == "Canonical":
                return item

to this:

    def get_canonical_feed_labelvisual(self):
        itemList = self.app.select_many('LabelVisual', text = 'Canonical')
        index = -1
        for item in itemList:
            index += 1
            if item.text == "Canonical":
               return itemList[index]

See the difference? You can use item directly as it's equal to itemList[index].

Revision history for this message
Nicholas Skaggs (nskaggs) wrote :

Note this still requires some love, but I'm pushing into trunk for the sake of restoring a testsuite to the application so we can avoid regressions that have plagued us.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'TopicTab.qml'
2--- TopicTab.qml 2013-08-03 10:06:36 +0000
3+++ TopicTab.qml 2013-08-13 04:48:23 +0000
4@@ -7,6 +7,7 @@
5
6 Tab {
7 id: topictab
8+ objectName: topictab
9 // title: i18n.tr("test")
10
11 property int tag_id
12@@ -38,6 +39,7 @@
13 id: toolbar
14
15 back: ToolbarButton {
16+ objectName: "refreshbutton"
17 action: Action {
18 text: i18n.tr("Refresh")
19 iconSource: Qt.resolvedUrl("./icons_tmp/reload.svg")
20@@ -50,6 +52,7 @@
21 }
22
23 ToolbarButton {
24+ objectName: "listviewbutton"
25 action: Action {
26 text: i18n.tr("List view")
27 iconSource: Qt.resolvedUrl("./icons_tmp/view-fullscreen.svg")
28@@ -60,6 +63,7 @@
29 }
30
31 ToolbarButton {
32+ objectName: "addfeedbutton"
33 id: addReadsBtn
34 action: Action {
35 text: i18n.tr("Add reads")
36@@ -72,6 +76,7 @@
37 }
38
39 ToolbarButton {
40+ objectName: "edittopicbutton"
41 action: Action {
42 text: i18n.tr("Edit topics")
43 iconSource: Qt.resolvedUrl("./icons_tmp/edit.svg")
44
45=== modified file 'feeds/AppendFeedPage.qml'
46--- feeds/AppendFeedPage.qml 2013-08-02 19:00:56 +0000
47+++ feeds/AppendFeedPage.qml 2013-08-13 04:48:23 +0000
48@@ -9,7 +9,7 @@
49
50 Page {
51 id: appendFeedPage
52-
53+ objectName: "appendfeedpage"
54 title: "Append feed"
55 flickable: null
56 visible: false
57
58=== modified file 'feeds/ChooseTopicPage.qml'
59--- feeds/ChooseTopicPage.qml 2013-08-04 08:51:35 +0000
60+++ feeds/ChooseTopicPage.qml 2013-08-13 04:48:23 +0000
61@@ -8,7 +8,7 @@
62
63 Page {
64 id: chooseTopicPage
65-
66+ objectName: "choosetopicpage"
67 title: "Choose topic"
68 flickable: null
69 visible: false
70@@ -101,6 +101,7 @@
71 }
72
73 delegate: ListItem.Standard {
74+ objectName: "topicItem"
75 text: model.tagName
76
77 onClicked: {
78
79=== modified file 'feeds/EditFeed.qml'
80--- feeds/EditFeed.qml 2013-08-03 10:06:36 +0000
81+++ feeds/EditFeed.qml 2013-08-13 04:48:23 +0000
82@@ -8,7 +8,7 @@
83
84 Page {
85 id: editPage
86-
87+ objectName: "editfeedpage"
88 title: i18n.tr("Edit Feed")
89 flickable: null/*content*/
90 tools: ToolbarItems {
91@@ -27,6 +27,7 @@
92 Button
93 {
94 id: btnDelete
95+ objectName: "deleteButton"
96 text: i18n.tr("Delete")
97 gradient: UbuntuColors.orangeGradient
98 anchors.verticalCenter: parent.verticalCenter
99
100=== modified file 'feeds/ManageFeedsPage.qml'
101--- feeds/ManageFeedsPage.qml 2013-08-03 14:21:20 +0000
102+++ feeds/ManageFeedsPage.qml 2013-08-13 04:48:23 +0000
103@@ -8,6 +8,7 @@
104
105 Page {
106 id: editFeedsPageRoot
107+ objectName: "editfeedspage"
108 flickable: null
109 title: i18n.tr("Feeds")
110
111
112=== modified file 'feeds/TopicManagement.qml'
113--- feeds/TopicManagement.qml 2013-08-03 10:06:36 +0000
114+++ feeds/TopicManagement.qml 2013-08-13 04:48:23 +0000
115@@ -7,6 +7,7 @@
116 import "../databasemodule_v2.js" as DB
117
118 Page {
119+ objectName: "topicmanagement"
120 id: topicManagement
121
122 // width: units.gu(50)
123@@ -69,6 +70,7 @@
124
125 Item {
126 id: itemAddTopic
127+ objectName: "addTopic"
128 anchors{ left: parent.left; right: parent.right }
129 height: units.gu(8)
130
131
132=== modified file 'listview/ArticleListPage.qml'
133--- listview/ArticleListPage.qml 2013-07-29 18:31:05 +0000
134+++ listview/ArticleListPage.qml 2013-08-13 04:48:23 +0000
135@@ -8,7 +8,7 @@
136 import "../databasemodule_v2.js" as DB
137
138 Page {
139-
140+ objectName: "articlelistpage"
141 signal articleSelected(var data) // mb id.
142 property var updateData: null
143
144
145=== modified file 'listview/FeedListPage.qml'
146--- listview/FeedListPage.qml 2013-08-07 18:09:21 +0000
147+++ listview/FeedListPage.qml 2013-08-13 04:48:23 +0000
148@@ -10,7 +10,7 @@
149
150 Page {
151 id: pageItself
152-
153+ objectName: "feedlistpage"
154 property var updatingFeed: null
155 property bool isDirty: false
156
157
158=== removed directory 'tests/autopilot/ubuntu_rssreader_app/emulators'
159=== added file 'tests/autopilot/ubuntu_rssreader_app/emulators.py'
160--- tests/autopilot/ubuntu_rssreader_app/emulators.py 1970-01-01 00:00:00 +0000
161+++ tests/autopilot/ubuntu_rssreader_app/emulators.py 2013-08-13 04:48:23 +0000
162@@ -0,0 +1,123 @@
163+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
164+#
165+# Copyright (C) 2013 Canonical Ltd.
166+#
167+# This program is free software; you can redistribute it and/or modify
168+# it under the terms of the GNU Lesser General Public License as published by
169+# the Free Software Foundation; version 3.
170+#
171+# This program is distributed in the hope that it will be useful,
172+# but WITHOUT ANY WARRANTY; without even the implied warranty of
173+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
174+# GNU Lesser General Public License for more details.
175+#
176+# You should have received a copy of the GNU Lesser General Public License
177+# along with this program. If not, see <http://www.gnu.org/licenses/>.
178+
179+from ubuntuuitoolkit import emulators as toolkit_emulators
180+
181+class MainView(toolkit_emulators.MainView):
182+
183+ #ideally this should be converted to the sdk and use object name not text names
184+ #see https://bugs.launchpad.net/ubuntu-ui-toolkit/+bug/1205144
185+ def run_action(self, popover, name):
186+ actions = popover.select_many("Empty")
187+ requested = None
188+ for action in actions:
189+ if action.text == name:
190+ requested = action
191+ self.pointing_device.click_object(requested)
192+
193+ def get_action_popover(self):
194+ # Returns all instances, but with current one as first index
195+ return self.select_many("ActionSelectionPopover")[0]
196+
197+ def get_append_page(self):
198+ return self.select_single("AppendFeedPage", objectName = "appendfeedpage")
199+
200+ def get_feed_management_page(self):
201+ return self.select_single("TopicManagement", objectName = "topicmanagement")
202+
203+ def get_edit_feed_page(self):
204+ return self.select_single("EditFeed", objectName = "editfeedpage")
205+
206+ def get_checkbox_button(self):
207+ return self.select_single("CheckBox", objectName = "feedCheckbox")
208+
209+ def get_delete_button(self):
210+ return self.select_single("Button", objectName = "deleteButton")
211+
212+ def get_next_button(self):
213+ return self.select_single("Button", objectName = "nextButton")
214+
215+ def get_append_feed_input_box(self):
216+ return self.select_single("TextField", objectName = "tfFeedUrl")
217+
218+ def get_new_topic_input_box(self):
219+ return self.select_single("TextField", objectName = "New topic")
220+
221+ def get_topics_page(self):
222+ return self.select_single("ChooseTopicPage", objectName = "choosetopicpage")
223+
224+ def get_topics(self):
225+ return self.select_single("QQuickListView", objectName = "topiclist")
226+
227+ def get_manage_topics_page(self):
228+ return self.select_single("ManageTopicsPage")
229+
230+ def get_canonical_topic(self):
231+ itemList = self.select_many("LabelVisual", text = "CanonicalTopic")
232+ for item in itemList:
233+ if item.text == "CanonicalTopic":
234+ return item
235+
236+ def get_canonical_feed_labelvisual(self):
237+ itemList = self.select_many("LabelVisual", text = "Canonical")
238+ for item in itemList:
239+ if item.text == "Canonical":
240+ return item
241+
242+ def get_feeds(self):
243+ return self.select_many("Standard", objectName = "FeedListItem")
244+
245+ def get_canonical_feed(self):
246+ itemList = self.get_feeds()
247+ for item in itemList:
248+ if item.text == "Canonical":
249+ return item
250+
251+ def get_header(self):
252+ return self.select_many("Header")
253+
254+ def get_all_feeds(self):
255+ return self.select_single("Subtitled", text = "All articles")
256+
257+ def get_refresh_button(self):
258+ return self.select_single("AbstractButton", objectName = "refreshbutton")
259+
260+ def get_list_view_button(self):
261+ return self.select_single("AbstractButton", objectName = "listviewbutton")
262+
263+ def get_add_feed_button(self):
264+ return self.select_single("AbstractButton", objectName = "addfeedbutton")
265+
266+ def get_edit_topic_button(self):
267+ return self.select_single("AbstractButton", objectName = "edittopicbutton")
268+
269+ def get_canonical_topic_labelvisual(self):
270+ itemList = self.select_many("LabelVisual", text = "CanonicalTopic")
271+ for item in itemList:
272+ if item.text == "CanonicalTopic":
273+ return item
274+
275+ def get_canonical_topic_TopicComponent(self):
276+ itemList = self.select_many("TopicComponent", topicName= "CanonicalTopic")
277+ for item in itemList:
278+ if item.topicName == "CanonicalTopic":
279+ return item
280+
281+ def get_canonical_feed_FeedComponent(self):
282+ return self.select_single("FeedComponent", text = "Canonical")
283+
284+ def get_add_a_topic(self):
285+ return self.select_single("QQuickItem", objectName = "addTopic")
286
287=== removed file 'tests/autopilot/ubuntu_rssreader_app/emulators/__init__.py'
288--- tests/autopilot/ubuntu_rssreader_app/emulators/__init__.py 2013-05-31 12:59:55 +0000
289+++ tests/autopilot/ubuntu_rssreader_app/emulators/__init__.py 1970-01-01 00:00:00 +0000
290@@ -1,6 +0,0 @@
291-# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
292-# Copyright 2013 Canonical
293-#
294-# This program is free software: you can redistribute it and/or modify it
295-# under the terms of the GNU General Public License version 3, as published
296-# by the Free Software Foundation.
297
298=== removed file 'tests/autopilot/ubuntu_rssreader_app/emulators/main_window.py'
299--- tests/autopilot/ubuntu_rssreader_app/emulators/main_window.py 2013-08-03 17:15:11 +0000
300+++ tests/autopilot/ubuntu_rssreader_app/emulators/main_window.py 1970-01-01 00:00:00 +0000
301@@ -1,64 +0,0 @@
302-# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
303-# Copyright 2013 Canonical
304-#
305-# This program is free software: you can redistribute it and/or modify it
306-# under the terms of the GNU General Public License version 3, as published
307-# by the Free Software Foundation.
308-
309-"""Rss Reader app autopilot emulators."""
310-
311-
312-class MainWindow(object):
313- """An emulator class that makes it easy to interact with the
314- rssreader-app.
315-
316- """
317- def __init__(self, app):
318- self.app = app
319-
320- def get_action_popover(self):
321- # Returns all instances, but with current one as first index
322- return self.app.select_many("ActionSelectionPopover")[0]
323-
324- def get_append_feed_input_box(self):
325- return self.app.select_single("TextField", objectName = "tfFeedUrl")
326-
327- def get_new_topic_input_box(self):
328- return self.app.select_single("TextField", objectName = "New topic")
329-
330- def get_topics(self):
331- return self.app.select_single('QQuickListView', objectName = 'topiclist')
332-
333- def get_manage_topics_page(self):
334- return self.app.select_single('ManageTopicsPage')
335-
336- def get_canonical_topic(self):
337- itemList = self.app.select_many('LabelVisual', text = 'CanonicalTopic')
338- index = -1
339- for item in itemList:
340- index += 1
341- if item.text == "CanonicalTopic":
342- return itemList[index]
343-
344-## def get_canonical_feed_labelvisual(self):
345-## return self.app.select_single('LabelVisual', text = 'Canonical')
346-
347- def get_canonical_feed_labelvisual(self):
348- itemList = self.app.select_many('LabelVisual', text = 'Canonical')
349- index = -1
350- for item in itemList:
351- index += 1
352- if item.text == "Canonical":
353- return itemList[index]
354-
355-
356- def get_canonical_feed(self):
357- itemList = self.app.select_many('Standard', objectName = 'FeedListItem')
358- index = -1
359- for item in itemList:
360- index += 1
361- if item.text == "Canonical":
362- return itemList[index]
363-
364- def get_header(self):
365- return self.app.select_many("Header")
366
367=== removed file 'tests/autopilot/ubuntu_rssreader_app/emulators/ubuntusdk.py'
368--- tests/autopilot/ubuntu_rssreader_app/emulators/ubuntusdk.py 2013-08-01 20:01:41 +0000
369+++ tests/autopilot/ubuntu_rssreader_app/emulators/ubuntusdk.py 1970-01-01 00:00:00 +0000
370@@ -1,153 +0,0 @@
371-# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
372-#
373-# Copyright (C) 2013 Canonical Ltd
374-#
375-# This program is free software: you can redistribute it and/or modify
376-# it under the terms of the GNU General Public License version 3 as
377-# published by the Free Software Foundation.
378-#
379-# This program is distributed in the hope that it will be useful,
380-# but WITHOUT ANY WARRANTY; without even the implied warranty of
381-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
382-# GNU General Public License for more details.
383-#
384-# You should have received a copy of the GNU General Public License
385-# along with this program. If not, see <http://www.gnu.org/licenses/>.
386-#
387-# Authored by: Nicholas Skaggs <nicholas.skaggs@canonical.com>
388-
389-
390-class ubuntusdk(object):
391- """An emulator class that makes it easy to interact with the ubuntu sdk
392- applications."""
393-
394- def __init__(self, autopilot, app):
395- self.app = app
396- self.autopilot = autopilot
397-
398- def get_qml_view(self):
399- """Get the main QML view"""
400- return self.app.select_single("QQuickView")
401-
402- def get_object(self, typeName, name):
403- """Get a specific object"""
404- return self.app.select_single(typeName, objectName=name)
405-
406- def get_objects(self, typeName, name):
407- """Get more than one object"""
408- return self.app.select_many(typeName, objectName=name)
409-
410- def switch_to_tab(self, tab):
411- """Switch to the specified tab number"""
412- tabs = self.get_tabs()
413- currentTab = tabs.selectedTabIndex
414-
415- #perform operations until tab == currentTab
416- while tab != currentTab:
417- if tab > currentTab:
418- self._previous_tab()
419- if tab < currentTab:
420- self._next_tab()
421- currentTab = tabs.selectedTabIndex
422-
423- def toggle_toolbar(self):
424- """Toggle the toolbar between revealed and hidden"""
425- #check and see if the toolbar is open or not
426- if self.get_toolbar().opened:
427- self.hide_toolbar()
428- else:
429- self.open_toolbar()
430-
431- def get_toolbar(self):
432- """Returns the toolbar in the main events view."""
433- return self.app.select_single("Toolbar")
434-
435- def get_toolbar_button(self, buttonLabel):
436- """Returns the toolbar button at position index"""
437- toolbar = self.get_toolbar()
438- if not toolbar.opened:
439- self.open_toolbar()
440- row = toolbar.select_single("ToolbarItems")
441- buttonList = row.select_many("ActionItem")
442- for button in buttonList:
443- if button.text == buttonLabel:
444- return button
445-
446- def click_toolbar_button(self, buttonLabel):
447- """Clicks the toolbar button with buttonLabel"""
448- #The toolbar button is assumed to be the following format
449- #ToolbarActions {
450- # Action {
451- # objectName: "name"
452- # text: value
453- button = self.get_toolbar_button(buttonLabel)
454- self.autopilot.pointing_device.click_object(button)
455-
456- def open_toolbar(self):
457- """Open the toolbar"""
458- qmlView = self.get_qml_view()
459-
460- lineX = qmlView.x + qmlView.width * 0.50
461- startY = qmlView.y + qmlView.height - 1
462- stopY = qmlView.y + qmlView.height * 0.95
463-
464- self.autopilot.pointing_device.drag(lineX, startY, lineX, stopY)
465-
466- def hide_toolbar(self):
467- """Hide the toolbar"""
468- qmlView = self.get_qml_view()
469-
470- lineX = qmlView.x + qmlView.width * 0.50
471- startY = qmlView.y + qmlView.height * 0.95
472- stopY = qmlView.y + qmlView.height - 1
473-
474- self.autopilot.pointing_device.drag(lineX, startY, lineX, stopY)
475-
476- def set_popup_value(self, popover, button, value):
477- """Changes the given popover selector to the request value
478- At the moment this only works for values that are currently visible. To
479- access the remaining items, a help method to drag and recheck is
480- needed."""
481- #The popover is assumed to be the following format
482- # Popover {
483- # Column {
484- # ListView {
485- # delegate: Standard {
486- # objectName: "name"
487- # text: value
488-
489- self.autopilot.pointing_device.click_object(button)
490- # we'll get all matching objects, incase the popover is reused between
491- # buttons
492- itemList = lambda: self.get_objects("Standard", popover)
493-
494- for item in itemList():
495- if item.get_properties()['text'] == value:
496- self.autopilot.pointing_device.click_object(item)
497-
498- def get_tabs(self):
499- """Return all tabs"""
500- return self.get_object("Tabs", "rootTabs")
501-
502- def _previous_tab(self):
503- """Switch to the previous tab"""
504- qmlView = self.get_qml_view()
505-
506- startX = qmlView.x + qmlView.width * 0.35
507- stopX = qmlView.x + qmlView.width * 0.50
508- lineY = qmlView.y + qmlView.height * 0.05
509-
510- self.autopilot.pointing_device.drag(startX, lineY, stopX, lineY)
511- self.autopilot.pointing_device.click()
512- self.autopilot.pointing_device.click()
513-
514- def _next_tab(self):
515- """Switch to the next tab"""
516- qmlView = self.get_qml_view()
517-
518- startX = qmlView.x + qmlView.width * 0.50
519- stopX = qmlView.x + qmlView.width * 0.35
520- lineY = qmlView.y + qmlView.height * 0.05
521-
522- self.autopilot.pointing_device.drag(startX, lineY, stopX, lineY)
523- self.autopilot.pointing_device.click()
524
525=== modified file 'tests/autopilot/ubuntu_rssreader_app/tests/__init__.py'
526--- tests/autopilot/ubuntu_rssreader_app/tests/__init__.py 2013-08-01 19:47:14 +0000
527+++ tests/autopilot/ubuntu_rssreader_app/tests/__init__.py 2013-08-13 04:48:23 +0000
528@@ -1,29 +1,40 @@
529 # -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
530-# Copyright 2013 Canonical
531-#
532-# This program is free software: you can redistribute it and/or modify it
533-# under the terms of the GNU General Public License version 3, as published
534-# by the Free Software Foundation.
535-
536-"""Rssreader app autopilot tests."""
537+#
538+# Copyright (C) 2013 Canonical Ltd
539+#
540+# This program is free software: you can redistribute it and/or modify
541+# it under the terms of the GNU General Public License version 3 as
542+# published by the Free Software Foundation.
543+#
544+# This program is distributed in the hope that it will be useful,
545+# but WITHOUT ANY WARRANTY; without even the implied warranty of
546+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
547+# GNU General Public License for more details.
548+#
549+# You should have received a copy of the GNU General Public License
550+# along with this program. If not, see <http://www.gnu.org/licenses/>.
551+#
552+# Authored by: Renato Araujo Oliveira Filho <renato@canonical.com>
553+
554+
555+"""rssreader-app autopilot tests."""
556
557 import os.path
558+import os
559
560 from autopilot.input import Mouse, Touch, Pointer
561 from autopilot.platform import model
562 from autopilot.testcase import AutopilotTestCase
563-
564-from time import sleep
565-
566-from ubuntu_rssreader_app.emulators.main_window import MainWindow
567-from ubuntu_rssreader_app.emulators.ubuntusdk import ubuntusdk
568-
569-
570-
571-class RssreaderTestCase(AutopilotTestCase):
572+from autopilot.matchers import Eventually
573+from testtools.matchers import GreaterThan
574+
575+from ubuntuuitoolkit import emulators as toolkit_emulators
576+from ubuntu_rssreader_app import emulators
577+
578+class RssReaderAppTestCase(AutopilotTestCase):
579
580 """A common test case class that provides several useful methods for
581- rssreader-app tests.
582+ calendar-app tests.
583
584 """
585 if model() == 'Desktop':
586@@ -35,7 +46,7 @@
587
588 def setUp(self):
589 self.pointing_device = Pointer(self.input_device_class.create())
590- super(RssreaderTestCase, self).setUp()
591+ super(RssReaderAppTestCase, self).setUp()
592 if os.path.exists(self.local_location):
593 self.launch_test_local()
594 else:
595@@ -45,26 +56,18 @@
596 self.app = self.launch_test_application(
597 "qmlscene",
598 self.local_location,
599- app_type='qt')
600+ app_type='qt',
601+ emulator_base=toolkit_emulators.UbuntuUIToolkitEmulatorBase)
602
603 def launch_test_installed(self):
604 self.app = self.launch_test_application(
605 "qmlscene",
606 "/usr/share/ubuntu-rssreader-app/ubuntu-rssreader-app.qml",
607- "--desktop_file_hint="
608- "/usr/share/applications/ubuntu-rssreader-app.desktop",
609- app_type='qt')
610-
611- def tap_item(self, item):
612- self.pointing_device.move_to_object(item)
613- self.pointing_device.press()
614- sleep(1)
615- self.pointing_device.release()
616-
617- @property
618- def main_window(self):
619- return MainWindow(self.app)
620-
621- @property
622- def ubuntusdk(self):
623- return ubuntusdk(self, self.app)
624+ "--desktop_file_hint=/usr/share/applications/"
625+ "ubuntu-rssreader-app.desktop",
626+ app_type='qt',
627+ emulator_base=toolkit_emulators.UbuntuUIToolkitEmulatorBase)
628+
629+ @property
630+ def main_view(self):
631+ return self.app.select_single(emulators.MainView)
632
633=== modified file 'tests/autopilot/ubuntu_rssreader_app/tests/test_rssreader.py'
634--- tests/autopilot/ubuntu_rssreader_app/tests/test_rssreader.py 2013-08-03 17:15:11 +0000
635+++ tests/autopilot/ubuntu_rssreader_app/tests/test_rssreader.py 2013-08-13 04:48:23 +0000
636@@ -10,6 +10,7 @@
637 from __future__ import absolute_import
638
639 import tempfile
640+import unittest
641
642 import mock
643 import os
644@@ -21,139 +22,290 @@
645 from testtools.matchers import NotEquals
646
647 from autopilot.introspection.dbus import StateNotFoundError
648-from ubuntu_rssreader_app.tests import RssreaderTestCase
649+from ubuntu_rssreader_app.tests import RssReaderAppTestCase
650
651 from time import sleep
652
653-class TestMainWindow(RssreaderTestCase):
654+class TestMainWindow(RssReaderAppTestCase):
655
656 def setUp(self):
657 super(TestMainWindow, self).setUp()
658- self.assertThat(
659- self.ubuntusdk.get_qml_view().visible, Eventually(Equals(True)))
660-
661-
662- def test_add_remove_feed_and_topic(self):
663- #toggle toolbar
664- self.ubuntusdk.toggle_toolbar()
665+ self.assertThat(self.main_view.visible, Eventually(Equals(True)))
666+
667+ def _add_feed_and_topic(self):
668+ """test add feed and topic"""
669+
670+ #verify we are on the first page
671+ shortsPage = self.main_view.switch_to_tab_by_index(0)
672+ self.assertThat(lambda: shortsPage.visible, Eventually(Equals(True)))
673+
674+ #open toolbar
675+ toolbar = self.main_view.open_toolbar()
676
677 #click on add reads toolbar button
678- self.ubuntusdk.click_toolbar_button('Add reads')
679+ toolbar.click_button("addreadsbutton")
680
681 #click on add feeds popover action
682- addReadsPopover = self.main_window.get_action_popover()
683- self._run_action(addReadsPopover, '+ Add feeds')
684+ addReadsPopover = self.main_view.get_action_popover()
685+ self.main_view.run_action(addReadsPopover, "+ Add feeds")
686
687 #verify Append Feed page is open
688- header = self.main_window.get_header()[0]
689- self.assertThat(header.title, Eventually(Equals("Append feed")))
690+ appendpage = self.main_view.get_append_page()
691+ self.assertThat(lambda: appendpage.visible, Eventually(Equals(True)))
692
693 #type feed in input field
694- new_Feed_Url = self.main_window.get_append_feed_input_box()
695- self.assertThat(new_Feed_Url, NotEquals(None))
696- self.pointing_device.click_object(new_Feed_Url)
697- self.keyboard.type("http://www.canonical.com/rss.xml")
698- self.keyboard.type("\n")
699- self.assertThat(new_Feed_Url.text, Eventually(Equals("http://www.canonical.com/rss.xml")))
700- #---> TODO fix this
701- sleep(1)
702+ self._input_new_feed("http://www.canonical.com/rss.xml")
703
704 #check that feed is updated, not empty
705- canonicalFeed = self.main_window.get_canonical_feed_labelvisual()
706- self.assertThat(canonicalFeed.text, Eventually(Equals("Canonical")))
707+ canonicalFeed = self.main_view.get_canonical_feed_labelvisual()
708+ self.assertThat(lambda: canonicalFeed.text, Eventually(Equals("Canonical")))
709
710 #click on checkbox to confirm feed
711- checkboxBtn = self.ubuntusdk.get_object('CheckBox', "feedCheckbox")
712- lambda: self.assertThat(checkboxBtn, Eventually(NotEquals(None)))
713+ checkboxBtn = self.main_view.get_checkbox_button()
714+ self.assertThat(lambda: checkboxBtn, Eventually(NotEquals(None)))
715 self.pointing_device.click_object(checkboxBtn)
716- self.assertThat(checkboxBtn.checked, Eventually(Equals(True)))
717+ self.assertThat(lambda: checkboxBtn.checked, Eventually(Equals(True)))
718
719 #click on Next button
720- nextButton = self.ubuntusdk.get_object("Button", "nextButton")
721- lambda: self.assertThat(nextButton, Eventually(NotEquals(None)))
722+ nextButton = self.main_view.get_next_button()
723+ self.assertThat(lambda: nextButton, Eventually(NotEquals(None)))
724 self.pointing_device.click_object(nextButton)
725- header = self.main_window.get_header()[0]
726- self.assertThat(header.title, Eventually(Equals("Choose topic")))
727+
728+ chossetopicpage = self.main_view.get_topics_page()
729+ self.assertThat(lambda: chossetopicpage.visible, Eventually(Equals(True)))
730
731 #add a new topic
732- new_Topic_Url = self.main_window.get_new_topic_input_box()
733- self.assertThat(new_Topic_Url, NotEquals(None))
734- self.pointing_device.click_object(new_Topic_Url)
735- self.keyboard.type("CanonicalTopic")
736- self.keyboard.type("\n")
737+ self._input_new_topic("CanonicalTopic")
738
739 #select canonical topic
740- canonicalTopic = self.main_window.get_canonical_topic()
741- self.assertThat(canonicalTopic, NotEquals(None))
742+ canonicalTopic = self.main_view.get_canonical_topic_labelvisual()
743+ self.assertThat(lambda: canonicalTopic, Eventually(NotEquals(None)))
744 self.pointing_device.click_object(canonicalTopic)
745
746- #remove added Canonical topic
747- self._remove_topic()
748-
749- #check that it's gone
750- canonicalTopic = self.main_window.get_canonical_topic()
751- #---> TODO fix this
752- sleep(1)
753- self.assertThat(canonicalTopic.text, NotEquals("CanonicalTopic"))
754-
755- #remove added Canonical feed
756- self._remove_feed()
757+ #just for timing purposes
758+ self.assertThat(lambda: canonicalTopic.text, Eventually(Equals("CanonicalTopic")))
759+
760+ #verify we are on the first page
761+ shortsPage = self.main_view.switch_to_tab_by_index(0)
762+ self.assertThat(lambda: shortsPage.visible, Eventually(Equals(True)))
763
764 def _remove_feed(self):
765- #toggle toolbar
766- self.ubuntusdk.toggle_toolbar()
767- #click on back toolbar button
768- header = self.main_window.get_header()[0]
769- self.assertThat(header.title, Eventually(Equals("Topics")))
770- self.ubuntusdk.click_toolbar_button('Back')
771-
772- header = self.main_window.get_header()[0]
773- self.assertThat(header.title, Eventually(Equals("Feeds")))
774+ #verify we are on the first page
775+ shortsPage = self.main_view.switch_to_tab_by_index(0)
776+ self.assertThat(lambda: shortsPage.visible, Eventually(Equals(True)))
777+
778+ #open toolbar
779+ toolbar = self.main_view.open_toolbar()
780+
781+ #click on back toolbar Button
782+ toolbar.click_button("edittopicsbutton")
783+
784+ #verify we are on the Management page
785+ feedlistpage = self.main_view.get_feed_management_page()
786+ self.assertThat(feedlistpage.visible, Eventually(Equals(True)))
787+
788+ #select canonical topic
789+ self._get_canonical_topic()
790
791 #select canonical feed
792- canonicalFeed = self.main_window.get_canonical_feed()
793- self.assertThat(canonicalFeed, NotEquals(None))
794- self.pointing_device.click_object(canonicalFeed, press_duration=2)
795-
796- #click on Remove popover action
797- removeFeedPopover = self.main_window.get_action_popover()
798- self._run_action(removeFeedPopover, 'Remove')
799+ canonicalFeed = self.main_view.get_canonical_feed_FeedComponent()
800+ self.assertThat(lambda: canonicalFeed, Eventually(NotEquals(None)))
801+
802+ self.pointing_device.click_object(canonicalFeed)
803+
804+ #verify we are on the Edit Feed page
805+ editFeedPage = self.main_view.get_edit_feed_page()
806+ self.assertThat(editFeedPage.visible, Eventually(Equals(True)))
807+
808+ #open toolbar
809+ self.main_view.open_toolbar()
810+
811+ #press delete button
812+ deleteButton = self.main_view.get_delete_button()
813+ self.assertThat(lambda: deleteButton, Eventually(NotEquals(None)))
814+ self.pointing_device.click_object(deleteButton)
815+
816+ #verify we are on the Management page
817+ feedlistpage = self.main_view.get_feed_management_page()
818+ self.assertThat(feedlistpage.visible, Eventually(Equals(True)))
819+
820+ #select canonical topic
821+ canonicalTopic = self.main_view.get_canonical_topic_labelvisual()
822+ self.assertThat(lambda: canonicalTopic, Eventually(NotEquals(None)))
823+
824+ #check feed has been removed
825+ canonicalFeed = self.main_view.get_canonical_feed_FeedComponent()
826+ self.assertThat(lambda: canonicalFeed, Eventually(Equals(None)))
827
828 def _remove_topic(self):
829- #toggle toolbar
830- self.ubuntusdk.toggle_toolbar()
831-
832- #click on edit topics toolbar button
833- self.ubuntusdk.click_toolbar_button('Edit topics')
834- header = self.main_window.get_header()[0]
835- self.assertThat(header.title, Eventually(Equals("Feeds")))
836-
837- self.ubuntusdk.click_toolbar_button('Topics')
838- header = self.main_window.get_header()[0]
839- self.assertThat(header.title, Eventually(Equals("Topics")))
840-
841- #select and swipe canonical topic
842- canonicalTopic = self.main_window.get_canonical_topic()
843- self.assertThat(canonicalTopic, NotEquals(None))
844-
845- qmlView = self.ubuntusdk.get_qml_view()
846- topicsPage = self.main_window.get_manage_topics_page()
847-
848+ #this been quasi converted to the sdk, but does not work as-is
849+ #see https://bugs.launchpad.net/ubuntu-rssreader-app/+bug/1211631
850+
851+ #verify we are on the first page
852+ shortsPage = self.main_view.switch_to_tab_by_index(0)
853+ self.assertThat(lambda: shortsPage.visible, Eventually(Equals(True)))
854+
855+ #open toolbar
856+ toolbar = self.main_view.open_toolbar()
857+
858+ #click on back toolbar Button
859+ toolbar.click_button("edittopicsbutton")
860+
861+ #verify we are on the Management page
862+ feedlistpage = self.main_view.get_feed_management_page()
863+ self.assertThat(feedlistpage.visible, Eventually(Equals(True)))
864+
865+ #select canonical topic
866+ canonicalTopic = self._get_canonical_topic()
867+
868+ topicsPage = self.main_view.get_manage_topics_page()
869+ self.assertThat(topicsPage, Eventually(NotEquals(None)))
870+
871+ addATopicItem = self.main_view.get_add_a_topic()
872+ self.assertThat(lambda: addATopic, Eventually(NotEquals(None)))
873+
874+ #swipe to delete canonical topic
875 #we have to consider the top tab offset, then create a swipe operation across the width of the page
876 startX = int(topicsPage.x + topicsPage.width * 0.20)
877 stopX = int(topicsPage.x + topicsPage.width * 0.80)
878- tabHeightOffset = qmlView.height - topicsPage.height
879- lineY = int(qmlView.y + canonicalTopic.y + tabHeightOffset)
880+ tabHeightOffset = qmlView.height - topicsPage.height + addATopicItem.height
881+ lineY = int(qmlView.y + canonicalTopic.y + tabHeightOffset)
882
883 #swipe to remove the topic
884 self.pointing_device.move(startX, lineY)
885 self.pointing_device.drag(startX, lineY, stopX, lineY)
886
887- def _run_action(self, popover, name):
888- actions = popover.select_many('Empty')
889- requested = None
890- for action in actions:
891- if action.text == name:
892- requested = action
893- self.pointing_device.click_object(requested)
894-
895+ #check that it is gone
896+ canonicalTopic = self.main_view.get_canonical_topic()
897+ self.assertThat(lambda: canonicalTopic.visible, Eventually(Equals(False)))
898+
899+ def _input_new_feed(self, rssFeed):
900+ inputField = self.main_view.get_append_feed_input_box()
901+ return self._safe_enter_text(inputField, rssFeed)
902+
903+ def _input_new_topic(self, topic):
904+ inputField = self.main_view.get_new_topic_input_box()
905+ return self._safe_enter_text(inputField, topic)
906+
907+ def _safe_enter_text(self, inputField, text, timeout = 10):
908+ self.assertThat(lambda: inputField.visible, Eventually(Equals(True)))
909+ #poll clicking for focus for lack of better method, due to screen switching animation
910+ #is there a property we can use instead?
911+ poll = 0
912+ while inputField.focus != True and poll < timeout:
913+ self.pointing_device.click_object(inputField)
914+ sleep(1)
915+ poll += 1
916+ self.keyboard.type(text)
917+ self.assertThat(inputField.text, Eventually(Equals(text)))
918+ self.keyboard.press_and_release("Enter")
919+ return inputField
920+
921+ def _get_canonical_topic(self, timeout = 10):
922+ canonicalTopic = self.main_view.get_canonical_topic_TopicComponent()
923+ self.assertThat(lambda: canonicalTopic, Eventually(NotEquals(None)))
924+ self.pointing_device.click_object(canonicalTopic)
925+
926+ poll = 0
927+ while canonicalTopic.isExpended == False and poll < timeout:
928+ self.pointing_device.click_object(canonicalTopic)
929+ sleep(1)
930+ poll += 1
931+ return canonicalTopic
932+
933+
934+ def test_add_remove_feed_and_topic(self):
935+ """ test add and remove feed and topic"""
936+
937+ #add topic and feed
938+ self._add_feed_and_topic()
939+
940+ #remove added Canonical topic
941+ #12 Aug 2013, removing topic broken for now
942+ #test commented until fixed, see https://bugs.launchpad.net/ubuntu-rssreader-app/+bug/1211631
943+ ## self._remove_topic()
944+
945+ #remove added Canonical feed
946+ self._remove_feed()
947+
948+ @unittest.skip("Topic page broken")
949+ def test_view_feeds(self):
950+ """test view feeds"""
951+
952+ #this has NOT BEEN converted to the sdk, and needs to be done before activating
953+
954+ #verify we are on the first page
955+ self.main_view.switch_to_tab_by_index(0)
956+ self.assertThat(lambda: shortsPage.visible, Eventually(Equals(True)))
957+
958+ #-----> view all news:
959+ #open toolbar
960+ self.main_view.open_toolbar()
961+
962+ #click on add reads toolbar button
963+ self.main_view.click_toolbar_button("List view")
964+
965+ #verify we are on the Feeds page
966+ feedlistpage = self.main_view.get_object("FeedListPage", "feedlistpage")
967+ self.assertThat(lambda: feedlistpage.visible, Eventually(Equals(True)))
968+
969+ #select All articles
970+ allFeeds = self.main_view.get_all_feeds()
971+ self.assertThat(allFeeds, NotEquals("None"))
972+ self.pointing_device.click_object(allFeeds )
973+
974+ #verify we are on the All articles page
975+ articlelistpage = self.main_view.get_object("ArticleListPage", "articlelistpage")
976+ self.assertThat(lambda: articlelistpage.visible, Eventually(Equals(True)))
977+
978+ #toggle toolbar
979+ self.main_view.open_toolbar()
980+ self.assertThat(self.main_view.get_toolbar().opened, Eventually(Equals(True)))
981+
982+ #click on back toolbar button
983+ self.main_view.click_toolbar_button("Back")
984+
985+ #verify we are on the Feeds page
986+ feedlistpage = self.main_view.get_object("FeedListPage", "feedlistpage")
987+ self.assertThat(feedlistpage.title, Eventually(Equals("Feeds")))
988+
989+ #-----> view individual feed:
990+ #add topic and feed
991+ self._add_feed_and_topic()
992+
993+ #select Canonical feed
994+ canonicalFeed = self.main_view.get_canonical_feed_labelvisual()
995+ self.assertThat(canonicalFeed, NotEquals(None))
996+ self.pointing_device.click_object(canonicalFeed)
997+
998+ #verify we are on the Canonical page
999+ header = self.main_view.get_header()[0]
1000+ self.assertThat(header.title, Eventually(Equals("Canonical")))
1001+
1002+ #toggle toolbar
1003+ self.main_view.open_toolbar()
1004+ self.assertThat(self.main_view.get_toolbar().opened, Eventually(Equals(True)))
1005+
1006+ #click on back toolbar button
1007+ self.main_view.click_toolbar_button("Back")
1008+
1009+ #verify we are on the Feeds page
1010+ feedlistpage = self.main_view.get_object("FeedListPage", "feedlistpage")
1011+ self.assertThat(feedlistpage.title, Eventually(Equals("Feeds")))
1012+
1013+ #toggle toolbar
1014+ self.main_view.open_toolbar()
1015+ self.assertThat(self.main_view.get_toolbar().opened, Eventually(Equals(True)))
1016+
1017+ #click on back toolbar button
1018+ self.main_view.click_toolbar_button("Shorts")
1019+
1020+ #verify we are on the Shorts page
1021+ pageName = self.main_view.get_object("Tab", "Tab0")
1022+ self.assertThat(pageName.title, Eventually(Equals("Shorts")))
1023+
1024+ #remove added Canonical topic
1025+ self._remove_topic()
1026+
1027+ #remove added Canonical feed
1028+ self._remove_feed()
1029
1030=== modified file 'ubuntu-rssreader-app.qml'
1031--- ubuntu-rssreader-app.qml 2013-08-08 15:15:39 +0000
1032+++ ubuntu-rssreader-app.qml 2013-08-13 04:48:23 +0000
1033@@ -131,6 +131,7 @@
1034
1035 ToolbarButton {
1036 id: addReadsBtn
1037+ objectName: "addreadsbutton"
1038 action: Action {
1039 text: i18n.tr("Add reads")
1040 iconSource: Qt.resolvedUrl("./icons_tmp/add.svg")
1041@@ -142,6 +143,7 @@
1042 }
1043
1044 ToolbarButton {
1045+ objectName: "edittopicsbutton"
1046 action: Action {
1047 text: i18n.tr("Edit topics")
1048 iconSource: Qt.resolvedUrl("./icons_tmp/edit.svg")
1049@@ -336,6 +338,7 @@
1050
1051 ActionSelectionPopover {
1052 id: addReadsPopover
1053+ objectName: addreadspopover
1054
1055 actions: ActionList {
1056 id: popoverActionsList

Subscribers

People subscribed via source and target branches