Merge lp:~cellsoftware/telegram-app/autopilotTest-4 into lp:telegram-app
- autopilotTest-4
- Merge into telegram
Status: | Merged |
---|---|
Approved by: | Jin |
Approved revision: | 250 |
Merged at revision: | 247 |
Proposed branch: | lp:~cellsoftware/telegram-app/autopilotTest-4 |
Merge into: | lp:telegram-app |
Diff against target: |
3409 lines (+2757/-37) 35 files modified
README.md (+191/-35) buildScripts/click.sh (+10/-0) setup.sh (+17/-1) telegram/app/qml/AccountContactsPage.qml (+5/-1) telegram/app/qml/AccountDialogList.qml (+2/-0) telegram/app/qml/AccountDialogPage.qml (+4/-0) telegram/app/qml/AccountMessageList.qml (+2/-0) telegram/app/qml/AccountMessageMedia.qml (+1/-0) telegram/app/qml/AccountPage.qml (+4/-0) telegram/app/qml/AccountSendMessage.qml (+7/-0) telegram/app/qml/AccountSettings.qml (+4/-0) telegram/app/qml/AuthCountriesPage.qml (+2/-0) telegram/app/qml/AuthNumberPage.qml (+3/-0) telegram/app/qml/ProfilePage.qml (+14/-0) telegram/app/qml/components/AccountPanel.qml (+4/-0) telegram/app/qml/components/AttachPanel.qml (+4/-0) telegram/app/qml/components/MediaImport.qml (+2/-0) telegram/app/qml/components/MessageStatus.qml (+1/-0) telegram/app/qml/components/MessagesListItem.qml (+3/-0) telegram/app/qml/telegram.qml (+1/-0) telegram/autopilot/CLI/test_receive_response.lua (+149/-0) telegram/autopilot/telegram/common/__init__.py (+36/-0) telegram/autopilot/telegram/common/config.py (+350/-0) telegram/autopilot/telegram/common/options.py (+37/-0) telegram/autopilot/telegram/common/ssh.py (+199/-0) telegram/autopilot/telegram/common/utils.py (+87/-0) telegram/autopilot/telegram/emulators.py (+550/-0) telegram/autopilot/telegram/setup.py (+57/-0) telegram/autopilot/telegram/tests/__init__.py (+76/-0) telegram/autopilot/telegram/tests/test_Logout.py (+52/-0) telegram/autopilot/telegram/tests/test_MessageDisplay.py (+205/-0) telegram/autopilot/telegram/tests/test_Messaging.py (+402/-0) telegram/autopilot/telegram/tests/test_Offline.py (+54/-0) telegram/autopilot/telegram/tests/test_Profile.py (+186/-0) telegram/autopilot/telegram/utilities.py (+36/-0) |
To merge this branch: | bzr merge lp:~cellsoftware/telegram-app/autopilotTest-4 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Jin (community) | Approve | ||
Roberto Mier Escandon (community) | Approve | ||
Review via email: mp+310414@code.launchpad.net |
Commit message
Description of the change
Autopilot tests added
Code changes involve adding 'objectName' attribute to necessary components in order to make them visible to autopilot
Build script updates (setup.sh and click.sh) to include new flag (-u) to include autopilot tests in click package for mobile build
README document updated with autopilot use
- 246. By Paz Chauhan
-
Removal of parseText function
Paz Chauhan (paz-chauhan) wrote : | # |
Conflicts hopefully resolved
Roberto Mier Escandon (rmescandon) wrote : | # |
Still seen conflicts here. See just below the "Diff against target" section
- 247. By Paz Chauhan
-
conflicts resolved
- 248. By Paz Chauhan
-
.po and .pot files reverted
Roberto Mier Escandon (rmescandon) wrote : | # |
Please revert also the telegram/po complete directory
- 249. By Paz Chauhan
-
.po and .pot files reverted
Roberto Mier Escandon (rmescandon) wrote : | # |
Just a pair of commented out lines that I'm not sure if are there left on purpose. If not remove them, please
- 250. By Paz Chauhan
-
Commented out code explained
Roberto Mier Escandon (rmescandon) wrote : | # |
My experience is that on device some of the tests pass, some others not. I have not been able to pass all them ever.
In desktop version, the textbox to write messages is disabled (I see also app in "waiting for network", so seem it is related) and thus the tests are not passing (send messages cannot be executed)
I guess all this can be fixed in a later MR. For now +1
Jin (jindallo) wrote : | # |
I can't get them all passed as well,
no further actions on Contact selection page in running oftenly,
now the DUT from me is Nexus 4 with stable channel,
still need to verify it on BQ phone later,
will report my running result here.
Jin (jindallo) wrote : | # |
After .lua configured now the test cases can run well,
I approve.
Preview Diff
1 | === modified file 'README.md' |
2 | --- README.md 2016-09-30 05:22:00 +0000 |
3 | +++ README.md 2016-11-14 11:39:33 +0000 |
4 | @@ -1,4 +1,4 @@ |
5 | -# Telegram for Ubuntu |
6 | +# **Telegram for Ubuntu** |
7 | |
8 | ### TLDR; |
9 | "./setup.sh -t mobile -dbc" for a full mobile build |
10 | @@ -7,60 +7,216 @@ |
11 | ### How to build |
12 | |
13 | This build setup has been tested on: |
14 | -- Ubuntu Xenial 16.04 |
15 | +- Ubuntu Vivid 15.04 with Overlay PPA enabled |
16 | |
17 | The following instructions assume you downloaded Telegram for Ubuntu source and changed ("cd") to the project's root directory. |
18 | |
19 | -1) Install build dependencies |
20 | - If you're building for mobile devices: |
21 | - If you don't have a 15.04 click chroot yet: |
22 | - sudo click chroot --arch armhf --framework ubuntu-sdk-15.04 create |
23 | - To install the build dependencies in the chroot: |
24 | - sudo click chroot --arch armhf --framework ubuntu-sdk-15.04 maint |
25 | - apt-get install libthumbnailer-qt-dev:armhf thumbnailer-service:armhf |
26 | - Else if you're building for desktop, install the build dependencies using the following command: |
27 | - sudo apt-get install libthumbnailer-qt-dev qml-module-ubuntu-connectivity qtdeclarative5-ubuntu-contacts0.1 |
28 | - |
29 | -2) Environment setup |
30 | - Change your directory into below: |
31 | - ~/.config/QtProject/qtcreator/ubuntu-sdk/ubuntu-sdk-15.04-armhf |
32 | - then make a symbolic link bewteen qtc_chroot_wrapper and the make: |
33 | - ln -s /usr/share/qtcreator/ubuntu/scripts/qtc_chroot_wrapper.py make |
34 | - |
35 | -3) Download and build the source of libqtelegram-aseman-edition library and TelegramQML plugin: |
36 | - - Run ./setup.sh -t <build_type> -d |
37 | - |
38 | - The help command will show the available values for <build_type>. |
39 | - It'll git clone both projects to the deps directory and build them (inside the click chroot, if |
40 | - the build type chosen was "mobile"). |
41 | - You can use same command to re-build, if you have changed them, too. |
42 | - NOTE: it may be required to modify some environment variables that drive the build process, such |
43 | +## **Install build dependencies** |
44 | +### Device |
45 | + If you don't have a 15.04 click chroot yet: |
46 | + |
47 | + $ sudo click chroot --arch armhf --framework ubuntu-sdk-15.04 create |
48 | + |
49 | +To install the build dependencies in the chroot: |
50 | + |
51 | + $ sudo click chroot --arch armhf --framework ubuntu-sdk-15.04 maint |
52 | + |
53 | + $ apt-get install libthumbnailer-qt-dev:armhf libthumbnailer-qt1.0:armhf thumbnailer-service:armhf |
54 | + |
55 | +### Desktop |
56 | + |
57 | + Install the build dependencies using the following command: |
58 | + |
59 | + $ sudo apt-get install libthumbnailer-qt-dev libthumbnailer-qt1.0 thumbnailer-service libqt5xmlpatterns5-dev qtdeclarative5-dev qtmultimedia5-dev libssl-dev |
60 | + |
61 | +2) Download and build the source of libqtelegram-aseman-edition library and TelegramQML plugin: |
62 | + |
63 | + $ ./setup.sh -t <build_type> -d |
64 | + |
65 | +The help command will show the available values for <build_type>. |
66 | + It'll git clone both projects to the deps directory and build them (inside the click chroot, if the build type chosen was "mobile"). |
67 | +You can use same command to re-build, if you have changed them, too. |
68 | + |
69 | + NOTE: it may be required to modify some environment variables that drive the build process, such |
70 | as the path to qmake or make, the path to system libraries, the name of the chroot, etc. |
71 | The env variables are grouped at the beginning of setup.sh, to make the customization easier. |
72 | |
73 | -4) Build Telegram for Ubuntu |
74 | - - Run ./setup.sh -t <build_type> -b |
75 | +3) Build Telegram for Ubuntu |
76 | + |
77 | + $ ./setup.sh -t <build_type> -b |
78 | |
79 | - This will build the app in the build path defined by setup.sh |
80 | + This will build the app in the build path defined by setup.sh |
81 | and prepare everything in a directory named click in the project's root directory. |
82 | NOTE: it may be required to modify some environment variables that drive the build process, such |
83 | as the path to qmake or make, the path to system libraries, the name of the chroot, etc. |
84 | The env variables are grouped at the beginning of setup.sh, to make the customization easier. |
85 | |
86 | -5) (Optional) Build the click package and install it using adb (requires an Ubuntu Touch |
87 | +4) (Optional) Build the click package and install it using adb (requires an Ubuntu Touch |
88 | mobile device connected via USB with developer mode enabled): |
89 | - - Run ./setup.sh -t mobile -c |
90 | |
91 | + $ ./setup.sh -t mobile -c |
92 | |
93 | ### How to run (DESKTOP VERSION only) |
94 | |
95 | -- cd to the path holding the binary we have just build, e.g. "cd build_desktop/lib/x86_64-linux-gnu/bin/" |
96 | -- run "LD_LIBRARY_PATH=../../../:$LD_LIBRARY_PATH ./telegram" |
97 | +cd to the path holding the binary we have just build, e.g. `$ cd build_desktop/lib/x86_64-linux-gnu/bin/` |
98 | + |
99 | + $ LD_LIBRARY_PATH=../../../:$LD_LIBRARY_PATH ./telegram |
100 | + |
101 | |
102 | ### How to delete the build files |
103 | |
104 | -- Run ./setup -t <build_type> -e |
105 | + $ ./setup -t <build_type> -e |
106 | |
107 | ### How to get help |
108 | |
109 | -- Run ./setup -h |
110 | + $ ./setup -h |
111 | + |
112 | +---------- |
113 | + |
114 | +# **Autopilot** |
115 | + |
116 | +### Install On Desktop |
117 | +To install Autopilot on a Ubuntu Desktop follow [this tutorial](https://developer.ubuntu.com/api/autopilot/python/1.5.0/guides-installation/). |
118 | + |
119 | +### Install on Device |
120 | +To install on a Ubuntu device you will need to first connect to the device via SSH: |
121 | + |
122 | + $ adb shell |
123 | + |
124 | +Then execute the following commands: |
125 | + |
126 | + $ sudo mount -o remount,rw / |
127 | + |
128 | + $ sudo apt-get update |
129 | + |
130 | + $ sudo apt-get install python3-autopilot ubuntu-ui-toolkit-autopilot -yq |
131 | + |
132 | +## **Telegram-App code changes** |
133 | +Download the following telegram-app sample project which contains the autopilot test cases and and supporting documentation such as, **Telegram-App_Code_Changes.pdf**: |
134 | + |
135 | + $ bzr branch lp:~cellsoftware/telegram-app/autopilotTest-3 |
136 | + |
137 | +**Telegram-App_Code_Changes.pdf** lists the components which need to be updated, on your on version of the telegram-app code, with the *objectName* attribute in order for them to become visible to autopilot. This document also describes certain code changes which need to be made in order for desktop tests to pass. These are mainly to do with simulating an online device. |
138 | + |
139 | +Once downloaded, you will have created and autopilotTest-3 directory on your computer. The autopilot test scripts for **telegram-app** can be found in the following relative directory path: |
140 | + |
141 | +> autopilotTest-3/telegram/autopilot/telegram |
142 | + |
143 | +**This directory structure must be maintained when copying the autopilot test cases to your own version of the app.** |
144 | + |
145 | +##**Test Environment** |
146 | + |
147 | +###Telegram-CLI |
148 | +All tests involving the sending and receiving of messages will involve the Telegram CLI. This can be downloaded from [GitHub](https://github.com/vysheng/tg). Follow the instructions to install and build. The Telegram CLI scripts are written in Lua and can be found in the following relative directory path: |
149 | + |
150 | +> autopilotTest-3/telegram/autopilot/CLI |
151 | + |
152 | +**This directory structure must be maintained when copying the autopilot test cases to your own version of the app.** |
153 | + |
154 | +#### Telegram CLI Launch |
155 | + |
156 | +Once downloaded cd, to the '**tg**' folder. Then execute the following command: |
157 | + |
158 | + $ bin/telegram-cli -k tg-server.pub -W -s <location of the test script> |
159 | + |
160 | +###Test Data |
161 | +The following are prerequisites to executing the autopilot test cases: |
162 | + |
163 | +> - A Telegram user must be logged into the app |
164 | +> - The Telegram user must be signed into their Ubuntu One account |
165 | +> - The app must not be launched |
166 | +> - The device must not be screen or SIM locked |
167 | +> - The device must be on the screen displaying the apps |
168 | +> - The user must have 2 Telegram contacts defined, one of which must be the phone number used to set up the Telegram CLI |
169 | +> - The Telegram CLI must be online |
170 | + |
171 | +## **Execution** |
172 | + |
173 | +### Desktop |
174 | + |
175 | +Before running, the **telegram-app** and its dependencies have to be built. |
176 | +From the autopilotTest-3 directory execute the following command: |
177 | + |
178 | + $ ./setup.sh -t desktop -db |
179 | + |
180 | +To execute the entire test suite perform the following command from the `autopilotTest-3/telegram/autopilot/` directory: |
181 | + |
182 | + $ autopilot3 run telegram/ |
183 | + |
184 | +To get a list of all individual test cases execute the following command: |
185 | + |
186 | + $ autopilot3 list telegram/ |
187 | + |
188 | +You will see an output similar to this: |
189 | + |
190 | +> *2 telegram.tests.test_Messaging.SecretMessaging.test_SecretMessage |
191 | +> telegram.tests.test_Profile.ProfileTests.test_check_group_to_verify_members |
192 | +> telegram.tests.test_Profile.ProfileDetails.test_verify_profile_details |
193 | +> telegram.tests.test_Profile.ProfileTests.test_check_blocked_user |
194 | + |
195 | +The *2 next to a test case refers to the number of scenarios within that test case. Therefore executing test_SecretMessage will run the same Secret Message test case but for 2 scenarios, e.g. sending a Secret Message containing text only and sending a Secret Message containing images only. |
196 | + |
197 | +To execute all Profile tests execute the following: |
198 | + |
199 | + $ autopilot3 run telegram.tests.test_Profile |
200 | + |
201 | +To execute all Profile Detail tests, execute the following: |
202 | + |
203 | + $ autopilot3 run telegram.tests.test_Profile.ProfileDetails |
204 | + |
205 | +To execute individual tests choose a test from the list, for example *telegram.tests.test_Login.Login.test_sign_in* then execute the following command: |
206 | + |
207 | + $ autopilot3 run telegram.tests.test_Login.Login.test_sign_in |
208 | + |
209 | +### Device |
210 | + |
211 | +To execute the autopilot test cases on a device, the **telegram-app**, its dependencies and the click package have to be built and installed on the device. Once you have connected your device via USB, build the mobile version of the app using the following command: |
212 | + |
213 | + $ ./setup.sh -t mobile -dbcu |
214 | + |
215 | +Next, navigate to the installed test suite using: |
216 | + |
217 | + $ adb shell |
218 | + |
219 | + $ cd /opt/click.ubuntu.com/com.ubuntu.telegram/current/autopilot |
220 | + |
221 | +The listing and executing of tests are as described in the Desktop section. |
222 | + |
223 | +## **Notes** |
224 | +After getting Autopilot working. Here are some notes you need to do to ensure tests can be run properly: |
225 | + |
226 | +### Device |
227 | + |
228 | +During device testing the orientation should remain as portrait. Changing the orientation to landscape will cause tests to fail. |
229 | + |
230 | +### Telegram CLI |
231 | + |
232 | +If any of the test cases executed require the sending and/or receiving of messages the Telegram CLI will have to be launched, as described above. If left running for some time without activity the Telegram CLI will go offline. This may cause some autopilot tests to fail. To bring the Telegram CLI back online you can issue a CLI command, or quit the CLI by entering 'safe_quit' and relaunching. |
233 | + |
234 | +### Flags |
235 | + |
236 | +Here are the types and meanings for each flag: |
237 | + |
238 | +**-d** - Dependency - Build the dependency to support the app |
239 | +**-b** - Build - Builds and compile the app. |
240 | +**-c** - Install on device |
241 | +**-u** - Adds the autopilot tests to the click package installed on the device |
242 | + |
243 | + $ ./setup.sh -t mobile -<flag(s)> |
244 | +For a more in-depth 'how-to' see [here](https://developer.ubuntu.com/api/autopilot/python/1.5.0/guides-running_ap/). |
245 | + |
246 | +###Messaging |
247 | +To get messaging working correctly you need to make some code changes in |
248 | +AccountSendMessage.qml: |
249 | + |
250 | +> 1. Enable TextArea - #155 - Change to `enabled: true`. |
251 | +> 2. Enable Sticker button (if required) - #264 - Remove `connected || !NetworkingStatus` IF statement so you only have `if |
252 | +> (!privates.emojiItem) {...}` in `onClicked:`. |
253 | +> 3. Enable Send button - #326 - Remove `connected || !NetworkingStatus` IF statement so you only have `if (state == “attach”) {...}` in |
254 | +> `onClicked:`. |
255 | + |
256 | +## **References & Tutorials** |
257 | +- [Autopilot Tutorials and Guides](https://developer.ubuntu.com/api/autopilot/python/1.5.0/) |
258 | +- [Autopilot at a glance](http://www.theorangenotebook.com/2012/11/a-glance-at-autopilot.html) |
259 | +- [Getting started with Autopilot](http://www.theorangenotebook.com/2012/11/getting-started-with-autopilot.html) |
260 | +- [Your first autopilot test case](http://www.theorangenotebook.com/2012/11/our-first-autopilot-testcase.html) |
261 | |
262 | === added file 'Telegram-App_Code_Changes.pdf' |
263 | Binary files Telegram-App_Code_Changes.pdf 1970-01-01 00:00:00 +0000 and Telegram-App_Code_Changes.pdf 2016-11-14 11:39:33 +0000 differ |
264 | === modified file 'buildScripts/click.sh' |
265 | --- buildScripts/click.sh 2015-11-02 15:30:52 +0000 |
266 | +++ buildScripts/click.sh 2016-11-14 11:39:33 +0000 |
267 | @@ -6,6 +6,16 @@ |
268 | exit 1 |
269 | fi |
270 | |
271 | +if [ "$TEST_STEP" = "y" ]; then |
272 | + # Copy autopilot tests into click directory |
273 | + echo "Removing old autopilot tests..." |
274 | + rm -rf $TG_DIR/$BUILD_DIR_BASENAME/click/$AUTOPILOT_DIR || exit 1 |
275 | + echo "Adding autopilot tests to the click package..." |
276 | + mkdir $TG_DIR/$BUILD_DIR_BASENAME/click/$AUTOPILOT_DIR || exit 1 |
277 | + # mkdir $TG_DIR/$BUILD_DIR_BASENAME/click/$AUTOPILOT_DIR_BASENAME || exit 1 |
278 | + cp -avr $TG_DIR/$AUTOPILOT_PATH $TG_DIR/$BUILD_DIR_BASENAME/click/$AUTOPILOT_DIR_BASENAME || exit 1 |
279 | +fi |
280 | + |
281 | cd $TG_DIR/$BUILD_DIR_BASENAME/ || exit 1 |
282 | click build click || exit 1 |
283 | |
284 | |
285 | === modified file 'setup.sh' |
286 | --- setup.sh 2016-04-01 08:44:31 +0000 |
287 | +++ setup.sh 2016-11-14 11:39:33 +0000 |
288 | @@ -37,6 +37,10 @@ |
289 | export SYSTEM_LIB_PATH=/usr/lib/arm-linux-gnueabihf |
290 | export SYSTEM_INCLUDE_PATH=/usr/include/ |
291 | export BUILD_DIR_BASENAME=build_mobile |
292 | + export AUTOPILOT_DIR=autopilot |
293 | + export AUTOPILOT_APP_DIR=/telegram |
294 | + export AUTOPILOT_DIR_BASENAME=$AUTOPILOT_DIR/$AUTOPILOT_APP_DIR |
295 | + export AUTOPILOT_PATH=telegram/$AUTOPILOT_DIR_BASENAME |
296 | } |
297 | #Generic env vars |
298 | function setTelegramEnvVars() { |
299 | @@ -65,6 +69,7 @@ |
300 | APP_STEP=n |
301 | CLICK_STEP=n |
302 | ERASE_STEP=n |
303 | +export TEST_STEP=n |
304 | RESET_ENV_VARS=n |
305 | |
306 | function usage() { |
307 | @@ -75,9 +80,10 @@ |
308 | echo "-b To build the telegram app." |
309 | echo "-c To create and install the click package (only valid if mobile build type has been selected)" |
310 | echo "-e To erase all build files relative to the specified build type." |
311 | + echo "-u To include all autopilot unit test cases in the click package (only valid if -c has been selected)." |
312 | } |
313 | |
314 | -while getopts "t:dbceh" opt; do |
315 | +while getopts "t:dbceuh" opt; do |
316 | case $opt in |
317 | t) |
318 | case $OPTARG in |
319 | @@ -106,6 +112,9 @@ |
320 | e) |
321 | ERASE_STEP=y |
322 | ;; |
323 | + u) |
324 | + TEST_STEP=y |
325 | + ;; |
326 | v) |
327 | RESET_ENV_VARS=y |
328 | ;; |
329 | @@ -125,6 +134,12 @@ |
330 | exit 1 |
331 | fi |
332 | |
333 | +if [ "$CLICK_STEP" = "n" ] && [ "$TEST_STEP" = "y" ]; then |
334 | + echo "The inclusion of autopilot test cases requires the -c flag." |
335 | + usage |
336 | + exit 1 |
337 | +fi |
338 | + |
339 | if [ "$BUILD_TYPE" = "desktop" ]; then |
340 | setDesktopBuildEnvVars |
341 | else |
342 | @@ -167,3 +182,4 @@ |
343 | if [ "$ERASE_STEP" = "y" ]; then |
344 | source ./buildScripts/clean.sh || exit 1 |
345 | fi |
346 | + |
347 | |
348 | === modified file 'telegram/app/qml/AccountContactsPage.qml' |
349 | --- telegram/app/qml/AccountContactsPage.qml 2016-06-17 15:19:54 +0000 |
350 | +++ telegram/app/qml/AccountContactsPage.qml 2016-11-14 11:39:33 +0000 |
351 | @@ -17,7 +17,7 @@ |
352 | Page { |
353 | id: page |
354 | flickable: null |
355 | - |
356 | + objectName: "accountContactsPage" |
357 | header: default_header |
358 | |
359 | PageHeader { |
360 | @@ -113,6 +113,7 @@ |
361 | property var none: [] |
362 | property list<Action> confirm: [ |
363 | Action { |
364 | + objectName: "createGroupChatOK" |
365 | iconName: "ok" |
366 | text: i18n.tr("OK") |
367 | enabled: hasGroupTitle |
368 | @@ -225,6 +226,7 @@ |
369 | |
370 | TextField { |
371 | id: group_chat_title_text_field |
372 | + objectName: "groupChatTextField" |
373 | anchors { |
374 | top: page.header.bottom |
375 | topMargin: isVisible ? units.gu(1) : 0 |
376 | @@ -253,6 +255,7 @@ |
377 | } |
378 | |
379 | MultipleSelectionListView { |
380 | + objectName: "contactList" |
381 | id: contact_list |
382 | anchors { |
383 | top: group_chat_title_text_field.visible ? group_chat_title_text_field.bottom : parent.top |
384 | @@ -278,6 +281,7 @@ |
385 | |
386 | listModel: searchTerm == "" ? contacts_model : contacts_filter_model |
387 | listDelegate: TelegramContactsListItem { |
388 | + objectName: "contact%1".arg(index) |
389 | id: delegate |
390 | telegram: page.telegram |
391 | user: model.user |
392 | |
393 | === modified file 'telegram/app/qml/AccountDialogList.qml' |
394 | --- telegram/app/qml/AccountDialogList.qml 2016-07-19 15:15:28 +0000 |
395 | +++ telegram/app/qml/AccountDialogList.qml 2016-11-14 11:39:33 +0000 |
396 | @@ -57,6 +57,7 @@ |
397 | |
398 | ListView { |
399 | id: dialog_list |
400 | + objectName: "dialogListView" |
401 | anchors { |
402 | top: parent.top |
403 | left: parent.left |
404 | @@ -81,6 +82,7 @@ |
405 | |
406 | delegate: DialogsListItem { |
407 | id: list_item |
408 | + objectName: "dialog%1".arg(index) |
409 | anchors { |
410 | topMargin: units.dp(3) |
411 | leftMargin: units.dp(5) |
412 | |
413 | === modified file 'telegram/app/qml/AccountDialogPage.qml' |
414 | --- telegram/app/qml/AccountDialogPage.qml 2016-07-22 06:27:59 +0000 |
415 | +++ telegram/app/qml/AccountDialogPage.qml 2016-11-14 11:39:33 +0000 |
416 | @@ -28,6 +28,7 @@ |
417 | |
418 | property list<Action> defaultActions: [ |
419 | Action { |
420 | + objectName: "groupInfo" |
421 | iconName: "stock_contact" |
422 | text: isChat ? i18n.tr("Group Info") : i18n.tr("Profile Info") |
423 | onTriggered: { |
424 | @@ -85,6 +86,7 @@ |
425 | trailingActionBar.actions: message_list.inSelectionMode ? selectionActions : defaultActions |
426 | leadingActionBar.actions: Action { |
427 | id: back_action |
428 | + objectName: "dialogBack" |
429 | iconName: message_list.inSelectionMode ? "close" : "back" |
430 | onTriggered: { |
431 | if (message_list.inSelectionMode) { |
432 | @@ -213,6 +215,7 @@ |
433 | |
434 | AccountSendMessage { |
435 | id: send_msg |
436 | + objectName: "accountSendMessageArea" |
437 | anchors { |
438 | right: parent.right |
439 | bottom: parent.bottom |
440 | @@ -236,6 +239,7 @@ |
441 | |
442 | AccountMessageList { |
443 | id: message_list |
444 | + objectName: "accountMessageList" |
445 | anchors { |
446 | top: add_contact_header.visible ? add_contact_header.bottom : parent.top |
447 | right: parent.right |
448 | |
449 | === modified file 'telegram/app/qml/AccountMessageList.qml' |
450 | --- telegram/app/qml/AccountMessageList.qml 2016-11-14 02:59:38 +0000 |
451 | +++ telegram/app/qml/AccountMessageList.qml 2016-11-14 11:39:33 +0000 |
452 | @@ -176,6 +176,7 @@ |
453 | |
454 | MultipleSelectionListView { |
455 | id: mlist |
456 | + objectName: "messagesListView" |
457 | anchors.fill: parent |
458 | cacheBuffer: units.gu(10) * 20 |
459 | clip: true |
460 | @@ -228,6 +229,7 @@ |
461 | listModel: messages_model |
462 | listDelegate: MessagesListItem { |
463 | id: message_item |
464 | + objectName: "message%1".arg(index) |
465 | maximumMediaHeight: acc_msg_list.maximumMediaHeight |
466 | maximumMediaWidth: acc_msg_list.maximumMediaWidth |
467 | message: item |
468 | |
469 | === modified file 'telegram/app/qml/AccountMessageMedia.qml' |
470 | --- telegram/app/qml/AccountMessageMedia.qml 2016-09-28 18:34:44 +0000 |
471 | +++ telegram/app/qml/AccountMessageMedia.qml 2016-11-14 11:39:33 +0000 |
472 | @@ -315,6 +315,7 @@ |
473 | |
474 | MessageStatus { |
475 | id: message_status |
476 | + objectName: "mediaMessageStatus" |
477 | anchors { |
478 | bottom: parent.bottom |
479 | bottomMargin: units.dp(4) |
480 | |
481 | === modified file 'telegram/app/qml/AccountPage.qml' |
482 | --- telegram/app/qml/AccountPage.qml 2016-07-11 16:11:59 +0000 |
483 | +++ telegram/app/qml/AccountPage.qml 2016-11-14 11:39:33 +0000 |
484 | @@ -75,6 +75,7 @@ |
485 | |
486 | AccountPanel { |
487 | id: account_panel |
488 | + objectName:"accountPanel" |
489 | anchors { |
490 | left: parent.left |
491 | top: parent.top |
492 | @@ -168,6 +169,7 @@ |
493 | |
494 | AccountDialogList { |
495 | id: dialogs |
496 | + objectName: "accountDialogList" |
497 | anchors{ |
498 | fill: parent |
499 | topMargin: account_page.header.height |
500 | @@ -289,6 +291,7 @@ |
501 | header: default_header |
502 | PageHeader { |
503 | id: default_header |
504 | + objectName: "defaultHeader" |
505 | visible: account_page.header === default_header |
506 | title: { |
507 | if (NetworkingStatus.online) { |
508 | @@ -305,6 +308,7 @@ |
509 | } |
510 | } |
511 | leadingActionBar.actions: Action { |
512 | + objectName: "navigationMenu" |
513 | iconName: "navigation-menu" |
514 | onTriggered: { |
515 | account_panel.opened ? account_panel.close() : account_panel.open() |
516 | |
517 | === modified file 'telegram/app/qml/AccountSendMessage.qml' |
518 | --- telegram/app/qml/AccountSendMessage.qml 2016-04-22 10:35:16 +0000 |
519 | +++ telegram/app/qml/AccountSendMessage.qml 2016-11-14 11:39:33 +0000 |
520 | @@ -139,6 +139,7 @@ |
521 | |
522 | TextArea { |
523 | id: txt |
524 | + objectName: "sendMessageTextArea" |
525 | |
526 | property int oldLength: 0 |
527 | |
528 | @@ -152,6 +153,9 @@ |
529 | |
530 | // This value is to avoid letter and underline being cut off. |
531 | height: units.gu(4.3) |
532 | + |
533 | + // To work on desktop change the following line to: |
534 | + // enabled: True |
535 | enabled: NetworkingStatus.online && telegramObject.connected |
536 | visible: !messagePlaceholder.visible |
537 | // TRANSLATORS: Placeholder for the message input text area. |
538 | @@ -297,6 +301,7 @@ |
539 | |
540 | MouseArea { |
541 | id: send_mouse_area |
542 | + objectName: "sendMouseArea" |
543 | height: parent.height |
544 | width: units.gu(6) |
545 | enabled: telegramObject.connected |
546 | @@ -323,6 +328,8 @@ |
547 | onClicked: { |
548 | Qt.inputMethod.commit(); |
549 | |
550 | + // To work on desktop change the following line to: |
551 | + // if (!telegramObject.connected) return |
552 | if (!telegramObject.connected || !NetworkingStatus.online) return |
553 | |
554 | if (state == "attach") { |
555 | |
556 | === modified file 'telegram/app/qml/AccountSettings.qml' |
557 | --- telegram/app/qml/AccountSettings.qml 2016-07-13 09:13:36 +0000 |
558 | +++ telegram/app/qml/AccountSettings.qml 2016-11-14 11:39:33 +0000 |
559 | @@ -194,6 +194,7 @@ |
560 | } |
561 | |
562 | ListItem.Standard { |
563 | + objectName: "listItem_logout" |
564 | showDivider: true |
565 | text: i18n.tr("Log out") + " | " + telegram.phoneNumber |
566 | onClicked: PopupUtils.open(logout_dialog_component) |
567 | @@ -282,6 +283,7 @@ |
568 | } |
569 | |
570 | ListView { |
571 | + objectName: "settingsList" |
572 | anchors { |
573 | topMargin: units.gu(2) |
574 | top: profile_image.bottom |
575 | @@ -297,9 +299,11 @@ |
576 | id: logout_dialog_component |
577 | Popup.Dialog { |
578 | id: logout_dialog |
579 | + objectName: "logoutDialog" |
580 | title: i18n.tr("Telegram") |
581 | text: i18n.tr("Are you sure you want to log out?\nAny secret chats will be lost.") |
582 | Button { |
583 | + objectName: "logoutConfirm" |
584 | text: i18n.tr("OK") |
585 | color: UbuntuColors.orange |
586 | onClicked: { |
587 | |
588 | === modified file 'telegram/app/qml/AuthCountriesPage.qml' |
589 | --- telegram/app/qml/AuthCountriesPage.qml 2016-06-22 09:29:10 +0000 |
590 | +++ telegram/app/qml/AuthCountriesPage.qml 2016-11-14 11:39:33 +0000 |
591 | @@ -22,6 +22,7 @@ |
592 | property bool searchMode: false |
593 | Action { |
594 | id: searchAction |
595 | + objectName: "searchIcon" |
596 | iconName: "search"; |
597 | text: i18n.tr("Search"); |
598 | onTriggered:{ |
599 | @@ -48,6 +49,7 @@ |
600 | |
601 | TextField { |
602 | id: search_text_field |
603 | + objectName: "countryField" |
604 | visible: choose_header.searchMode |
605 | anchors { |
606 | right: parent ? parent.right : undefined |
607 | |
608 | === modified file 'telegram/app/qml/AuthNumberPage.qml' |
609 | --- telegram/app/qml/AuthNumberPage.qml 2016-06-23 07:07:53 +0000 |
610 | +++ telegram/app/qml/AuthNumberPage.qml 2016-11-14 11:39:33 +0000 |
611 | @@ -84,6 +84,9 @@ |
612 | height: phone_number.height |
613 | anchors.horizontalCenter: parent.horizontalCenter |
614 | text: i18n.tr("Done") |
615 | + |
616 | + // To work on desktop change the following line to: |
617 | + // enabled: phoneNumber.length > 0 |
618 | enabled: isOnline && phoneNumber.length > 0 |
619 | focus: true |
620 | onClicked: phone_number.accepted() |
621 | |
622 | === modified file 'telegram/app/qml/ProfilePage.qml' |
623 | --- telegram/app/qml/ProfilePage.qml 2016-06-27 09:22:33 +0000 |
624 | +++ telegram/app/qml/ProfilePage.qml 2016-11-14 11:39:33 +0000 |
625 | @@ -17,6 +17,7 @@ |
626 | Page { |
627 | id: profile_page |
628 | title: isChat ? i18n.tr("Group Info") : i18n.tr("Contact Info") |
629 | + objectName: "profilePage" |
630 | |
631 | property Telegram telegram |
632 | property Dialog dialog |
633 | @@ -59,6 +60,12 @@ |
634 | header: PageHeader { |
635 | title: profile_page.title |
636 | trailingActionBar.actions: isChat ? groupActions : noActions |
637 | + leadingActionBar.actions: Action { |
638 | + id: back_action |
639 | + objectName: "profileBack" |
640 | + iconName: "back" |
641 | + onTriggered: pageStack.removePages(profile_page); |
642 | + } |
643 | } |
644 | |
645 | signal openDialog(var dialogId) |
646 | @@ -186,6 +193,7 @@ |
647 | |
648 | MediaImport { |
649 | id: photo_importer |
650 | + objectName: "profileImageImport" |
651 | contentType: ContentType.Pictures |
652 | |
653 | onMediaReceived: { |
654 | @@ -235,6 +243,7 @@ |
655 | |
656 | ClickableContactImage { |
657 | id: profile_image |
658 | + objectName: "profileImage" |
659 | anchors { |
660 | top: parent.top |
661 | topMargin: units.gu(2) + profile_page.header.height |
662 | @@ -388,6 +397,7 @@ |
663 | spacing: units.dp(4) |
664 | |
665 | Label { |
666 | + objectName: "profilePhoneNumber" |
667 | verticalAlignment: Text.AlignVCenter |
668 | horizontalAlignment: Text.AlignLeft |
669 | fontSize: "large" |
670 | @@ -449,6 +459,7 @@ |
671 | spacing: units.dp(4) |
672 | |
673 | Label { |
674 | + objectName: "profileUserName" |
675 | id: username_label |
676 | fontSize: "large" |
677 | font.family: "Helvetica" |
678 | @@ -621,6 +632,7 @@ |
679 | |
680 | Switch { |
681 | id: block_check |
682 | + objectName: "switchBlock" |
683 | |
684 | property bool silentChecked |
685 | property bool override: false |
686 | @@ -656,6 +668,7 @@ |
687 | |
688 | ListView { |
689 | id: participants_list |
690 | + objectName: "memberListView" |
691 | anchors { |
692 | top: blocked_row.bottom |
693 | topMargin: units.gu(2) |
694 | @@ -669,6 +682,7 @@ |
695 | model: chat_participants_model |
696 | delegate: TelegramContactsListItem { |
697 | id: contact_item |
698 | + objectName: "dialog%1".arg(index) |
699 | telegram: profile_page.telegram |
700 | user: telegram.user(item.userId) |
701 | |
702 | |
703 | === modified file 'telegram/app/qml/components/AccountPanel.qml' |
704 | --- telegram/app/qml/components/AccountPanel.qml 2016-04-08 06:26:31 +0000 |
705 | +++ telegram/app/qml/components/AccountPanel.qml 2016-11-14 11:39:33 +0000 |
706 | @@ -72,6 +72,7 @@ |
707 | } |
708 | |
709 | AccountPanelItem { |
710 | + objectName:"groupChatItem" |
711 | icon: "../files/menu_newgroup.png" |
712 | text: i18n.tr("New Group") |
713 | showDivider: false |
714 | @@ -81,6 +82,7 @@ |
715 | } |
716 | } |
717 | AccountPanelItem { |
718 | + objectName:"secretChatItem" |
719 | icon: "../files/menu_secret.png" |
720 | text: i18n.tr("New Secret Chat") |
721 | onClicked: { |
722 | @@ -89,6 +91,7 @@ |
723 | } |
724 | } |
725 | AccountPanelItem { |
726 | + objectName:"panelContacts" |
727 | icon: "../files/menu_contacts.png" |
728 | text: i18n.tr("Contacts") |
729 | showDivider: false |
730 | @@ -98,6 +101,7 @@ |
731 | } |
732 | } |
733 | AccountPanelItem { |
734 | + objectName:"panelSettings" |
735 | icon: "../files/menu_settings.png" |
736 | text: i18n.tr("Settings") |
737 | showDivider: false |
738 | |
739 | === modified file 'telegram/app/qml/components/AttachPanel.qml' |
740 | --- telegram/app/qml/components/AttachPanel.qml 2015-10-01 14:19:18 +0000 |
741 | +++ telegram/app/qml/components/AttachPanel.qml 2016-11-14 11:39:33 +0000 |
742 | @@ -81,6 +81,7 @@ |
743 | spacing: units.gu(2.8) |
744 | |
745 | AttachPanelItem { |
746 | + objectName: "panelPhoto" |
747 | id: attach_photo_item |
748 | // TRANSLATORS: Used in attach menu, when sending a photo to the conversation. |
749 | text: i18n.tr("Photo") |
750 | @@ -94,6 +95,7 @@ |
751 | |
752 | AttachPanelItem { |
753 | // TRANSLATORS: Used in attach menu, when sending a video to the conversation. |
754 | + objectName: "panelVideo" |
755 | text: i18n.tr("Video") |
756 | image: Qt.resolvedUrl("qrc:/qml/files/android/attach_video.png") |
757 | onClicked: { |
758 | @@ -105,6 +107,7 @@ |
759 | |
760 | AttachPanelItem { |
761 | // TRANSLATORS: Used in attach menu, when sending a file to the conversation. |
762 | + objectName: "panelFile" |
763 | text: i18n.tr("File") |
764 | image: Qt.resolvedUrl("qrc:/qml/files/android/attach_file.png") |
765 | onClicked: { |
766 | @@ -115,6 +118,7 @@ |
767 | } |
768 | |
769 | AttachPanelItem { |
770 | + objectName: "panelClose" |
771 | height: attach_photo_item.height |
772 | // TRANSLATORS: Used in attach menu, when sending a file to the conversation. |
773 | image: Qt.resolvedUrl("qrc:/qml/files/android/attach_hide1.png") |
774 | |
775 | === modified file 'telegram/app/qml/components/MediaImport.qml' |
776 | --- telegram/app/qml/components/MediaImport.qml 2016-04-08 06:08:04 +0000 |
777 | +++ telegram/app/qml/components/MediaImport.qml 2016-11-14 11:39:33 +0000 |
778 | @@ -40,6 +40,7 @@ |
779 | |
780 | Popups.PopupBase { |
781 | id: dialogue |
782 | + objectName: "mediaImportPopup" |
783 | |
784 | property alias activeTransfer: signalConnections.target |
785 | focus: true |
786 | @@ -49,6 +50,7 @@ |
787 | |
788 | ContentHub.ContentPeerPicker { |
789 | id: peerPicker |
790 | + objectName: "contentPeerPicker" |
791 | |
792 | anchors.fill: parent |
793 | contentType: root.contentType |
794 | |
795 | === modified file 'telegram/app/qml/components/MessageStatus.qml' |
796 | --- telegram/app/qml/components/MessageStatus.qml 2016-05-11 10:18:15 +0000 |
797 | +++ telegram/app/qml/components/MessageStatus.qml 2016-11-14 11:39:33 +0000 |
798 | @@ -52,6 +52,7 @@ |
799 | |
800 | Image { |
801 | id: status_image |
802 | + objectName: "statusImage" |
803 | anchors.verticalCenter: parent.verticalCenter |
804 | width: units.gu(2) |
805 | height: width |
806 | |
807 | === modified file 'telegram/app/qml/components/MessagesListItem.qml' |
808 | --- telegram/app/qml/components/MessagesListItem.qml 2016-11-01 21:03:10 +0000 |
809 | +++ telegram/app/qml/components/MessagesListItem.qml 2016-11-14 11:39:33 +0000 |
810 | @@ -245,6 +245,7 @@ |
811 | |
812 | AccountMessageMedia { |
813 | id: message_media |
814 | + objectName: "accountMessageMedia" |
815 | message: message_item.message |
816 | visible: message_media.hasMedia && !uploading |
817 | showStatus: !hasLink |
818 | @@ -268,6 +269,7 @@ |
819 | |
820 | Label { |
821 | id: message_text |
822 | + objectName: "messageText" |
823 | |
824 | anchors { |
825 | top: parent.top |
826 | @@ -296,6 +298,7 @@ |
827 | |
828 | MessageStatus { |
829 | id: message_status |
830 | + objectName: "messageStatus" |
831 | anchors { |
832 | top: message_text.bottom |
833 | right: parent.right |
834 | |
835 | === modified file 'telegram/app/qml/telegram.qml' |
836 | --- telegram/app/qml/telegram.qml 2016-07-19 15:15:28 +0000 |
837 | +++ telegram/app/qml/telegram.qml 2016-11-14 11:39:33 +0000 |
838 | @@ -235,6 +235,7 @@ |
839 | } |
840 | |
841 | AdaptivePageLayout { |
842 | + objectName: "APL" |
843 | id: pageStack |
844 | |
845 | property bool forceSinglePage: false |
846 | |
847 | === added directory 'telegram/autopilot' |
848 | === added directory 'telegram/autopilot/CLI' |
849 | === added file 'telegram/autopilot/CLI/canonical-logo.png' |
850 | Binary files telegram/autopilot/CLI/canonical-logo.png 1970-01-01 00:00:00 +0000 and telegram/autopilot/CLI/canonical-logo.png 2016-11-14 11:39:33 +0000 differ |
851 | === added file 'telegram/autopilot/CLI/test_receive_response.lua' |
852 | --- telegram/autopilot/CLI/test_receive_response.lua 1970-01-01 00:00:00 +0000 |
853 | +++ telegram/autopilot/CLI/test_receive_response.lua 2016-11-14 11:39:33 +0000 |
854 | @@ -0,0 +1,149 @@ |
855 | +function on_msg_receive (msg) |
856 | + |
857 | + status_online(ok_cb, false); |
858 | + |
859 | + -- Uncomment, if debugging, to see all properties of objects |
860 | + -- print ("Message From data...") |
861 | + -- getAllData(msg.from,nil) |
862 | + -- print ("Message To data...") |
863 | + -- getAllData(msg.to,nil) |
864 | + -- print ("Message data...") |
865 | + -- getAllData(msg,nil) |
866 | + |
867 | + -- if (msg.media ~= nil) then |
868 | + -- print ("Message Media data...") |
869 | + -- getAllData(msg.media,nil) |
870 | + -- end |
871 | + |
872 | + if msg.out then |
873 | + return |
874 | + end |
875 | + |
876 | + if (msg.text == nil) and (msg.media == nil) then |
877 | + return |
878 | + end |
879 | + |
880 | + if (msg.to.peer_type == "encr_chat") or (msg.to.peer_type == "chat") then |
881 | + from_name = msg.to.print_name; |
882 | + sleep_timer = 2; |
883 | + else |
884 | + from_name = msg.from.print_name; |
885 | + sleep_timer = 3; |
886 | + end |
887 | + |
888 | + if (msg.text ~= nil) and string.find(msg.text, "INSTANT") then |
889 | + sleep_timer = 0; |
890 | + end |
891 | + |
892 | + if (msg.media ~= nil) then |
893 | + sleep_timer = 3; |
894 | + end |
895 | + |
896 | + if (msg.text ~= nil) then |
897 | + |
898 | + -- wait for sender to run 'sending' confirmation checks |
899 | + sleep(sleep_timer); |
900 | + |
901 | + -- mark the message as read |
902 | + mark_read(from_name, ok_cb, false); |
903 | + |
904 | + if string.find(msg.text, "DO NOT REPLY") then |
905 | + return |
906 | + end |
907 | + |
908 | + -- generate and send an image response, if asked for |
909 | + if string.find(msg.text, "SEND IMAGE") then |
910 | + image_location = (string.sub( debug.getinfo(1).source, 2, string.len(debug.getinfo(1).source) - 25 )); |
911 | + image_file = "canonical-logo.png"; |
912 | + send_photo (from_name, (image_location .. image_file), ok_cb, false); |
913 | + else |
914 | + -- generate and send a text response |
915 | + reply = ("ReplyTo:" .. msg.text); |
916 | + send_msg (from_name, reply, ok_cb, false); |
917 | + |
918 | + end |
919 | + end |
920 | + |
921 | + if (msg.media ~= nil) then |
922 | + |
923 | + -- wait for sender to run 'sending' confirmation checks |
924 | + sleep(sleep_timer); |
925 | + |
926 | + mark_read(from_name, ok_cb, false); |
927 | + end |
928 | + |
929 | + |
930 | +end |
931 | + |
932 | + |
933 | +function ok_cb (extra, success, result) |
934 | + |
935 | +end |
936 | + |
937 | + |
938 | +function on_our_id (id) |
939 | + |
940 | +end |
941 | + |
942 | +function on_secret_chat_created (peer) |
943 | + |
944 | +end |
945 | + |
946 | +function on_user_update (user) |
947 | + |
948 | + -- Change status to online |
949 | + status_online(ok_cb, false); |
950 | + |
951 | +end |
952 | + |
953 | +function on_chat_update (user) |
954 | + |
955 | + -- Change status to online |
956 | + status_online(ok_cb, false); |
957 | + |
958 | +end |
959 | + |
960 | +function on_get_difference_end () |
961 | + |
962 | + -- Change status to online |
963 | + status_online(ok_cb, false); |
964 | + |
965 | +end |
966 | + |
967 | +function on_binlog_replay_end () |
968 | + |
969 | + -- Change status to online |
970 | + status_online(ok_cb, false); |
971 | + |
972 | +end |
973 | + |
974 | +-- Helper Methods |
975 | + |
976 | +-- Sleep function to insert a delay in execution |
977 | +function sleep(n) |
978 | + os.execute("sleep " .. tonumber(n)) |
979 | +end |
980 | + |
981 | +-- Recursive function to obtain properties of an object |
982 | +function getAllData(t, prevData) |
983 | + -- if prevData == nil, start empty, otherwise start with prevData |
984 | + local data = prevData or {} |
985 | + |
986 | + -- copy all the attributes from t |
987 | + for k,v in pairs(t) do |
988 | + data[k] = data[k] or v |
989 | + print(string.format("Key: %s, Value:%s", k, data[k])) |
990 | + end |
991 | + |
992 | + |
993 | + -- get t's metatable, or exit if not existing |
994 | + local mt = getmetatable(t) |
995 | + if type(mt)~='table' then return data end |
996 | + |
997 | + -- get the __index from mt, or exit if not table |
998 | + local index = mt.__index |
999 | + if type(index)~='table' then return data end |
1000 | + |
1001 | + -- include the data from index into data, recursively, and return |
1002 | + return getAllData(index, data) |
1003 | +end |
1004 | |
1005 | === added directory 'telegram/autopilot/telegram' |
1006 | === added file 'telegram/autopilot/telegram/__init__.py' |
1007 | === added directory 'telegram/autopilot/telegram/common' |
1008 | === added file 'telegram/autopilot/telegram/common/__init__.py' |
1009 | --- telegram/autopilot/telegram/common/__init__.py 1970-01-01 00:00:00 +0000 |
1010 | +++ telegram/autopilot/telegram/common/__init__.py 2016-11-14 11:39:33 +0000 |
1011 | @@ -0,0 +1,36 @@ |
1012 | +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
1013 | + |
1014 | +# |
1015 | +# Ubuntu System Tests |
1016 | +# Copyright (C) 2016 Canonical |
1017 | +# |
1018 | +# This program is free software: you can redistribute it and/or modify |
1019 | +# it under the terms of the GNU General Public License as published by |
1020 | +# the Free Software Foundation, either version 3 of the License, or |
1021 | +# (at your option) any later version. |
1022 | +# |
1023 | +# This program is distributed in the hope that it will be useful, |
1024 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1025 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1026 | +# GNU General Public License for more details. |
1027 | +# |
1028 | +# You should have received a copy of the GNU General Public License |
1029 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
1030 | +# |
1031 | + |
1032 | +from telegram.common.utils import ( |
1033 | + clean_dir, |
1034 | + delete_file, |
1035 | + get_random_string, |
1036 | + get_tests_ids_to_run, |
1037 | + get_tests_to_run, |
1038 | +) |
1039 | + |
1040 | + |
1041 | +__all__ = [ |
1042 | + 'clean_dir', |
1043 | + 'delete_file', |
1044 | + 'get_random_string', |
1045 | + 'get_tests_ids_to_run', |
1046 | + 'get_tests_to_run', |
1047 | +] |
1048 | |
1049 | === added file 'telegram/autopilot/telegram/common/config.py' |
1050 | --- telegram/autopilot/telegram/common/config.py 1970-01-01 00:00:00 +0000 |
1051 | +++ telegram/autopilot/telegram/common/config.py 2016-11-14 11:39:33 +0000 |
1052 | @@ -0,0 +1,350 @@ |
1053 | +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
1054 | + |
1055 | +# |
1056 | +# Ubuntu System Tests |
1057 | +# Copyright (C) 2014-2016 Canonical |
1058 | +# |
1059 | +# This program is free software: you can redistribute it and/or modify |
1060 | +# it under the terms of the GNU General Public License as published by |
1061 | +# the Free Software Foundation, either version 3 of the License, or |
1062 | +# (at your option) any later version. |
1063 | +# |
1064 | +# This program is distributed in the hope that it will be useful, |
1065 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1066 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1067 | +# GNU General Public License for more details. |
1068 | +# |
1069 | +# You should have received a copy of the GNU General Public License |
1070 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
1071 | +# |
1072 | + |
1073 | +import configparser |
1074 | +import logging |
1075 | +import os |
1076 | + |
1077 | +from telegram.common import options |
1078 | + |
1079 | +logger = logging.getLogger(__name__) |
1080 | +config_stack = None |
1081 | + |
1082 | +DEFAULT_CONF = 'ubuntu-system-tests.conf' |
1083 | +KEY_DEFAULT = 'default' |
1084 | + |
1085 | + |
1086 | +CONFIG_OPTIONS = [ |
1087 | + options.Option( |
1088 | + 'device_serial', help_string='Device serial'), |
1089 | + options.Option( |
1090 | + 'device_password', help_string='Device password', mandatory=True), |
1091 | + options.Option( |
1092 | + 'output_dir', mandatory=True, |
1093 | + help_string='Directory to store the tests results and artifacts.\n' |
1094 | + 'WARNING: This directory will have all existing content ' |
1095 | + 'deleted!'), |
1096 | + options.Option( |
1097 | + 'sim_0_pin', mandatory=True, |
1098 | + help_string='SIM pin for the card in the first slot'), |
1099 | + options.Option( |
1100 | + 'sim_1_pin', |
1101 | + help_string='SIM pin for the card in the second slot'), |
1102 | + options.Option( |
1103 | + 'wifi_ssid', mandatory=True, |
1104 | + help_string='Wi-Fi SSID used to connect during setup wizard'), |
1105 | + options.Option( |
1106 | + 'wifi_password', mandatory=True, |
1107 | + help_string='Wi-Fi password used to connect during setup wizard'), |
1108 | + options.Option( |
1109 | + 'device_security', default='Passcode', |
1110 | + help_string='The security method to select during setup wizard'), |
1111 | + options.Option( |
1112 | + 'bluetooth_device_name', |
1113 | + help_string='Name of a nearby bluetooth pairing device'), |
1114 | + options.Option( |
1115 | + 'device_phone_number', |
1116 | + help_string="The phone number of the SIM card inserted in the first " |
1117 | + "SIM slot. This must be formatted exactly as you would " |
1118 | + "dial it."), |
1119 | + options.Option( |
1120 | + 'device_phone_number2', |
1121 | + help_string="The phone number of the SIM card inserted in the second " |
1122 | + "SIM slot. If the device has only one SIM slot, you can " |
1123 | + "leave this blank. This must be formatted exactly as you " |
1124 | + "would dial it."), |
1125 | + options.Option( |
1126 | + 'telephony_service_number1', |
1127 | + help_string="The phone number to call and message from " |
1128 | + "in the telephony service. In Twilio go to " |
1129 | + "https://www.twilio.com/user/account/" |
1130 | + "phone-numbers/incoming and click on the number " |
1131 | + "you want to use, then copy the 'Phone Number' " |
1132 | + "field exactly."), |
1133 | + options.Option( |
1134 | + 'telephony_service_number2', |
1135 | + help_string="The second phone number to call and message from " |
1136 | + "in the telephony service. In Twilio go to " |
1137 | + "https://www.twilio.com/user/account/" |
1138 | + "phone-numbers/incoming and click on the number " |
1139 | + "you want to use, then copy the 'Phone Number' " |
1140 | + "field exactly."), |
1141 | + options.Option( |
1142 | + # this is a private key, that will not be exported to |
1143 | + # autopilot directly |
1144 | + '_twilio_account_sid', mandatory=True, |
1145 | + help_string='Account SID for Twilio. Please log into ' |
1146 | + 'https://www.twilio.com/login ' |
1147 | + 'and select \'Dashboard -> Show API Credentials\'.' |
1148 | + 'Then copy and paste the Account SID value here.'), |
1149 | + options.Option( |
1150 | + # this is a private key, that will not be exported to |
1151 | + # autopilot directly |
1152 | + '_twilio_auth_token', mandatory=True, |
1153 | + help_string='Auth token for Twilio account. Please log into ' |
1154 | + 'https://www.twilio.com/login ' |
1155 | + 'and select \'Dashboard -> Show API Credentials\'.' |
1156 | + 'Then copy and paste the Auth token value here.'), |
1157 | + options.Option( |
1158 | + # this is a private key, that will not be exported to |
1159 | + # autopilot directly |
1160 | + 'max_unity8_retry_delay', default=30000, |
1161 | + help_string='The boundary for how long we should be retrying until ' |
1162 | + 'unity8 is started'), |
1163 | + options.Option( |
1164 | + 'app_startup_cold_runs', default=0, |
1165 | + help_string='How many iterations to run for the cold start app ' |
1166 | + 'performance tests?'), |
1167 | + options.Option( |
1168 | + 'app_startup_hot_runs', default=0, |
1169 | + help_string='How many iterations to run for the hot start app ' |
1170 | + 'performance tests?'), |
1171 | + options.Option( |
1172 | + 'email_outlook', default='platform_qa_test@outlook.com', |
1173 | + help_string='@outlook.com email address to use for email tests'), |
1174 | + options.Option( |
1175 | + 'password_outlook', mandatory=True, |
1176 | + help_string='@outlook.com password to use for email tests'), |
1177 | + options.Option( |
1178 | + 'email_yahoo', default='platform_qa_test_account@yahoo.com', |
1179 | + help_string='@yahoo.com email address to use for email tests'), |
1180 | + options.Option( |
1181 | + 'password_yahoo', mandatory=True, |
1182 | + help_string='@yahoo.com password to use for email tests'), |
1183 | + options.Option( |
1184 | + 'username_imap', default='platform-qa-test-account', |
1185 | + help_string='IMAP username to use for email tests'), |
1186 | + options.Option( |
1187 | + 'password_imap', mandatory=True, |
1188 | + help_string='IMAP password to use for email tests'), |
1189 | + options.Option( |
1190 | + 'pictures_scalability_runs', |
1191 | + help_string='The different loads used for scalability pictures tests ' |
1192 | + 'separated by comma'), |
1193 | + options.Option( |
1194 | + '_practitest_project_id', |
1195 | + help_string='Practitest project ID to use for retrieving test lists.'), |
1196 | + options.Option( |
1197 | + '_practitest_api_token', |
1198 | + help_string='Practitest api token used for authentication.'), |
1199 | + options.Option( |
1200 | + 'country_sim', default='United States', |
1201 | + help_string='The name of the country of the SIM card to use for ' |
1202 | + 'telegram login'), |
1203 | +] |
1204 | + |
1205 | + |
1206 | +def get_user_config_dir(): |
1207 | + """Return the path to the user configuration directory.""" |
1208 | + conf_dir = os.environ.get( |
1209 | + 'XDG_CONFIG_HOME', os.path.expanduser('~/.config')) |
1210 | + return conf_dir |
1211 | + |
1212 | + |
1213 | +def get_device_config_file_path(): |
1214 | + """Return the path of the config file copied to the device.""" |
1215 | + return '/tmp/ubuntu-system-tests.conf' |
1216 | + |
1217 | + |
1218 | +def get_device_config_section(): |
1219 | + """Return the name of config section to use.""" |
1220 | + return os.environ.get('CONFIG_SECTION') |
1221 | + |
1222 | + |
1223 | +def get_config_stack_from_file(file_path, config_section=None): |
1224 | + """Return config stack from specified file path.""" |
1225 | + config = UbuntuSystemTestsConfig(file_path, section=config_section) |
1226 | + config.get_config_from_file() |
1227 | + return config |
1228 | + |
1229 | + |
1230 | +def get_device_config_stack(): |
1231 | + """Return the config stack variable""" |
1232 | + global config_stack |
1233 | + if not config_stack: |
1234 | + config_stack = get_config_stack_from_file( |
1235 | + get_device_config_file_path(), get_device_config_section()) |
1236 | + return config_stack |
1237 | + |
1238 | + |
1239 | +def get_test_config_values(config_stack): |
1240 | + """ Return a string containing the comma separated key=value options. |
1241 | + The list includes the config values and the temporal ones as well |
1242 | + """ |
1243 | + return config_stack.get_autopilot_config_string() |
1244 | + |
1245 | + |
1246 | +class UbuntuSystemTestsConfig(): |
1247 | + |
1248 | + """Class to get and save test configuration data.""" |
1249 | + |
1250 | + def __init__(self, file_name=None, section=None, options=None): |
1251 | + """ |
1252 | + Construct the config and parser object. |
1253 | + :param file_name: Name of config file to load. Default file is used if |
1254 | + value is not specified. |
1255 | + :param section: Name of section to use in config file. Default section |
1256 | + is used if not specified. |
1257 | + :param options: List of options that should be specified in config. |
1258 | + Default list of options is used if not specified. |
1259 | + """ |
1260 | + user_config_dir = get_user_config_dir() |
1261 | + if not os.path.exists(user_config_dir): |
1262 | + os.mkdir(user_config_dir) |
1263 | + self.file_path = os.path.join( |
1264 | + user_config_dir, file_name or DEFAULT_CONF) |
1265 | + self.section = section or KEY_DEFAULT |
1266 | + self.parser = configparser.ConfigParser( |
1267 | + allow_no_value=True, empty_lines_in_values=False, |
1268 | + default_section=KEY_DEFAULT) |
1269 | + self.config = {} |
1270 | + self.options = options or CONFIG_OPTIONS |
1271 | + |
1272 | + def set(self, option_name, value): |
1273 | + """Set a config value. |
1274 | + :param option_name: Name of config option. |
1275 | + :param value: Value to set. |
1276 | + """ |
1277 | + self.config[option_name] = value |
1278 | + self.save() |
1279 | + |
1280 | + def get(self, option_name, default=''): |
1281 | + """Get a config value. |
1282 | + :param option_name: Name of config option to get. |
1283 | + :param default: Value to return as default if item doesn't exist. |
1284 | + :return: Config option value if it exists. If the config option itself |
1285 | + doesn't exist, return None. Otherwise if the option exists but no value |
1286 | + is defined return the default value.""" |
1287 | + return self.config.get(option_name, default) |
1288 | + |
1289 | + def save(self): |
1290 | + """Save the config to file.""" |
1291 | + mode = 'r+' if os.path.exists(self.file_path) else 'w' |
1292 | + with open(self.file_path, mode) as f: |
1293 | + self.parser.write(f) |
1294 | + |
1295 | + def get_config_from_string(self, string): |
1296 | + """Load config from a string. This is used for selftests only. |
1297 | + :param string: Config string to load from. |
1298 | + """ |
1299 | + self.parser.read_string(string) |
1300 | + self._save_config_for_section() |
1301 | + |
1302 | + def get_config_from_file(self): |
1303 | + """Load config from file.""" |
1304 | + self.parser.read(self.file_path) |
1305 | + self._save_config_for_section() |
1306 | + |
1307 | + def _save_config_for_section(self): |
1308 | + """Save the current config for the specified section only.""" |
1309 | + self.config = self.parser[self.section] |
1310 | + |
1311 | + def get_missing_options(self, silent=False): |
1312 | + """Check through each required option and get a value for each one |
1313 | + that is not present. |
1314 | + :param silent: Whether to query stdin for an input value or take a |
1315 | + default value where it exists. |
1316 | + """ |
1317 | + save_required = False |
1318 | + for option in self.options: |
1319 | + if option.name in self.config: |
1320 | + # name exists, check if its mandatory and if a value exists |
1321 | + if option.mandatory and not self.config.get(option.name): |
1322 | + # mandatory and no value exists, so get one |
1323 | + self._get_option_value(option, silent) |
1324 | + save_required = True |
1325 | + else: |
1326 | + # option name not in config, get a value |
1327 | + self._get_option_value(option, silent) |
1328 | + save_required = True |
1329 | + self._save_if_required(save_required) |
1330 | + |
1331 | + def _save_if_required(self, save_required): |
1332 | + """Save config if it is required. |
1333 | + :param save_required: Whether to save or not. |
1334 | + """ |
1335 | + if save_required: |
1336 | + self.save() |
1337 | + |
1338 | + def _get_option_value(self, option, silent): |
1339 | + """Request a value for specified option. |
1340 | + :param option: Required option. |
1341 | + :param silent: Whether to query stdin or take default value. |
1342 | + """ |
1343 | + if silent: |
1344 | + default = option.default |
1345 | + if default: |
1346 | + self.config[option.name] = option.default |
1347 | + logger.warning( |
1348 | + 'In silent mode no value specified for option: "{o}". ' |
1349 | + 'Using default value "{v}".'.format( |
1350 | + o=option.name, v=default)) |
1351 | + else: |
1352 | + logger.warning( |
1353 | + 'In silent mode no default value specified for option: ' |
1354 | + '"{o}". Continuing with value unset.'.format( |
1355 | + o=option.name)) |
1356 | + else: |
1357 | + self._get_option_value_from_stdin(option) |
1358 | + |
1359 | + def _get_option_value_from_stdin(self, option): |
1360 | + """Request option value from stdin. |
1361 | + :param option: Required option. |
1362 | + """ |
1363 | + help_msg = self._get_option_help_text(option) |
1364 | + print(help_msg, end='') |
1365 | + value = self._get_value_from_user_or_default(option) |
1366 | + self.config[option.name] = value |
1367 | + |
1368 | + def _get_option_help_text(self, option): |
1369 | + """Return help message for specified option. |
1370 | + :param option: Required option. |
1371 | + """ |
1372 | + help_msg = option.help_string |
1373 | + default = option.default |
1374 | + if default: |
1375 | + help_msg += ' (leave blank to use default value: {})'.format( |
1376 | + default) |
1377 | + elif not option.mandatory: |
1378 | + help_msg += ' (leave blank if not required)' |
1379 | + help_msg += ': ' |
1380 | + return help_msg |
1381 | + |
1382 | + def _get_value_from_user_or_default(self, option): |
1383 | + """Return value from stdin or default value if no stdin value.""" |
1384 | + return input() or option.default |
1385 | + |
1386 | + def get_autopilot_config_string(self): |
1387 | + """Return the configuration in a string usable by Autopilot. |
1388 | + |
1389 | + That is, a list of key=value pairs serparated by comma. |
1390 | + |
1391 | + Any keys starting with _ will be ignored. |
1392 | + |
1393 | + """ |
1394 | + config = '' |
1395 | + for key, value in self.config.items(): |
1396 | + if not key.startswith('_'): |
1397 | + config += '{k}={v},'.format(k=key, v=value) |
1398 | + |
1399 | + # remove trailing ',' if it exists |
1400 | + if config.endswith(','): |
1401 | + config = config[:-1] |
1402 | + return config |
1403 | |
1404 | === added file 'telegram/autopilot/telegram/common/options.py' |
1405 | --- telegram/autopilot/telegram/common/options.py 1970-01-01 00:00:00 +0000 |
1406 | +++ telegram/autopilot/telegram/common/options.py 2016-11-14 11:39:33 +0000 |
1407 | @@ -0,0 +1,37 @@ |
1408 | +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
1409 | + |
1410 | +# |
1411 | +# Ubuntu System Tests |
1412 | +# Copyright (C) 2016 Canonical |
1413 | +# |
1414 | +# This program is free software: you can redistribute it and/or modify |
1415 | +# it under the terms of the GNU General Public License as published by |
1416 | +# the Free Software Foundation, either version 3 of the License, or |
1417 | +# (at your option) any later version. |
1418 | +# |
1419 | +# This program is distributed in the hope that it will be useful, |
1420 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1421 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1422 | +# GNU General Public License for more details. |
1423 | +# |
1424 | +# You should have received a copy of the GNU General Public License |
1425 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
1426 | +# |
1427 | + |
1428 | + |
1429 | +class Option(): |
1430 | + |
1431 | + """Class to represent configuration option.""" |
1432 | + |
1433 | + def __init__(self, name, help_string, default=None, mandatory=False): |
1434 | + """ |
1435 | + Construct the Option object. |
1436 | + :param name: Name of option. |
1437 | + :param help_string: Help message to explain option to user. |
1438 | + :param default: Default value for option. |
1439 | + :param mandatory: Whether the option is mandatory or not. |
1440 | + """ |
1441 | + self.name = name |
1442 | + self.help_string = help_string |
1443 | + self.default = str(default) if default else None |
1444 | + self.mandatory = mandatory |
1445 | |
1446 | === added file 'telegram/autopilot/telegram/common/ssh.py' |
1447 | --- telegram/autopilot/telegram/common/ssh.py 1970-01-01 00:00:00 +0000 |
1448 | +++ telegram/autopilot/telegram/common/ssh.py 2016-11-14 11:39:33 +0000 |
1449 | @@ -0,0 +1,199 @@ |
1450 | +#!/usr/bin/env python3 |
1451 | +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
1452 | + |
1453 | +# |
1454 | +# Ubuntu System Tests |
1455 | +# Copyright (C) 2015 Canonical |
1456 | +# |
1457 | +# This program is free software: you can redistribute it and/or modify |
1458 | +# it under the terms of the GNU General Public License as published by |
1459 | +# the Free Software Foundation, either version 3 of the License, or |
1460 | +# (at your option) any later version. |
1461 | +# |
1462 | +# This program is distributed in the hope that it will be useful, |
1463 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1464 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1465 | +# GNU General Public License for more details. |
1466 | +# |
1467 | +# You should have received a copy of the GNU General Public License |
1468 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
1469 | +# |
1470 | + |
1471 | +import getpass |
1472 | +import glob |
1473 | +import os |
1474 | +import re |
1475 | +import socket |
1476 | +import stat |
1477 | +import subprocess |
1478 | + |
1479 | +from ubuntu_system_tests.common import ( |
1480 | + get_random_string, |
1481 | + delete_file |
1482 | +) |
1483 | + |
1484 | +SSH_IP = 'SSH_IP' |
1485 | +SSH_PASSPHRASE = 'SSH_PASSPHRASE' |
1486 | +SSH_PRIVATE_KEY = 'SSH_PRIVATE_KEY' |
1487 | +SSH_USER = 'SSH_USER' |
1488 | + |
1489 | + |
1490 | +def get_ssh_ip_address(): |
1491 | + """Return ssh passphrase value.""" |
1492 | + return os.environ.get(SSH_IP) |
1493 | + |
1494 | + |
1495 | +def get_ssh_passphrase(): |
1496 | + """Return ssh passphrase value.""" |
1497 | + return os.environ.get(SSH_PASSPHRASE) |
1498 | + |
1499 | + |
1500 | +def get_ssh_private_key(): |
1501 | + """Return path to ssh private key file.""" |
1502 | + return os.environ.get(SSH_PRIVATE_KEY) |
1503 | + |
1504 | + |
1505 | +def get_ssh_user(): |
1506 | + """Return ssh username value.""" |
1507 | + return os.environ.get(SSH_USER) |
1508 | + |
1509 | + |
1510 | +def _get_local_ip_address(): |
1511 | + """ Retrieve the local ip address |
1512 | + :return: The ip obtained from the socket connection |
1513 | + """ |
1514 | + ip = '127.0.0.1' |
1515 | + try: |
1516 | + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) |
1517 | + s.connect(("8.8.8.8", 80)) |
1518 | + ip = s.getsockname()[0] |
1519 | + finally: |
1520 | + s.close() |
1521 | + return ip |
1522 | + |
1523 | + |
1524 | +def _get_set_env_var_command(name, value): |
1525 | + """Return command to set environment variable on device.""" |
1526 | + return ['--env={n}={v}'.format(n=name, v=value)] |
1527 | + |
1528 | + |
1529 | +def _get_copy_file_to_device_command(src, dest): |
1530 | + """Return command to copy a file to the device.""" |
1531 | + return ['--copy', '{s}:{d}'.format(s=src, d=dest)] |
1532 | + |
1533 | + |
1534 | +def get_ssh_config_commands(): |
1535 | + """ Retrieve a private key that can be used to connect to the host and add |
1536 | + the public key to the authorized_keys if it is not included yet. If either |
1537 | + it is not required to configure ssh or the ssh password is defined, |
1538 | + keypairs are not used and the function return None |
1539 | + """ |
1540 | + cmds = [] |
1541 | + cmds.extend(_get_set_env_var_command(SSH_IP, _get_local_ip_address())) |
1542 | + cmds.extend(_get_set_env_var_command(SSH_USER, getpass.getuser())) |
1543 | + |
1544 | + # Add the private key and the passphrase when it is needed |
1545 | + private_key = get_valid_key() |
1546 | + if not private_key: |
1547 | + private_key, public_key = generate_keypair(get_random_string(10)) |
1548 | + add_public_key_to_ssh_uthorized_keys(public_key) |
1549 | + os.remove(public_key) |
1550 | + |
1551 | + device_key_file = get_device_keyfile_path(private_key) |
1552 | + cmds.extend(_get_set_env_var_command( |
1553 | + SSH_PASSPHRASE, _get_key_passprhase(private_key))) |
1554 | + cmds.extend(_get_set_env_var_command(SSH_PRIVATE_KEY, device_key_file)) |
1555 | + cmds.extend(_get_copy_file_to_device_command(private_key, device_key_file)) |
1556 | + return cmds |
1557 | + |
1558 | + |
1559 | +def _get_key_passprhase(private_key): |
1560 | + """ Get the passphrase from the name, None if it is not found """ |
1561 | + keyname = os.path.basename(private_key) |
1562 | + match = re.search(r'test_(.+)_key', keyname) |
1563 | + if match: |
1564 | + return match.group(1) |
1565 | + else: |
1566 | + return |
1567 | + |
1568 | + |
1569 | +def _get_ssh_authorized_keys_path(): |
1570 | + path = os.path.join(os.path.expanduser('~'), '.ssh', 'authorized_keys') |
1571 | + directory = os.path.dirname(path) |
1572 | + if not os.path.exists(directory): |
1573 | + os.makedirs(directory) |
1574 | + if not os.path.exists(path): |
1575 | + file = open(path, 'w') |
1576 | + file.close() |
1577 | + return path |
1578 | + |
1579 | + |
1580 | +def is_authorized_key(id): |
1581 | + """ Indicate if the comment it is part of the ssh authorized_keys file |
1582 | + :param id: a string used to identify the public key. Currently the |
1583 | + passphrase is being used for that |
1584 | + """ |
1585 | + authorized_keys = _get_ssh_authorized_keys_path() |
1586 | + command_check = ['grep', '"{c}"'.format(c=id), authorized_keys] |
1587 | + return subprocess.call(command_check, stdout=subprocess.PIPE) == 0 |
1588 | + |
1589 | + |
1590 | +def add_public_key_to_ssh_uthorized_keys(public_key): |
1591 | + """ Add the public key to the ssh authorized_keys if is not included yet""" |
1592 | + # In case the public key is not authorized yet, add it to the |
1593 | + # authorized_keys file |
1594 | + authorized_keys = _get_ssh_authorized_keys_path() |
1595 | + command_add = 'cat {public_key} >> {authorized_keys}'.format( |
1596 | + public_key=public_key, authorized_keys=authorized_keys) |
1597 | + subprocess.call(command_add, shell=True) |
1598 | + |
1599 | + |
1600 | +def get_valid_key(): |
1601 | + """ Retrieve a private key which has its public key is already authorized |
1602 | + to be used through ssh |
1603 | + """ |
1604 | + all_keys = get_all_defined_keys() |
1605 | + for key in all_keys: |
1606 | + passphrase = _get_key_passprhase(key) |
1607 | + if passphrase and is_authorized_key(passphrase): |
1608 | + return key |
1609 | + return |
1610 | + |
1611 | + |
1612 | +def get_all_defined_keys(): |
1613 | + """ Retrieve the keys already saved in the tmp dir """ |
1614 | + return glob.glob('/tmp/test_*_key') |
1615 | + |
1616 | + |
1617 | +def generate_keypair(passphrase): |
1618 | + """ Create a pair of keys with the passphrase as part of the key names """ |
1619 | + keypath = '/tmp/test_{}_key'.format(passphrase) |
1620 | + command = 'ssh-keygen -t rsa -b 4096 -C "{p}" -P "{p}" -f {k} -q' |
1621 | + command = command.format(p=passphrase, |
1622 | + k=keypath) |
1623 | + subprocess.check_call(command, shell=True) |
1624 | + return keypath, keypath + '.pub' |
1625 | + |
1626 | + |
1627 | +def get_device_keyfile_path(filepath): |
1628 | + """Return the path of the config file copied to the device.""" |
1629 | + return os.path.join('/tmp', os.path.basename(filepath)) |
1630 | + |
1631 | + |
1632 | +def prepare_device_keys(): |
1633 | + """ Prepare the keyfile to be used by changing the ownership and the |
1634 | + permissions. These changes are done when other ssh authentication |
1635 | + mechanisms have not being selected |
1636 | + """ |
1637 | + passphrase = get_ssh_passphrase() |
1638 | + key_file = get_ssh_private_key() |
1639 | + |
1640 | + if passphrase and key_file and os.path.isfile(key_file): |
1641 | + os.chown(key_file, os.getuid(), os.getgid()) |
1642 | + os.chmod(key_file, stat.S_IREAD) |
1643 | + |
1644 | + |
1645 | +def ensure_device_keyfile_deleted(): |
1646 | + """ Delete the private key file in the device when required """ |
1647 | + key_file = get_ssh_private_key() |
1648 | + not key_file or delete_file(key_file) |
1649 | |
1650 | === added file 'telegram/autopilot/telegram/common/utils.py' |
1651 | --- telegram/autopilot/telegram/common/utils.py 1970-01-01 00:00:00 +0000 |
1652 | +++ telegram/autopilot/telegram/common/utils.py 2016-11-14 11:39:33 +0000 |
1653 | @@ -0,0 +1,87 @@ |
1654 | +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
1655 | + |
1656 | +# |
1657 | +# Ubuntu System Tests |
1658 | +# Copyright (C) 2015 Canonical |
1659 | +# |
1660 | +# This program is free software: you can redistribute it and/or modify |
1661 | +# it under the terms of the GNU General Public License as published by |
1662 | +# the Free Software Foundation, either version 3 of the License, or |
1663 | +# (at your option) any later version. |
1664 | +# |
1665 | +# This program is distributed in the hope that it will be useful, |
1666 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1667 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1668 | +# GNU General Public License for more details. |
1669 | +# |
1670 | +# You should have received a copy of the GNU General Public License |
1671 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
1672 | +# |
1673 | + |
1674 | +import inspect |
1675 | +import os |
1676 | +import random |
1677 | +import shutil |
1678 | +import string |
1679 | + |
1680 | + |
1681 | +def clean_dir(dir_path): |
1682 | + """Delete all the content of the directory""" |
1683 | + if os.path.isdir(dir_path): |
1684 | + for obj in os.listdir(dir_path): |
1685 | + _delete(os.path.join(dir_path, obj)) |
1686 | + |
1687 | + |
1688 | +def _delete(obj): |
1689 | + """ Delete an object which could be either a file or a dir """ |
1690 | + if os.path.isfile(obj): |
1691 | + os.remove(obj) |
1692 | + else: |
1693 | + shutil.rmtree(obj, True) |
1694 | + |
1695 | + |
1696 | +def delete_file(file_name): |
1697 | + """Delete the file passed as parameter. In case the file does not |
1698 | + exist, the deletion is skipped""" |
1699 | + if os.path.isfile(file_name): |
1700 | + os.unlink(file_name) |
1701 | + |
1702 | + |
1703 | +def get_random_string(length=10): |
1704 | + """Get a string with random content""" |
1705 | + return ''.join(random.choice(string.ascii_uppercase) for i in |
1706 | + range(length)) |
1707 | + |
1708 | + |
1709 | +def get_tests_ids_to_run(tests_module=None, testsuite_list_filepath=None): |
1710 | + """Return a list of the test ids to run in the test bed. |
1711 | + |
1712 | + :param tests_module: The module that contains the Ubuntu System Tests. |
1713 | + Default value is ubuntu_system_tests.tests. Currently, a value other |
1714 | + than the default is used only for self-testing. |
1715 | + |
1716 | + """ |
1717 | + tests_from_config = get_tests_to_run() |
1718 | + if tests_from_config: |
1719 | + return tests_from_config.split() |
1720 | + |
1721 | + # If we do this at the module level then we need to have unity8 and UITK on |
1722 | + # the host and would rather avoid this |
1723 | + from ubuntu_system_tests import external_tests |
1724 | + test_ids = external_tests.get_external_test_ids(testsuite_list_filepath) |
1725 | + |
1726 | + if tests_module is None: |
1727 | + # We delay the import so this is only executed in the test bed, not on |
1728 | + # the host which might have a different version of the libraries used |
1729 | + # in the system tests. |
1730 | + from ubuntu_system_tests import tests |
1731 | + tests_module = tests |
1732 | + |
1733 | + if inspect.ismodule(tests_module): |
1734 | + test_ids.append(tests_module.__name__) |
1735 | + |
1736 | + return test_ids |
1737 | + |
1738 | + |
1739 | +def get_tests_to_run(): |
1740 | + return os.getenv('TESTS_TO_RUN') |
1741 | |
1742 | === added file 'telegram/autopilot/telegram/emulators.py' |
1743 | --- telegram/autopilot/telegram/emulators.py 1970-01-01 00:00:00 +0000 |
1744 | +++ telegram/autopilot/telegram/emulators.py 2016-11-14 11:39:33 +0000 |
1745 | @@ -0,0 +1,550 @@ |
1746 | +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
1747 | +# Copyright 2016 Canonical |
1748 | +# |
1749 | +# This file is part of telegram-app. |
1750 | +# |
1751 | +# telegram-app is free software: you can redistribute it and/or modify it |
1752 | +# under the terms of the GNU General Public License version 3, as published |
1753 | +# by the Free Software Foundation. |
1754 | + |
1755 | + |
1756 | +"""Telegram app autopilot emulators.""" |
1757 | + |
1758 | +from autopilot import logging as autopilot_logging |
1759 | +from autopilot.introspection.dbus import StateNotFoundError |
1760 | +from autopilot.utilities import sleep |
1761 | +from autopilot import platform |
1762 | + |
1763 | +from ubuntuuitoolkit import emulators as toolkit_emulators |
1764 | +from ubuntuuitoolkit._custom_proxy_objects import _common |
1765 | +from ubuntuuitoolkit._custom_proxy_objects._common import is_maliit_process_running |
1766 | +#from ubuntu_keyboard.emulators.keyboard import Keyboard as UbuntuKeyboard |
1767 | +#from address_book_app import address_book |
1768 | + |
1769 | +from telegram import utilities |
1770 | + |
1771 | +import logging |
1772 | +import time |
1773 | +import dbus |
1774 | + |
1775 | +# from telegram.helpers.notifications.utils import Notifications |
1776 | + |
1777 | + |
1778 | +#logger = logging.getLogger(__name__) |
1779 | +class MainView(toolkit_emulators.MainView): |
1780 | + |
1781 | + def __init__(self, *args): |
1782 | + super(MainView, self).__init__(*args) |
1783 | + self.pointing_device = toolkit_emulators.get_pointing_device() |
1784 | + self._account_page = None |
1785 | + self._apl = None |
1786 | + self._content_hub_popup = None |
1787 | + self._content_picker = None |
1788 | + self._content_hub_app_gallery = None |
1789 | + self._confirmation_dialog = None |
1790 | + |
1791 | + @property |
1792 | + def account_page(self): |
1793 | + if self._account_page is None: |
1794 | + try: |
1795 | + self._account_page = self.wait_select_single(AccountPage, objectName="accountPage", active=True) |
1796 | + except StateNotFoundError: |
1797 | + raise RuntimeError("User needs to be logged on") |
1798 | + return self._account_page |
1799 | + |
1800 | + @property |
1801 | + def apl(self): |
1802 | + if self._apl is None: |
1803 | + self._apl = self.wait_select_single(AdaptivePageLayout, objectName="APL", active=True) |
1804 | + return self._apl |
1805 | + |
1806 | + @property |
1807 | + def content_picker(self): |
1808 | + if self._content_hub_popup is None: |
1809 | + self._content_hub_popup = self.wait_select_single(objectName="mediaImportPopup") |
1810 | + self._content_picker = self._content_hub_popup.wait_select_single(objectName="contentPeerPicker") |
1811 | + return self._content_picker |
1812 | + |
1813 | + def select_content_hub_app(self, appName): |
1814 | + cp = self.content_picker |
1815 | + content_hub_gridviews = cp.select_many(objectName="responsiveGridViewGrid") |
1816 | + for gridview in content_hub_gridviews: |
1817 | + app_icon_labels = gridview.select_many(objectName="label") |
1818 | + if len(app_icon_labels) > 0: |
1819 | + for app_icon_label in app_icon_labels: |
1820 | + if appName in app_icon_label.text: |
1821 | + self.pointing_device.click_object(app_icon_label) |
1822 | + return |
1823 | + |
1824 | + @property |
1825 | + def confirmation_dialog(self): |
1826 | + if self._confirmation_dialog is None: |
1827 | + self._confirmation_dialog = self.wait_select_single(Dialog, objectName='confirmationDialog') |
1828 | + return self._confirmation_dialog |
1829 | + |
1830 | + def click_header_action(self, action): |
1831 | + """Click the action 'action' on the header""" |
1832 | + action = self.wait_select_single(objectName='%s_button' % action) |
1833 | + self.pointing_device.click_object(action) |
1834 | + |
1835 | + # def get_notifications_list(self): |
1836 | + # """Return a list of notifications currently being displayed.""" |
1837 | + # return self.wait_select_single(Notifications, objectName='notificationList') |
1838 | + |
1839 | + |
1840 | +class AdaptivePageLayout(toolkit_emulators.UbuntuUIToolkitEmulatorBase): |
1841 | + |
1842 | + def __init__(self, *args): |
1843 | + super(AdaptivePageLayout, self).__init__(*args) |
1844 | + self._intro_page = None |
1845 | + self._contacts_page = None |
1846 | + self._dialog_page = None |
1847 | + self._settings_page = None |
1848 | + self._profile_page = None |
1849 | + self._countries_page = None |
1850 | + self._auth_phone_page = None |
1851 | + self._auth_code_page = None |
1852 | + |
1853 | + @property |
1854 | + def intro_page(self): |
1855 | + if self._intro_page is None: |
1856 | + try: |
1857 | + self._intro_page = self.wait_select_single(IntroPage, objectName='introPage', active=True) |
1858 | + except StateNotFoundError: |
1859 | + raise RuntimeError("Intro page is not active") |
1860 | + return self._intro_page |
1861 | + |
1862 | + @property |
1863 | + def countries_page(self): |
1864 | + if self._countries_page is None: |
1865 | + self._countries_page = self.wait_select_single(AuthCountriesPage, objectName='countriesListPage', active=True) |
1866 | + return self._countries_page |
1867 | + |
1868 | + @property |
1869 | + def auth_phone_page(self): |
1870 | + if self._auth_phone_page is None: |
1871 | + self._auth_phone_page = self.wait_select_single(AuthNumberPage, objectName='authPhonePage', active=True) |
1872 | + return self._auth_phone_page |
1873 | + |
1874 | + @property |
1875 | + def auth_code_page(self): |
1876 | + if self._auth_code_page is None: |
1877 | + self._auth_code_page = self.wait_select_single(AuthCodePage, objectName='authCodePage', active=True) |
1878 | + return self._auth_code_page |
1879 | + |
1880 | + @property |
1881 | + def contacts_page(self): |
1882 | + if self._contacts_page is None: |
1883 | + self._contacts_page = self.wait_select_single(AccountContactsPage, objectName='accountContactsPage', active=True) |
1884 | + return self._contacts_page |
1885 | + |
1886 | + @property |
1887 | + def dialog_page(self): |
1888 | + if self._dialog_page is None: |
1889 | + self._dialog_page = self.wait_select_single(AccountDialogPage, objectName='dialogPage', active=True) |
1890 | + return self._dialog_page |
1891 | + |
1892 | + @property |
1893 | + def settings_page(self): |
1894 | + if self._settings_page is None: |
1895 | + self._settings_page = self.wait_select_single(AccountSettings, objectName="settingsPage", active=True) |
1896 | + return self._settings_page |
1897 | + |
1898 | + @property |
1899 | + def profile_page(self): |
1900 | + if self._profile_page is None: |
1901 | + self._profile_page = self.wait_select_single(ProfilePage, objectName="profilePage", active=True) |
1902 | + return self._profile_page |
1903 | + |
1904 | + def clear_profile_page(self): |
1905 | + self._profile_page = None |
1906 | + |
1907 | + |
1908 | +class IntroPage(toolkit_emulators.UbuntuUIToolkitEmulatorBase): |
1909 | + def __init__(self, *args): |
1910 | + super(IntroPage, self).__init__(*args) |
1911 | + |
1912 | + def press_start_messaging(self): |
1913 | + return self.pointing_device.click_object(self.wait_select_single(objectName="startMessagingButton")) |
1914 | + |
1915 | +class AccountPage(toolkit_emulators.UbuntuUIToolkitEmulatorBase): |
1916 | + |
1917 | + def open_account_panel(self): |
1918 | + self.click_action_button('navigationMenu') |
1919 | + account_panel = self.wait_select_single(AccountPanel, objectName='accountPanel') |
1920 | + account_panel.visible.wait_for(True) |
1921 | + return account_panel |
1922 | + |
1923 | + def get_mainview_header(self): |
1924 | + """Return the Header custom proxy object of the Page.""" |
1925 | + return self.get_root_instance().wait_select_single('MainView').get_header() |
1926 | + |
1927 | + def get_default_header(self): |
1928 | + try: |
1929 | + return self.wait_select_single('PageHeader', objectName='defaultHeader') |
1930 | + except: |
1931 | + raise RuntimeError('The Account Page has no header.') |
1932 | + |
1933 | + def click_action_button(self, action_name): |
1934 | + action = self.wait_select_single(objectName='%s_button' % action_name) |
1935 | + self.pointing_device.click_object(action) |
1936 | + |
1937 | + def get_dialog_list_page(self): |
1938 | + return self.wait_select_single(AccountDialogList, objectName='accountDialogList') |
1939 | + |
1940 | + |
1941 | +class AccountPanel(toolkit_emulators.UbuntuUIToolkitEmulatorBase): |
1942 | + |
1943 | + def get_account_panel_list(self): |
1944 | + return self.wait_select_single('AccountPanel', objectName='accountPanel') |
1945 | + |
1946 | + def get_account_panel_count(self): |
1947 | + return self.get_account_panel_list().count |
1948 | + |
1949 | + def get_account_panel_delegate(self, index): |
1950 | + return self.wait_select_single('AccountPanelItem', objectName='contact{}'.format(index)) |
1951 | + |
1952 | + def select_secret_chat(self): |
1953 | + action = self.wait_select_single('AccountPanelItem', objectName='secretChatItem') |
1954 | + self.pointing_device.click_object(action) |
1955 | + |
1956 | + def select_group_chat(self): |
1957 | + action = self.wait_select_single('AccountPanelItem', objectName='groupChatItem') |
1958 | + self.pointing_device.click_object(action) |
1959 | + |
1960 | + def select_contacts(self): |
1961 | + action = self.wait_select_single('AccountPanelItem', objectName='panelContacts') |
1962 | + self.pointing_device.click_object(action) |
1963 | + |
1964 | + def select_settings(self): |
1965 | + action = self.wait_select_single('AccountPanelItem', objectName='panelSettings') |
1966 | + self.pointing_device.click_object(action) |
1967 | + |
1968 | + |
1969 | +class AccountContactsPage(toolkit_emulators.UbuntuUIToolkitEmulatorBase): |
1970 | + |
1971 | + def __init__(self, *args): |
1972 | + super(AccountContactsPage, self).__init__(*args) |
1973 | + self._index_of_first_online_contact = None |
1974 | + |
1975 | + |
1976 | + def _get_contacts_list(self): |
1977 | + return self.wait_select_single('MultipleSelectionListView', objectName='contactList') |
1978 | + |
1979 | + def _get_contacts_count(self): |
1980 | + return self._get_contacts_list().count |
1981 | + |
1982 | + def _get_contact_delegate(self, index): |
1983 | + return self.wait_select_single( |
1984 | + 'TelegramContactsListItem', objectName='contact{}'.format(index)) |
1985 | + |
1986 | + def _click_action_button(self, action_name): |
1987 | + action = self.wait_select_single(objectName='%s_button' % action_name) |
1988 | + if (action): |
1989 | + self.pointing_device.click_object(action) |
1990 | + else: |
1991 | + raise StateNotFoundError(action_name) |
1992 | + |
1993 | + |
1994 | + def select_first_online_contact(self): |
1995 | + #Select first contact if online (User MUST be online) |
1996 | + delegate = None |
1997 | + for index in range(self._get_contacts_count()): |
1998 | + delegate = self._get_contact_delegate(index) |
1999 | + if (delegate.isOnline): |
2000 | + self._index_of_first_online_contact = index |
2001 | + break |
2002 | + |
2003 | + if delegate != None: |
2004 | + return delegate |
2005 | + else: |
2006 | + raise RuntimeError('Chat cannot be created. There are no online users') |
2007 | + |
2008 | + def select_second_contact(self): |
2009 | + if self._index_of_first_online_contact is None: |
2010 | + raise RuntimeError('Please select first online contact before selecting a second contact') |
2011 | + |
2012 | + #Select a second contact |
2013 | + delegate = None |
2014 | + for index in range(self._get_contacts_count()): |
2015 | + if index is not self._index_of_first_online_contact: |
2016 | + delegate = self._get_contact_delegate(index) |
2017 | + break |
2018 | + |
2019 | + if delegate != None: |
2020 | + return delegate |
2021 | + else: |
2022 | + raise RuntimeError('Chat cannot be created. Cannot select second contact') |
2023 | + |
2024 | + def select_contact_at_index(self, index): |
2025 | + delegate = self._get_contact_delegate(index) |
2026 | + return delegate |
2027 | + |
2028 | + def enter_group_chat_title(self, title): |
2029 | + text_field = self.wait_select_single('TextField', objectName='groupChatTextField') |
2030 | + utilities.enter_text_in_text_area(text_field, title) |
2031 | + self._click_action_button("createGroupChatOK") |
2032 | + |
2033 | + |
2034 | +class AccountDialogList(toolkit_emulators.UbuntuUIToolkitEmulatorBase): |
2035 | + |
2036 | + @property |
2037 | + def dialog_count(self): |
2038 | + return self._get_dialog_list().count |
2039 | + |
2040 | + def select_dialog_at_index(self, index): |
2041 | + selected_dialog = self._get_dialog_delegate(index) |
2042 | + self.pointing_device.click_object(selected_dialog) |
2043 | + |
2044 | + def select_new_secret_chat(self): |
2045 | + count = self.dialog_count |
2046 | + count_including_new_secret_chat = count + 1 |
2047 | + while (count != count_including_new_secret_chat): |
2048 | + count = self.dialog_count |
2049 | + self.select_first_dialog() |
2050 | + |
2051 | + def _get_dialog_list(self): |
2052 | + return self.wait_select_single(objectName='dialogListView') |
2053 | + |
2054 | + def _get_dialog_delegate(self, index): |
2055 | + return self.wait_select_single( |
2056 | + 'DialogsListItem', objectName='dialog{}'.format(index)) |
2057 | + |
2058 | + |
2059 | +class AccountDialogPage(toolkit_emulators.UbuntuUIToolkitEmulatorBase): |
2060 | + |
2061 | + def __init__(self, *args): |
2062 | + super(AccountDialogPage, self).__init__(*args) |
2063 | + self._account_message_list = None |
2064 | + self._message_area = None |
2065 | + |
2066 | + @property |
2067 | + def account_message_list(self): |
2068 | + if self._account_message_list is None: |
2069 | + self._account_message_list = self.wait_select_single(AccountMessageList, objectName="accountMessageList") |
2070 | + return self._account_message_list |
2071 | + |
2072 | + @property |
2073 | + def message_area(self): |
2074 | + if self._message_area is None: |
2075 | + self._message_area = self.wait_select_single(AccountSendMessage, objectName='accountSendMessageArea') |
2076 | + return self._message_area |
2077 | + |
2078 | + def enter_message(self, message): |
2079 | + text_area = self.message_area.select_text_area() |
2080 | + utilities.enter_text_in_text_area(text_area, message) |
2081 | + |
2082 | + def _get_sending_message_area(self): |
2083 | + return self.wait_select_single(AccountSendMessage, objectName='accountSendMessageArea') |
2084 | + |
2085 | + def select_chat_info(self): |
2086 | + self.pointing_device.click_object(self.wait_select_single(objectName='groupInfo_button')) |
2087 | + |
2088 | +class AccountMessageList(toolkit_emulators.UbuntuUIToolkitEmulatorBase): |
2089 | + |
2090 | + def __init__(self, *args): |
2091 | + super(AccountMessageList, self).__init__(*args) |
2092 | + self._messages = None |
2093 | + |
2094 | + @property |
2095 | + def messages(self): |
2096 | + if self._messages is None: |
2097 | + self._messages = self.wait_select_single('MultipleSelectionListView', objectName="messagesListView") |
2098 | + return self._messages |
2099 | + |
2100 | + def get_message_at_index(self, index): |
2101 | + return self.wait_select_single( |
2102 | + MessagesListItem, objectName='message{}'.format(index)) |
2103 | + |
2104 | + |
2105 | +class AccountSendMessage(toolkit_emulators.UbuntuUIToolkitEmulatorBase): |
2106 | + |
2107 | + def select_text_area(self): |
2108 | + return(self.wait_select_single('TextArea', objectName='sendMessageTextArea')) |
2109 | + |
2110 | + def select_attach_or_send(self): |
2111 | + self.pointing_device.click_object(self.wait_select_single(objectName='sendMouseArea')) |
2112 | + |
2113 | + def select_attach_sticker_option(self): |
2114 | + self.pointing_device.click_object(self.wait_select_single(objectName='stickerButton')) |
2115 | + |
2116 | + def select_attach_photo_option(self): |
2117 | + self.pointing_device.click_object(self.wait_select_single(objectName="panelPhoto")) |
2118 | + |
2119 | + def select_attach_video_option(self): |
2120 | + self.pointing_device.click_object(self.wait_select_single(objectName="panelVideo")) |
2121 | + |
2122 | + |
2123 | +class MessagesListItem(toolkit_emulators.UbuntuUIToolkitEmulatorBase): |
2124 | + |
2125 | + def __init__(self, *args): |
2126 | + super(MessagesListItem, self).__init__(*args) |
2127 | + self._message_status = None |
2128 | + self._message_status_image = None |
2129 | + self._message_label = None |
2130 | + self._account_message_media = None |
2131 | + |
2132 | + @property |
2133 | + def message_status(self): |
2134 | + self._message_status = self.wait_select_single(objectName="messageStatus") |
2135 | + return self._message_status |
2136 | + |
2137 | + @property |
2138 | + def message_status_image(self): |
2139 | + self._message_status_image = self.message_status.wait_select_single(objectName="statusImage") |
2140 | + return self._message_status_image |
2141 | + |
2142 | + @property |
2143 | + def message_label(self): |
2144 | + self._message_label = self.wait_select_single(objectName="messageText") |
2145 | + return self._message_label |
2146 | + |
2147 | + @property |
2148 | + def account_message_media(self): |
2149 | + self._account_message_media = self.wait_select_single(AccountMessageMedia, objectName="accountMessageMedia") |
2150 | + return self._account_message_media |
2151 | + |
2152 | + |
2153 | +class AccountMessageMedia(toolkit_emulators.UbuntuUIToolkitEmulatorBase): |
2154 | + |
2155 | + def __init__(self, *args): |
2156 | + super(AccountMessageMedia, self).__init__(*args) |
2157 | + self._media_message_status = None |
2158 | + self._media_message_status_image = None |
2159 | + |
2160 | + @property |
2161 | + def media_message_status(self): |
2162 | + self._media_message_status = self.wait_select_single(objectName="mediaMessageStatus") |
2163 | + return self._media_message_status |
2164 | + |
2165 | + @property |
2166 | + def media_message_status_image(self): |
2167 | + self._media_message_status_image = self.media_message_status.wait_select_single(objectName="statusImage") |
2168 | + return self._media_message_status_image |
2169 | + |
2170 | + |
2171 | +class AccountSettings(toolkit_emulators.UbuntuUIToolkitEmulatorBase): |
2172 | + |
2173 | + def __init__(self, *args): |
2174 | + super(AccountSettings, self).__init__(*args) |
2175 | + self._list_item_logout = None |
2176 | + self._settings_list = None |
2177 | + self._popup_logout = None |
2178 | + |
2179 | + @property |
2180 | + def settings_list(self): |
2181 | + if self._settings_list is None: |
2182 | + self._settings_list = self.wait_select_single(objectName='settingsList') |
2183 | + return self._settings_list |
2184 | + |
2185 | + @property |
2186 | + def list_item_logout(self): |
2187 | + if self._list_item_logout is None: |
2188 | + self._list_item_logout = self.wait_select_single(objectName="listItem_logout") |
2189 | + return self._list_item_logout |
2190 | + |
2191 | + def select_list_item_logout(self): |
2192 | + self.settings_list.swipe_to_bottom() |
2193 | + self.pointing_device.click_object(self.list_item_logout) |
2194 | + |
2195 | + |
2196 | +class ProfilePage(toolkit_emulators.UbuntuUIToolkitEmulatorBase): |
2197 | + |
2198 | + def __init__(self, *args): |
2199 | + super(ProfilePage, self).__init__(*args) |
2200 | + |
2201 | + @property |
2202 | + def _member_list_count(self): |
2203 | + return self._get_member_list().count |
2204 | + |
2205 | + def _get_member_list(self): |
2206 | + return self.wait_select_single(objectName='memberListView') |
2207 | + |
2208 | + def _get_member_delegate(self, index): |
2209 | + return self.wait_select_single( |
2210 | + 'TelegramContactsListItem', objectName='dialog{}'.format(index)) |
2211 | + |
2212 | + def profile_member_at_index(self,index): |
2213 | + return self._get_member_delegate(index) |
2214 | + |
2215 | + @property |
2216 | + def profile_user_name(self): |
2217 | + return self.wait_select_single(objectName="profileUserName") |
2218 | + |
2219 | + @property |
2220 | + def profile_user_phone_number(self): |
2221 | + return self.wait_select_single(objectName="profilePhoneNumber") |
2222 | + |
2223 | + @property |
2224 | + def profile_user_photo(self): |
2225 | + return self.wait_select_single(objectName="profileImageImport") |
2226 | + |
2227 | + def select_user_photo(self): |
2228 | + return self.wait_select_single(objectName="profileImage") |
2229 | + |
2230 | + @property |
2231 | + def switch_block(self): |
2232 | + return self.wait_select_single(objectName="switchBlock") |
2233 | + |
2234 | + def select_switch_block(self): |
2235 | + self.pointing_device.click_object(self.wait_select_single(objectName="switchBlock")) |
2236 | + |
2237 | + def select_switch_notification(self): |
2238 | + self.pointing_device.click_object(self.wait_select_single(objectName="switchNotification")) |
2239 | + |
2240 | + def select_back_button(self): |
2241 | + # if platform.model() == "Desktop": |
2242 | + # action = self.wait_select_single(objectName='apl_back_action_button') |
2243 | + # else: |
2244 | + action = self.wait_select_single(objectName='profileBack_button') |
2245 | + self.pointing_device.click_object(action) |
2246 | + |
2247 | +class AuthCountriesPage(toolkit_emulators.UbuntuUIToolkitEmulatorBase): |
2248 | + |
2249 | + def __init__(self, *args): |
2250 | + super(AuthCountriesPage, self).__init__(*args) |
2251 | + |
2252 | + def _click_action_button(self, action_name): |
2253 | + action = self.wait_select_single(objectName='%s_button' % action_name) |
2254 | + try: |
2255 | + self.pointing_device.click_object(action) |
2256 | + except: |
2257 | + raise StateNotFoundError(action_name) |
2258 | + |
2259 | + def profile_member_at_index(self,index): |
2260 | + return self._get_member_delegate(index) |
2261 | + |
2262 | + def enter_country_title_and_select(self, title): |
2263 | + # Select search icon |
2264 | + self._click_action_button("searchIcon") |
2265 | + # Type for country |
2266 | + text_field = self.wait_select_single('TextField', objectName='countryField') |
2267 | + utilities.enter_text_in_text_area(text_field, title) |
2268 | + # Select the search country |
2269 | + self.pointing_device.click_object(self.wait_select_single(objectName="united_kingdom")) |
2270 | + |
2271 | +class AuthNumberPage(toolkit_emulators.UbuntuUIToolkitEmulatorBase): |
2272 | + |
2273 | + def __init__(self, *args): |
2274 | + super(AuthNumberPage, self).__init__(*args) |
2275 | + |
2276 | + def enter_phone_number(self, title): |
2277 | + # Enter text |
2278 | + text_field = self.wait_select_single('TextField', objectName='phoneNumberEntry') |
2279 | + utilities.enter_text_in_text_area(text_field, title) |
2280 | + # Press Send Code button |
2281 | + self.pointing_device.click_object(self.wait_select_single(objectName="doneButton")) |
2282 | + |
2283 | +class AuthCodePage(toolkit_emulators.UbuntuUIToolkitEmulatorBase): |
2284 | + |
2285 | + def __init__(self, *args): |
2286 | + super(AuthCodePage, self).__init__(*args) |
2287 | + |
2288 | + def enter_code_in_textfield(self, title): |
2289 | + # Enter text |
2290 | + text_field = self.wait_select_single('TextField', objectName='verificationCodeEntry') |
2291 | + utilities.enter_text_in_text_area(text_field, title) |
2292 | + |
2293 | + def press_sign_in_button(self): |
2294 | + # Press 'Sign In' button |
2295 | + self.pointing_device.click_object(self.wait_select_single(objectName="signInButton")) |
2296 | \ No newline at end of file |
2297 | |
2298 | === added file 'telegram/autopilot/telegram/setup.py' |
2299 | --- telegram/autopilot/telegram/setup.py 1970-01-01 00:00:00 +0000 |
2300 | +++ telegram/autopilot/telegram/setup.py 2016-11-14 11:39:33 +0000 |
2301 | @@ -0,0 +1,57 @@ |
2302 | +#!/usr/bin/env python3 |
2303 | + |
2304 | +# |
2305 | +# Ubuntu System Tests |
2306 | +# Copyright (C) 2014 Canonical |
2307 | +# |
2308 | +# This program is free software: you can redistribute it and/or modify |
2309 | +# it under the terms of the GNU General Public License as published by |
2310 | +# the Free Software Foundation, either version 3 of the License, or |
2311 | +# (at your option) any later version. |
2312 | +# |
2313 | +# This program is distributed in the hope that it will be useful, |
2314 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
2315 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2316 | +# GNU General Public License for more details. |
2317 | +# |
2318 | +# You should have received a copy of the GNU General Public License |
2319 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
2320 | +# |
2321 | + |
2322 | +import sys |
2323 | +from setuptools import find_packages, setup |
2324 | + |
2325 | +assert sys.version_info >= (3,), 'Python 3 is required' |
2326 | + |
2327 | + |
2328 | +VERSION = '1.0' |
2329 | + |
2330 | + |
2331 | +setup( |
2332 | + name='ubuntu-system-tests', |
2333 | + version=VERSION, |
2334 | + description='Automated tests for Ubuntu Touch images.', |
2335 | + author='Canonical Platform QA Team', |
2336 | + author_email='qa-team@lists.canonical.com', |
2337 | + url='https://launchpad.net/ubuntu-system-tests', |
2338 | + license='GPLv3', |
2339 | + packages=find_packages(), |
2340 | + package_data={ |
2341 | + 'ubuntu_system_tests': ['tests/data/*/*'] |
2342 | + }, |
2343 | + install_requires=[ |
2344 | + 'chardet', |
2345 | + 'python-debian', |
2346 | + 'requests', |
2347 | + 'retrying', |
2348 | + ], |
2349 | + entry_points={ |
2350 | + 'console_scripts': [ |
2351 | + 'ubuntu-system-tests = ubuntu_system_tests.run:main' |
2352 | + ] |
2353 | + }, |
2354 | + test_suite='ubuntu_system_tests.selftests', |
2355 | + tests_require=[ |
2356 | + 'python-subunit', |
2357 | + ] |
2358 | +) |
2359 | |
2360 | === added directory 'telegram/autopilot/telegram/tests' |
2361 | === added file 'telegram/autopilot/telegram/tests/__init__.py' |
2362 | --- telegram/autopilot/telegram/tests/__init__.py 1970-01-01 00:00:00 +0000 |
2363 | +++ telegram/autopilot/telegram/tests/__init__.py 2016-11-14 11:39:33 +0000 |
2364 | @@ -0,0 +1,76 @@ |
2365 | +from autopilot.testcase import AutopilotTestCase |
2366 | +from autopilot import platform |
2367 | +from ubuntuuitoolkit import emulators as toolkit_emulators |
2368 | +from autopilot.input import Mouse, Touch, Pointer |
2369 | +from telegram import emulators |
2370 | +from os.path import abspath, dirname, join |
2371 | +from autopilot.matchers import Eventually |
2372 | +from testtools.matchers import Equals |
2373 | + |
2374 | +import fixtures |
2375 | +import ubuntuuitoolkit |
2376 | +import subprocess |
2377 | + |
2378 | +class TelegramAppTestCase(AutopilotTestCase): |
2379 | + |
2380 | + def __init__(self, *args): |
2381 | + super(TelegramAppTestCase, self).__init__(*args) |
2382 | + self._main_view = None |
2383 | + |
2384 | + @property |
2385 | + def main_view(self): |
2386 | + if self._main_view is None: |
2387 | + self._main_view = self.app.wait_select_single(emulators.MainView) |
2388 | + return self._main_view |
2389 | + |
2390 | + def setUp(self, parameter=""): |
2391 | + #self.pointing_device = Pointer(self.input_device_class.create()) |
2392 | + super(TelegramAppTestCase, self).setUp() |
2393 | + |
2394 | + subprocess.call(['pkill', 'telegram-app']) |
2395 | + |
2396 | + #Preconditions: Logged In |
2397 | + if platform.model() == "Desktop": |
2398 | + self.app = self.launch_desktop_application(parameter) |
2399 | + else: |
2400 | + self.app = self.launch_mobile_application(parameter) |
2401 | + self.assertThat(self.main_view.visible, Eventually(Equals(True))) |
2402 | + # self.check_user_has_logged_in() |
2403 | + |
2404 | + # if (self.check_user_has_logged_in()): |
2405 | + # self.assertThat(self.main_view.visible, Eventually(Equals(True))) |
2406 | + # else: |
2407 | + # raise RuntimeError("User must be logged in") |
2408 | + |
2409 | + |
2410 | + def launch_desktop_application(self, parameter): |
2411 | + #Setup the lib path environment variable using absolute path values, required by the app to access the necessary libs |
2412 | + library_path = abspath(join(dirname(__file__), '..', '..', '..', '..', 'build_desktop',)) |
2413 | + envValue = library_path + ':$LD_LIBRARY_PATH' |
2414 | + self.useFixture(fixtures.EnvironmentVariable('LD_LIBRARY_PATH',envValue)) |
2415 | + |
2416 | + #Launch the test application using absolute path values |
2417 | + full_path = abspath(join(dirname(__file__), '..', '..', '..', '..', 'build_desktop','lib','x86_64-linux-gnu','bin','telegram')) |
2418 | + print(full_path + " " + parameter) |
2419 | + return self.launch_test_application( |
2420 | + full_path, |
2421 | + parameter, |
2422 | + app_type='qt', |
2423 | + emulator_base=toolkit_emulators.UbuntuUIToolkitEmulatorBase) |
2424 | + |
2425 | + def launch_mobile_application(self, parameter): |
2426 | + return self.launch_click_package( |
2427 | + "com.ubuntu.telegram", |
2428 | + app_uris=['QT_LOAD_TESTABILITY=1'], |
2429 | + emulator_base=toolkit_emulators.UbuntuUIToolkitEmulatorBase) |
2430 | + |
2431 | + def check_user_has_logged_in(self): |
2432 | + account_page = self.main_view.account_page |
2433 | + self.assertThat(account_page.visible, Eventually(Equals(True))) |
2434 | + |
2435 | + # try: |
2436 | + # self.main_view.get_account_page() |
2437 | + # self.assertThat(self.main_view.account_page.visible, Eventually(Equals(True))) |
2438 | + # return True |
2439 | + # except: |
2440 | + # return False |
2441 | \ No newline at end of file |
2442 | |
2443 | === added file 'telegram/autopilot/telegram/tests/test_Logout.py' |
2444 | --- telegram/autopilot/telegram/tests/test_Logout.py 1970-01-01 00:00:00 +0000 |
2445 | +++ telegram/autopilot/telegram/tests/test_Logout.py 2016-11-14 11:39:33 +0000 |
2446 | @@ -0,0 +1,52 @@ |
2447 | +from telegram.tests import TelegramAppTestCase |
2448 | +from telegram import emulators |
2449 | + |
2450 | +import os |
2451 | +import dbus |
2452 | +import time |
2453 | +import datetime |
2454 | +import ubuntuuitoolkit |
2455 | + |
2456 | +from autopilot.matchers import Eventually |
2457 | +from testtools.matchers import Equals |
2458 | +from autopilot.utilities import sleep |
2459 | + |
2460 | + |
2461 | +#from autopilot import logging as autopilot_logging |
2462 | +#from telegram import displays_and_interactions as interactions |
2463 | + |
2464 | + |
2465 | +class BaseTelegramTestCase(TelegramAppTestCase): |
2466 | + |
2467 | + def setUp(self): |
2468 | + super(BaseTelegramTestCase, self).setUp() |
2469 | + |
2470 | + |
2471 | +class Logout(BaseTelegramTestCase): |
2472 | + |
2473 | + # Prerequisites: |
2474 | + # - User is already logged on |
2475 | + # - User has one contact which is online |
2476 | + # - Online contact is running on Telegram CLI |
2477 | + |
2478 | + |
2479 | + def test_UserLogout(self): |
2480 | + |
2481 | + # Open the account panel by tapping the navigation menu icon |
2482 | + account_page = self.main_view.account_page |
2483 | + account_panel = account_page.open_account_panel() |
2484 | + self.assertThat(account_panel.opened, Eventually(Equals(True))) |
2485 | + |
2486 | + # Select the Settings option |
2487 | + account_panel.select_settings() |
2488 | + |
2489 | + # Scroll to select the logout list item |
2490 | + apl = self.main_view.apl |
2491 | + settings_page = apl.settings_page |
2492 | + settings_page.select_list_item_logout() |
2493 | + sleep(3) |
2494 | + logout_confirm_dialog = self.app.wait_select_single(objectName='logoutDialog') |
2495 | + self.main_view.pointing_device.click_object(logout_confirm_dialog.wait_select_single(objectName='logoutConfirm')) |
2496 | + |
2497 | + # Checks that the Intro Page is now active |
2498 | + introPage = apl.intro_page |
2499 | |
2500 | === added file 'telegram/autopilot/telegram/tests/test_MessageDisplay.py' |
2501 | --- telegram/autopilot/telegram/tests/test_MessageDisplay.py 1970-01-01 00:00:00 +0000 |
2502 | +++ telegram/autopilot/telegram/tests/test_MessageDisplay.py 2016-11-14 11:39:33 +0000 |
2503 | @@ -0,0 +1,205 @@ |
2504 | +from telegram.tests import TelegramAppTestCase |
2505 | +from telegram import emulators |
2506 | +from telegram import utilities |
2507 | + |
2508 | +import os |
2509 | +import dbus |
2510 | +import time |
2511 | +import datetime |
2512 | +# import subprocess |
2513 | +import ubuntuuitoolkit |
2514 | + |
2515 | +from autopilot.matchers import Eventually |
2516 | +from testtools.matchers import Equals |
2517 | +from autopilot.display import Display |
2518 | +from autopilot import platform |
2519 | +from autopilot.utilities import sleep |
2520 | + |
2521 | +#from autopilot import logging as autopilot_logging |
2522 | +#from telegram import displays_and_interactions as interactions |
2523 | + |
2524 | +messageTypeText = "Autopilot: Text DO NOT REPLY" |
2525 | +messageTypeSpecialChar = "Autopilot: !$%^&*""()-_''=+?; DO NOT REPLY" |
2526 | +messageTypeUrl = "http://google.co.uk DO NOT REPLY" |
2527 | + |
2528 | +message_status_received = "qrc:/qml/files/check_single_green.png" |
2529 | +message_status_read = "qrc:/qml/files/check_double_green.png" |
2530 | + |
2531 | +class BaseTelegramTestCase(TelegramAppTestCase): |
2532 | + |
2533 | + def setUp(self): |
2534 | + super(BaseTelegramTestCase, self).setUp() |
2535 | + |
2536 | +class SecretChatTests(BaseTelegramTestCase): |
2537 | + |
2538 | + scenarios = [ |
2539 | + ('dialog_msgText', {'input': "dialog_msgText"}), |
2540 | + ('dialog_msgSpecialChar', {'input': "dialog_msgSpecialChar"}), |
2541 | + ('dialog_msgUrl', {'input': "dialog_msgUrl"}), |
2542 | + ] |
2543 | + |
2544 | + def test_create_secret_chat(self): |
2545 | + # Open the account panel by tapping the navigation menu icon |
2546 | + account_page = self.main_view.account_page |
2547 | + account_panel = account_page.open_account_panel() |
2548 | + self.assertThat(account_panel.opened, Eventually(Equals(True))) |
2549 | + |
2550 | + # Select the secret chat option |
2551 | + account_panel.select_secret_chat() |
2552 | + |
2553 | + contact_page = self.main_view.apl.contacts_page |
2554 | + |
2555 | + # PAZ always select online user - Done |
2556 | + # Select first contact |
2557 | + self.main_view.pointing_device.click_object(contact_page.select_first_online_contact()) |
2558 | + |
2559 | + dialog_list_page = account_page.get_dialog_list_page() |
2560 | + # Give chance for app to add the secret chat to top of chat list |
2561 | + sleep(3) |
2562 | + # Select the top chat |
2563 | + dialog_list_page.select_dialog_at_index(0) |
2564 | + |
2565 | + dialog_page = self.main_view.apl.dialog_page |
2566 | + message_list = dialog_page.account_message_list |
2567 | + inital_count = message_list.messages.count |
2568 | + |
2569 | + if self.input == "dialog_msgSpecialChar": |
2570 | + dialog_page.enter_message(messageTypeSpecialChar) |
2571 | + dialog_page.message_area.select_attach_or_send() |
2572 | + |
2573 | + elif self.input == "dialog_msgUrl": |
2574 | + dialog_page.enter_message(messageTypeUrl) |
2575 | + dialog_page.message_area.select_attach_or_send() |
2576 | + |
2577 | + elif self.input == "dialog_msgText": |
2578 | + dialog_page.enter_message(messageTypeText) |
2579 | + dialog_page.message_area.select_attach_or_send() |
2580 | + |
2581 | + # Wait for the message to be sent and allow for network latency |
2582 | + # Check that the single tick image is displayed for the sent message |
2583 | + sleep(2) |
2584 | + |
2585 | + message = message_list.get_message_at_index(0) |
2586 | + self.assertThat(message.message_status_image.source, Eventually(Equals(message_status_received))) |
2587 | + |
2588 | + # Check that the double tick image is displayed for the read message |
2589 | + self.assertThat(message.message_status_image.source, Eventually(Equals(message_status_read))) |
2590 | + |
2591 | + # PAZ I believe you need to tap on the URL to make sure it opens up in a browser. Not just |
2592 | + # check that the URL received is the same as the URL sent |
2593 | + |
2594 | + # ASH - I don't believe theres a way to determine that Browser app opens up from taping |
2595 | + # a link. Could be wrong but some help on this would be appreciated. |
2596 | + |
2597 | + # ASH - Hold off. Needs to be rethinked |
2598 | + |
2599 | + # if self.input == "dialog_msgUrl": |
2600 | + # #Click on link |
2601 | + # self.main_view.pointing_device.click_object(message.message_label) |
2602 | + # #Check hovered link is same as entered link |
2603 | + # self.assertThat(message.message_label.hoveredLink, Eventually(Equals(messageTypeUrl))) |
2604 | + |
2605 | + #PAZ - always need to check for double tick |
2606 | + |
2607 | +class GroupChatTests(BaseTelegramTestCase): |
2608 | + |
2609 | + scenarios = [ |
2610 | + ('dialog_msgText', {'input': "dialog_msgText"}), |
2611 | + ('dialog_msgSpecialChar', {'input': "dialog_msgSpecialChar"}), |
2612 | + ('dialog_msgUrl', {'input': "dialog_msgUrl"}), |
2613 | + ] |
2614 | + |
2615 | + def test_create_group_chat(self): |
2616 | + # Open the account panel by tapping the navigation menu icon |
2617 | + account_page = self.main_view.account_page |
2618 | + account_panel = account_page.open_account_panel() |
2619 | + self.assertThat(account_panel.opened, Eventually(Equals(True))) |
2620 | + |
2621 | + # Select the secret chat option |
2622 | + account_panel.select_group_chat() |
2623 | + contact_page = self.main_view.apl.contacts_page |
2624 | + |
2625 | + # Select first contact |
2626 | + self.main_view.pointing_device.click_object(contact_page.select_first_online_contact()) |
2627 | + # Select second contact |
2628 | + self.main_view.pointing_device.click_object(contact_page.select_second_contact()) |
2629 | + |
2630 | + contact_page.enter_group_chat_title('NewGroupTitle') |
2631 | + |
2632 | + dialog_list_page = account_page.get_dialog_list_page() |
2633 | + # Give chance for app to add the group chat to top of chat list |
2634 | + sleep(3) |
2635 | + # Select the top chat |
2636 | + dialog_list_page.select_dialog_at_index(0) |
2637 | + |
2638 | + dialog_page = self.main_view.apl.dialog_page |
2639 | + message_list = dialog_page.account_message_list |
2640 | + inital_count = message_list.messages.count |
2641 | + |
2642 | + if self.input == "dialog_msgSpecialChar": |
2643 | + dialog_page.enter_message(messageTypeSpecialChar) |
2644 | + dialog_page.message_area.select_attach_or_send() |
2645 | + |
2646 | + elif self.input == "dialog_msgUrl": |
2647 | + dialog_page.enter_message(messageTypeUrl) |
2648 | + dialog_page.message_area.select_attach_or_send() |
2649 | + |
2650 | + elif self.input == "dialog_msgText": |
2651 | + dialog_page.enter_message(messageTypeText) |
2652 | + dialog_page.message_area.select_attach_or_send() |
2653 | + |
2654 | + # Wait for the message to be sent and allow for network latency |
2655 | + # Check that the single tick image is displayed for the sent message |
2656 | + sleep(1) |
2657 | + |
2658 | + message = message_list.get_message_at_index(0) |
2659 | + self.assertThat(message.message_status_image.source, Eventually(Equals(message_status_received))) |
2660 | + |
2661 | + # Check that the double tick image is displayed for the read message |
2662 | + self.assertThat(message.message_status_image.source, Eventually(Equals(message_status_read))) |
2663 | + |
2664 | +class BasicMessagingTests(BaseTelegramTestCase): |
2665 | + |
2666 | + scenarios = [ |
2667 | + ('dialog_msgText', {'input': "dialog_msgText"}), |
2668 | + ('dialog_msgSpecialChar', {'input': "dialog_msgSpecialChar"}), |
2669 | + ('dialog_msgUrl', {'input': "dialog_msgUrl"}), |
2670 | + ] |
2671 | + |
2672 | + def test_create_basic_chat(self): |
2673 | + # Open the account panel by tapping the navigation menu icon |
2674 | + account_page = self.main_view.account_page |
2675 | + account_panel = account_page.open_account_panel() |
2676 | + self.assertThat(account_panel.opened, Eventually(Equals(True))) |
2677 | + |
2678 | + # Select Contacts option |
2679 | + account_panel.select_contacts() |
2680 | + |
2681 | + #Select first contact |
2682 | + contact_page = self.main_view.apl.contacts_page |
2683 | + self.main_view.pointing_device.click_object(contact_page.select_first_online_contact()) |
2684 | + |
2685 | + dialog_page = self.main_view.apl.dialog_page |
2686 | + message_list = dialog_page.account_message_list |
2687 | + inital_count = message_list.messages.count |
2688 | + |
2689 | + if self.input == "dialog_msgSpecialChar": |
2690 | + dialog_page.enter_message(messageTypeSpecialChar) |
2691 | + dialog_page.message_area.select_attach_or_send() |
2692 | + |
2693 | + elif self.input == "dialog_msgUrl": |
2694 | + dialog_page.enter_message(messageTypeUrl) |
2695 | + dialog_page.message_area.select_attach_or_send() |
2696 | + |
2697 | + elif self.input == "dialog_msgText": |
2698 | + dialog_page.enter_message(messageTypeText) |
2699 | + dialog_page.message_area.select_attach_or_send() |
2700 | + |
2701 | + # Check that the single tick image is displayed for the sent message |
2702 | + sleep(1) |
2703 | + |
2704 | + message = message_list.get_message_at_index(0) |
2705 | + self.assertThat(message.message_status_image.source, Eventually(Equals(message_status_received))) |
2706 | + |
2707 | + # Check that the double tick image is displayed for the read message |
2708 | + self.assertThat(message.message_status_image.source, Eventually(Equals(message_status_read))) |
2709 | \ No newline at end of file |
2710 | |
2711 | === added file 'telegram/autopilot/telegram/tests/test_Messaging.py' |
2712 | --- telegram/autopilot/telegram/tests/test_Messaging.py 1970-01-01 00:00:00 +0000 |
2713 | +++ telegram/autopilot/telegram/tests/test_Messaging.py 2016-11-14 11:39:33 +0000 |
2714 | @@ -0,0 +1,402 @@ |
2715 | +from telegram.tests import TelegramAppTestCase |
2716 | +from telegram import emulators |
2717 | + |
2718 | +import os |
2719 | +import dbus |
2720 | +import time |
2721 | +import datetime |
2722 | +import threading |
2723 | +# import subprocess |
2724 | +import ubuntuuitoolkit |
2725 | + |
2726 | +from autopilot.matchers import Eventually |
2727 | +from testtools.matchers import Equals, NotEquals |
2728 | +from autopilot.display import Display |
2729 | +from autopilot import platform |
2730 | +from autopilot.utilities import sleep |
2731 | + |
2732 | + |
2733 | +#from autopilot import logging as autopilot_logging |
2734 | +#from telegram import displays_and_interactions as interactions |
2735 | + |
2736 | +message_sending_image = "qrc:/qml/files/msg_clock.png" |
2737 | +message_received_image = "qrc:/qml/files/check_single_green.png" |
2738 | +message_read_image = "qrc:/qml/files/check_double_green.png" |
2739 | +media_received_image = "qrc:/qml/files/check_single_white.png" |
2740 | +media_read_image = "qrc:/qml/files/check_double_white.png" |
2741 | + |
2742 | + |
2743 | +class BaseTelegramTestCase(TelegramAppTestCase): |
2744 | + |
2745 | + def setUp(self): |
2746 | + super(BaseTelegramTestCase, self).setUp() |
2747 | + |
2748 | + |
2749 | +class SecretMessaging(BaseTelegramTestCase): |
2750 | + |
2751 | + # Prerequisites: |
2752 | + # - User is already logged on |
2753 | + # - User has one contact which is online |
2754 | + # - Online contact is running on Telegram CLI |
2755 | + |
2756 | + scenarios = [ |
2757 | + ('textMessageSend', {'input': "textMessageSend"}), |
2758 | + ('textMessageSendReceive', {'input': "textMessageSendReceive"}), |
2759 | + ('photoMessageSend', {'input': "photoMessageSend"}), |
2760 | + # ('photoMessageReceive', {'input': "photoMessageReceive"}), |
2761 | + ] |
2762 | + |
2763 | + def test_SecretMessage(self): |
2764 | + |
2765 | + # Note the number of dialogs in the dialog list at the start of the test |
2766 | + account_page = self.main_view.account_page |
2767 | + dialog_list_page = account_page.get_dialog_list_page() |
2768 | + count = dialog_list_page.dialog_count |
2769 | + |
2770 | + # Open the account panel by tapping the navigation menu icon |
2771 | + account_panel = account_page.open_account_panel() |
2772 | + self.assertThat(account_panel.opened, Eventually(Equals(True))) |
2773 | + |
2774 | + # Select the secret chat option |
2775 | + account_panel.select_secret_chat() |
2776 | + |
2777 | + # Select an online contact |
2778 | + apl = self.main_view.apl |
2779 | + contacts_page = apl.contacts_page |
2780 | + recipient = contacts_page.select_first_online_contact() |
2781 | + self.main_view.pointing_device.click_object(recipient) |
2782 | + |
2783 | + # Create a new secret chat |
2784 | + self.assertThat(count, Eventually(Equals(count + 1))) |
2785 | + dialog_list_page.select_dialog_at_index(0) |
2786 | + dialog_page = apl.dialog_page |
2787 | + |
2788 | + # Check that only system message is being displayed |
2789 | + message_list = dialog_page.account_message_list |
2790 | + initial_count = message_list.messages.count |
2791 | + self.assertThat(initial_count, Equals(1)) |
2792 | + |
2793 | + status_received = message_received_image |
2794 | + status_read = message_read_image |
2795 | + |
2796 | + if "textMessage" in self.input or self.input == "photoMessageReceive": |
2797 | + # Send the first message |
2798 | + |
2799 | + ts = time.time() |
2800 | + timestamp = datetime.datetime.fromtimestamp(ts).strftime('%y:%m:%d,%H:%M:%S') |
2801 | + message_to_send = "Autopilot:" + timestamp |
2802 | + if self.input == "textMessageSend": |
2803 | + message_to_send = message_to_send + " DO NOT REPLY" |
2804 | + elif self.input == "photoMessageReceive": |
2805 | + message_to_send = message_to_send + " SEND IMAGE" |
2806 | + |
2807 | + dialog_page.enter_message(message_to_send) |
2808 | + dialog_page.message_area.select_attach_or_send() |
2809 | + |
2810 | + elif self.input == "photoMessageSend": |
2811 | + |
2812 | + if platform.model() == "Desktop": |
2813 | + return |
2814 | + |
2815 | + dialog_page.message_area.select_attach_or_send() |
2816 | + dialog_page.message_area.select_attach_photo_option() |
2817 | + self.main_view.select_content_hub_app("Camera") |
2818 | + |
2819 | + # Allow time to open the app |
2820 | + sleep(5) |
2821 | + |
2822 | + display = Display.create() |
2823 | + screen_width = display.get_screen_width() |
2824 | + screen_height = display.get_screen_height() |
2825 | + button_x_pos = screen_width / 2.0 |
2826 | + button_y_pos = screen_height - 100.0 |
2827 | + |
2828 | + # Click on the take photo button |
2829 | + self.main_view.pointing_device.move(button_x_pos, button_y_pos) |
2830 | + self.main_view.pointing_device.click() |
2831 | + |
2832 | + # Allow time to take the photo |
2833 | + sleep(5) |
2834 | + |
2835 | + # Tap the tick to return to Telegram |
2836 | + self.main_view.pointing_device.move(button_x_pos, button_y_pos) |
2837 | + self.main_view.pointing_device.click() |
2838 | + |
2839 | + status_received = media_received_image |
2840 | + status_read = media_read_image |
2841 | + |
2842 | + # Allow time for photo to be sent |
2843 | + sleep(5) |
2844 | + |
2845 | + # Check that sent message appears in the dialog content |
2846 | + self.assertThat(message_list.messages.count, Eventually(Equals(initial_count + 1))) |
2847 | + |
2848 | + # Check that the message received image is displayed for the sent message |
2849 | + index_of_sent_message = 0 |
2850 | + message = message_list.get_message_at_index(index_of_sent_message) |
2851 | + status_image = message.message_status_image |
2852 | + |
2853 | + if self.input == "photoMessageSend" and platform.model() != "Desktop": |
2854 | + status_image = message.account_message_media.media_message_status_image |
2855 | + |
2856 | + self.assertThat(status_image.source, Eventually(Equals(status_received))) |
2857 | + |
2858 | + if "Receive" in self.input: |
2859 | + |
2860 | + index_of_sent_message = index_of_sent_message + 1 |
2861 | + |
2862 | + # Check for reply |
2863 | + self.assertThat(message_list.messages.count, Eventually(Equals(initial_count + 2))) |
2864 | + |
2865 | + # Check that the message read image is displayed for the sent message |
2866 | + message = message_list.get_message_at_index(index_of_sent_message) |
2867 | + status_image = message.message_status_image |
2868 | + |
2869 | + if self.input == "photoMessageSend" and platform.model() != "Desktop": |
2870 | + status_image = message.account_message_media.media_message_status_image |
2871 | + |
2872 | + self.assertThat(status_image.source, Eventually(Equals(status_read))) |
2873 | + |
2874 | + |
2875 | + |
2876 | +class BasicMessaging(BaseTelegramTestCase): |
2877 | + |
2878 | + scenarios = [ |
2879 | + ('textMessageSend', {'input': "textMessageSend"}), |
2880 | + ('textMessageSendReceive', {'input': "textMessageSendReceive"}), |
2881 | + ('photoMessageSend', {'input': "photoMessageSend"}), |
2882 | + ('photoMessageReceive', {'input': "photoMessageReceive"}), |
2883 | + ] |
2884 | + |
2885 | + def test_BasicMessage(self): |
2886 | + |
2887 | + # Open the account panel by tapping the navigation menu icon |
2888 | + account_page = self.main_view.account_page |
2889 | + account_panel = account_page.open_account_panel() |
2890 | + self.assertThat(account_panel.opened, Eventually(Equals(True))) |
2891 | + |
2892 | + # Select contacts |
2893 | + account_panel.select_contacts() |
2894 | + |
2895 | + # Select an online contact |
2896 | + apl = self.main_view.apl |
2897 | + contacts_page = apl.contacts_page |
2898 | + recipient = contacts_page.select_first_online_contact() |
2899 | + self.main_view.pointing_device.click_object(recipient) |
2900 | + |
2901 | + # Check that no messages are being displayed |
2902 | + dialog_page = apl.dialog_page |
2903 | + message_list = dialog_page.account_message_list |
2904 | + initial_count = message_list.messages.count |
2905 | + |
2906 | + # Initialise status image values |
2907 | + status_received = message_received_image |
2908 | + status_read = message_read_image |
2909 | + |
2910 | + if "textMessage" in self.input or self.input == "photoMessageReceive": |
2911 | + |
2912 | + # Send the first message |
2913 | + ts = time.time() |
2914 | + timestamp = datetime.datetime.fromtimestamp(ts).strftime('%y:%m:%d,%H:%M:%S') |
2915 | + message_to_send = "Autopilot" + timestamp |
2916 | + if self.input == "textMessageSend": |
2917 | + message_to_send = message_to_send + " DO NOT REPLY" |
2918 | + elif self.input == "photoMessageReceive": |
2919 | + message_to_send = message_to_send + " SEND IMAGE" |
2920 | + |
2921 | + dialog_page.enter_message(message_to_send) |
2922 | + dialog_page.message_area.select_attach_or_send() |
2923 | + |
2924 | + elif self.input == "photoMessageSend": |
2925 | + |
2926 | + if platform.model() == "Desktop": |
2927 | + return |
2928 | + |
2929 | + dialog_page.message_area.select_attach_or_send() |
2930 | + dialog_page.message_area.select_attach_photo_option() |
2931 | + self.main_view.select_content_hub_app("Camera") |
2932 | + |
2933 | + # Allow time to open the app |
2934 | + sleep(5) |
2935 | + |
2936 | + display = Display.create() |
2937 | + screen_width = display.get_screen_width() |
2938 | + screen_height = display.get_screen_height() |
2939 | + button_x_pos = screen_width / 2.0 |
2940 | + button_y_pos = screen_height - 100.0 |
2941 | + |
2942 | + # Click on the take photo button |
2943 | + self.main_view.pointing_device.move(button_x_pos, button_y_pos) |
2944 | + self.main_view.pointing_device.click() |
2945 | + |
2946 | + # Allow time to take the photo |
2947 | + sleep(5) |
2948 | + |
2949 | + # Tap the tick to return to Telegram |
2950 | + self.main_view.pointing_device.move(button_x_pos, button_y_pos) |
2951 | + self.main_view.pointing_device.click() |
2952 | + |
2953 | + status_received = media_received_image |
2954 | + status_read = media_read_image |
2955 | + |
2956 | + # Allow time for photo to be sent |
2957 | + sleep(5) |
2958 | + |
2959 | + # Check that sent message appears in the dialog content |
2960 | + self.assertThat(message_list.messages.count, Eventually(Equals(initial_count + 1))) |
2961 | + |
2962 | + # Check that the message received image is displayed for the sent message |
2963 | + index_of_sent_message = 0 |
2964 | + message = message_list.get_message_at_index(index_of_sent_message) |
2965 | + status_image = message.message_status_image |
2966 | + |
2967 | + if self.input == "photoMessageSend" and platform.model() != "Desktop": |
2968 | + status_image = message.account_message_media.media_message_status_image |
2969 | + |
2970 | + self.assertThat(status_image.source, Eventually(Equals(status_received))) |
2971 | + |
2972 | + if "Receive" in self.input: |
2973 | + |
2974 | + index_of_sent_message = index_of_sent_message + 1 |
2975 | + |
2976 | + # Check for reply |
2977 | + self.assertThat(message_list.messages.count, Eventually(Equals(initial_count + 2))) |
2978 | + |
2979 | + # Check that the message read image is displayed for the sent message |
2980 | + message = message_list.get_message_at_index(index_of_sent_message) |
2981 | + status_image = message.message_status_image |
2982 | + |
2983 | + if self.input == "photoMessageSend" and platform.model() != "Desktop": |
2984 | + status_image = message.account_message_media.media_message_status_image |
2985 | + |
2986 | + self.assertThat(status_image.source, Eventually(Equals(status_read))) |
2987 | + |
2988 | + |
2989 | +class GroupMessaging(BaseTelegramTestCase): |
2990 | + |
2991 | + scenarios = [ |
2992 | + ('textMessageSend', {'input': "textMessageSend"}), |
2993 | + ('textMessageSendReceive', {'input': "textMessageSendReceive"}), |
2994 | + ('photoMessageSend', {'input': "photoMessageSend"}), |
2995 | + ('photoMessageReceive', {'input': "photoMessageReceive"}), |
2996 | + ] |
2997 | + |
2998 | + def test_GroupMessage(self): |
2999 | + |
3000 | + # Note the number of dialogs in the dialog list at the start of the test |
3001 | + account_page = self.main_view.account_page |
3002 | + dialog_list_page = account_page.get_dialog_list_page() |
3003 | + count = dialog_list_page.dialog_count |
3004 | + |
3005 | + # Open the account panel by tapping the navigation menu icon |
3006 | + account_panel = account_page.open_account_panel() |
3007 | + self.assertThat(account_panel.opened, Eventually(Equals(True))) |
3008 | + |
3009 | + # Select the group chat option |
3010 | + account_panel.select_group_chat() |
3011 | + |
3012 | + # Select an online contact |
3013 | + apl = self.main_view.apl |
3014 | + contacts_page = apl.contacts_page |
3015 | + online_member_one = contacts_page.select_first_online_contact() |
3016 | + self.main_view.pointing_device.click_object(online_member_one) |
3017 | + |
3018 | + # Select another contact |
3019 | + member_two = contacts_page.select_second_contact() |
3020 | + self.main_view.pointing_device.click_object(member_two) |
3021 | + |
3022 | + # Add a group chat title |
3023 | + contacts_page.enter_group_chat_title('Autopilot Group Messaging') |
3024 | + |
3025 | + # Select the group chat dialog just created |
3026 | + self.assertThat(count, Eventually(Equals(count + 1))) |
3027 | + dialog_list_page.select_dialog_at_index(0) |
3028 | + dialog_page = apl.dialog_page |
3029 | + |
3030 | + # Check that only system message is being displayed |
3031 | + message_list = dialog_page.account_message_list |
3032 | + initial_count = message_list.messages.count |
3033 | + self.assertThat(initial_count, Equals(1)) |
3034 | + |
3035 | + # Initialise status image values |
3036 | + status_received = message_received_image |
3037 | + status_read = message_read_image |
3038 | + |
3039 | + if "textMessage" in self.input or self.input == "photoMessageReceive": |
3040 | + |
3041 | + # Generate and send the first message |
3042 | + ts = time.time() |
3043 | + timestamp = datetime.datetime.fromtimestamp(ts).strftime('%y:%m:%d,%H:%M:%S') |
3044 | + message_to_send = "Autopilot:" + timestamp |
3045 | + if self.input == "textMessageSend": |
3046 | + message_to_send = message_to_send + " DO NOT REPLY" |
3047 | + elif self.input == "photoMessageReceive": |
3048 | + message_to_send = message_to_send + " SEND IMAGE" |
3049 | + |
3050 | + dialog_page.enter_message(message_to_send) |
3051 | + dialog_page.message_area.select_attach_or_send() |
3052 | + |
3053 | + elif self.input == "photoMessageSend": |
3054 | + |
3055 | + if platform.model() == "Desktop": |
3056 | + return |
3057 | + |
3058 | + dialog_page.message_area.select_attach_or_send() |
3059 | + sleep(1) |
3060 | + dialog_page.message_area.select_attach_photo_option() |
3061 | + self.main_view.select_content_hub_app("Camera") |
3062 | + |
3063 | + # Allow time to open the app |
3064 | + sleep(5) |
3065 | + |
3066 | + display = Display.create() |
3067 | + screen_width = display.get_screen_width() |
3068 | + screen_height = display.get_screen_height() |
3069 | + button_x_pos = screen_width / 2.0 |
3070 | + button_y_pos = screen_height - 100.0 |
3071 | + |
3072 | + # Click on the take photo button |
3073 | + self.main_view.pointing_device.move(button_x_pos, button_y_pos) |
3074 | + self.main_view.pointing_device.click() |
3075 | + |
3076 | + # Allow time to take the photo |
3077 | + sleep(5) |
3078 | + |
3079 | + # Tap the tick to return to Telegram |
3080 | + self.main_view.pointing_device.move(button_x_pos, button_y_pos) |
3081 | + self.main_view.pointing_device.click() |
3082 | + |
3083 | + status_received = media_received_image |
3084 | + status_read = media_read_image |
3085 | + |
3086 | + # Allow time for photo to be sent |
3087 | + sleep(5) |
3088 | + |
3089 | + # Check that sent message appears in the dialog content |
3090 | + self.assertThat(message_list.messages.count, Eventually(Equals(initial_count + 1))) |
3091 | + |
3092 | + # Check that the message received image is displayed for the sent message |
3093 | + index_of_sent_message = 0 |
3094 | + message = message_list.get_message_at_index(index_of_sent_message) |
3095 | + status_image = message.message_status_image |
3096 | + |
3097 | + if self.input == "photoMessageSend" and platform.model() != "Desktop": |
3098 | + status_image = message.account_message_media.media_message_status_image |
3099 | + |
3100 | + self.assertThat(status_image.source, Eventually(Equals(status_received))) |
3101 | + |
3102 | + if "Receive" in self.input: |
3103 | + |
3104 | + index_of_sent_message = index_of_sent_message + 1 |
3105 | + |
3106 | + # Check for reply |
3107 | + self.assertThat(message_list.messages.count, Eventually(Equals(initial_count + 2))) |
3108 | + |
3109 | + # Check that the double tick image is displayed for the read message |
3110 | + message = message_list.get_message_at_index(index_of_sent_message) |
3111 | + status_image = message.message_status_image |
3112 | + |
3113 | + if self.input == "photoMessageSend" and platform.model() != "Desktop": |
3114 | + status_image = message.account_message_media.media_message_status_image |
3115 | + |
3116 | + self.assertThat(status_image.source, Eventually(Equals(status_read))) |
3117 | |
3118 | === added file 'telegram/autopilot/telegram/tests/test_Offline.py' |
3119 | --- telegram/autopilot/telegram/tests/test_Offline.py 1970-01-01 00:00:00 +0000 |
3120 | +++ telegram/autopilot/telegram/tests/test_Offline.py 2016-11-14 11:39:33 +0000 |
3121 | @@ -0,0 +1,54 @@ |
3122 | +from telegram.tests import TelegramAppTestCase |
3123 | +from telegram import emulators |
3124 | + |
3125 | +# import subprocess |
3126 | +import ubuntuuitoolkit |
3127 | + |
3128 | +from autopilot.matchers import Eventually |
3129 | +from testtools.matchers import Equals |
3130 | +from autopilot.display import Display |
3131 | +from autopilot import platform |
3132 | +from testtools import skipUnless |
3133 | + |
3134 | +class BaseTelegramTestCase(TelegramAppTestCase): |
3135 | + |
3136 | + def setUp(self): |
3137 | + super(BaseTelegramTestCase, self).setUp() |
3138 | + |
3139 | +class OfflineTests(BaseTelegramTestCase): |
3140 | + |
3141 | + @skipUnless( |
3142 | + platform.model() != "Desktop", |
3143 | + "Offline Test is only available on Device" |
3144 | + ) |
3145 | + |
3146 | + def test_check_for_offline_message(self): |
3147 | + display = Display.create() |
3148 | + screenWidth = display.get_screen_width() |
3149 | + screenHeight = display.get_screen_height() |
3150 | + |
3151 | + #Pull menu from top |
3152 | + self.main_view.pointing_device.drag(screenWidth-202, 0, screenWidth-202, screenHeight) |
3153 | + #Tap Flight Mode switch |
3154 | + self.main_view.pointing_device.move(screenWidth-130,150) |
3155 | + self.main_view.pointing_device.click() |
3156 | + #Close menu |
3157 | + self.main_view.pointing_device.drag(0,screenHeight, 0,0) |
3158 | + |
3159 | + account_page = self.main_view.account_page |
3160 | + |
3161 | + # if account_page.get_default_header().title in ('Telegram', 'Connecting...'): |
3162 | + # print("WARNING - Please turn ON Airplane Mode") |
3163 | + |
3164 | + self.assertThat(account_page.get_default_header().title, Eventually(Equals("Waiting for network..."))) |
3165 | + |
3166 | + #Pull menu from top |
3167 | + self.main_view.pointing_device.drag(screenWidth-180, 0, screenWidth-180, screenHeight) |
3168 | + #Tap Flight Mode switch |
3169 | + self.main_view.pointing_device.move(screenWidth-130,150) |
3170 | + self.main_view.pointing_device.click() |
3171 | + #Close menu |
3172 | + self.main_view.pointing_device.drag(0,screenHeight, 0,0) |
3173 | + |
3174 | + # Check header no longer says offline message |
3175 | + self.assertThat(account_page.get_default_header().title, Eventually(Equals("Telegram"))) |
3176 | |
3177 | === added file 'telegram/autopilot/telegram/tests/test_Profile.py' |
3178 | --- telegram/autopilot/telegram/tests/test_Profile.py 1970-01-01 00:00:00 +0000 |
3179 | +++ telegram/autopilot/telegram/tests/test_Profile.py 2016-11-14 11:39:33 +0000 |
3180 | @@ -0,0 +1,186 @@ |
3181 | +from telegram.tests import TelegramAppTestCase |
3182 | +from telegram import emulators |
3183 | +from telegram import utilities |
3184 | + |
3185 | +import os |
3186 | +import dbus |
3187 | +import time |
3188 | +import datetime |
3189 | +# import subprocess |
3190 | +import ubuntuuitoolkit |
3191 | + |
3192 | +from autopilot.matchers import Eventually |
3193 | +from testtools.matchers import Equals |
3194 | +from autopilot.utilities import sleep |
3195 | + |
3196 | +messageTypeText = "Autopilot: Text INSTANT REPLY" |
3197 | + |
3198 | +class BaseTelegramTestCase(TelegramAppTestCase): |
3199 | + |
3200 | + def setUp(self): |
3201 | + super(BaseTelegramTestCase, self).setUp() |
3202 | + |
3203 | +class ProfileTests(BaseTelegramTestCase): |
3204 | + |
3205 | + def test_check_group_to_verify_members(self): |
3206 | + # Open the account panel by tapping the navigation menu icon |
3207 | + account_page = self.main_view.account_page |
3208 | + account_panel = account_page.open_account_panel() |
3209 | + self.assertThat(account_panel.opened, Eventually(Equals(True))) |
3210 | + |
3211 | + # Select the secret chat option |
3212 | + account_panel.select_group_chat() |
3213 | + |
3214 | + # Select first online contact |
3215 | + contacts_page = self.main_view.apl.contacts_page |
3216 | + |
3217 | + # Select first contact |
3218 | + self.main_view.pointing_device.click_object(contacts_page.select_contact_at_index(0)) |
3219 | + # Temporarily save fullname of contact |
3220 | + tempUser1Name = contacts_page.select_contact_at_index(0).fullName |
3221 | + |
3222 | + # Select second contact |
3223 | + self.main_view.pointing_device.click_object(contacts_page.select_contact_at_index(1)) |
3224 | + tempUser2Name = contacts_page.select_contact_at_index(1).fullName |
3225 | + |
3226 | + #Enter group title and press Enter |
3227 | + contacts_page.enter_group_chat_title('ProfileTest-NewGroup') |
3228 | + |
3229 | + #Assign dialog list |
3230 | + account_page = self.main_view.account_page |
3231 | + dialog_list_page = account_page.get_dialog_list_page() |
3232 | + count = dialog_list_page.dialog_count |
3233 | + self.assertThat(count, Eventually(Equals(count + 1))) |
3234 | + dialog_list_page.select_dialog_at_index(0) |
3235 | + |
3236 | + #Press groupInfo button |
3237 | + self.main_view.apl.dialog_page.select_chat_info() |
3238 | + |
3239 | + #Assign ProfilePage |
3240 | + profile_page = self.main_view.apl.profile_page |
3241 | + |
3242 | + # Check user 1 is listed |
3243 | + self.assertThat(str(profile_page.profile_member_at_index(1).title), Equals(tempUser1Name)) |
3244 | + # Check user 2 is listed |
3245 | + self.assertThat(str(profile_page.profile_member_at_index(0).title), Equals(tempUser2Name)) |
3246 | + |
3247 | + |
3248 | + def test_check_blocked_user(self): |
3249 | + # Open the account panel by tapping the navigation menu icon |
3250 | + account_page = self.main_view.account_page |
3251 | + account_panel = account_page.open_account_panel() |
3252 | + self.assertThat(account_panel.opened, Eventually(Equals(True))) |
3253 | + |
3254 | + # Select Contacts option |
3255 | + account_panel.select_contacts() |
3256 | + |
3257 | + #Select first contact |
3258 | + contacts_page = self.main_view.apl.contacts_page |
3259 | + recipient = contacts_page.select_first_online_contact() |
3260 | + self.main_view.pointing_device.click_object(recipient) |
3261 | + |
3262 | + dialog_page = self.main_view.apl.dialog_page |
3263 | + message_list = dialog_page.account_message_list |
3264 | + inital_count = message_list.messages.count |
3265 | + |
3266 | + #Send message |
3267 | + dialog_page.enter_message(messageTypeText) |
3268 | + dialog_page.message_area.select_attach_or_send() |
3269 | + |
3270 | + #Check received reply |
3271 | + self.assertThat(message_list.messages.count, Eventually(Equals(inital_count + 2))) |
3272 | + |
3273 | + #Tap the groupInfo button |
3274 | + self.main_view.apl.dialog_page.select_chat_info() |
3275 | + #Assign ProfilePage |
3276 | + profile_page = self.main_view.apl.profile_page |
3277 | + #Turn on Block contact |
3278 | + switch = profile_page.switch_block |
3279 | + self.main_view.pointing_device.click_object(switch) |
3280 | + #Verify blocked user switch is turned ON |
3281 | + self.assertThat(switch.checked, Equals(True)) |
3282 | + #Go back to dialog page |
3283 | + profile_page.select_back_button() |
3284 | + self.main_view.apl.clear_profile_page() |
3285 | + |
3286 | + #Send message |
3287 | + dialog_page.enter_message(messageTypeText) |
3288 | + dialog_page.message_area.select_attach_or_send() |
3289 | + |
3290 | + # Check that the sent message was read |
3291 | + message = None |
3292 | + for idx in range(0, message_list.messages.count): |
3293 | + message = message_list.get_message_at_index(idx) |
3294 | + if message.message_label.text == messageTypeText: |
3295 | + self.assertThat(message.message_status_image.source, Eventually(Equals("qrc:/qml/files/check_double_green.png"))) |
3296 | + break |
3297 | + else: |
3298 | + message = None |
3299 | + self.assertThat(message is None, Equals(False)) |
3300 | + |
3301 | + # Check that no response was received (wait for 10 seconds) |
3302 | + sleep(10) |
3303 | + self.assertThat(message_list.messages.count, Equals(inital_count + 3)) |
3304 | + |
3305 | + #Tap the groupInfo button |
3306 | + self.main_view.apl.dialog_page.select_chat_info() |
3307 | + #Assign ProfilePage |
3308 | + profile_page = self.main_view.apl.profile_page |
3309 | + #Turn off Block contact. |
3310 | + switch = profile_page.switch_block |
3311 | + self.assertThat(switch.checked, Eventually(Equals(True))) |
3312 | + self.main_view.pointing_device.click_object(switch) |
3313 | + #Verify blocked user switch is turned OFF |
3314 | + self.assertThat(switch.checked, Eventually(Equals(False))) |
3315 | + #Go back to dialog page |
3316 | + profile_page.select_back_button() |
3317 | + |
3318 | + #Check number of messages and send message |
3319 | + self.assertThat(message_list.messages.count, Equals(inital_count + 3)) |
3320 | + #Send message |
3321 | + dialog_page.enter_message(messageTypeText) |
3322 | + dialog_page.message_area.select_attach_or_send() |
3323 | + |
3324 | + #Check received reply |
3325 | + self.assertThat(message_list.messages.count, Eventually(Equals(inital_count + 5))) |
3326 | + |
3327 | +class ProfileDetails(BaseTelegramTestCase): |
3328 | + |
3329 | + def test_verify_profile_details(self): |
3330 | + # Open the account panel by tapping the navigation menu icon |
3331 | + account_page = self.main_view.account_page |
3332 | + account_panel = account_page.open_account_panel() |
3333 | + self.assertThat(account_panel.opened, Eventually(Equals(True))) |
3334 | + |
3335 | + # Select Contacts option |
3336 | + account_panel.select_contacts() |
3337 | + |
3338 | + #Select first contact |
3339 | + contact_page = self.main_view.apl.contacts_page |
3340 | + contact = contact_page.select_contact_at_index(0) |
3341 | + |
3342 | + self.main_view.pointing_device.click_object(contact) |
3343 | + |
3344 | + self.main_view.apl.dialog_page.select_chat_info() |
3345 | + |
3346 | + profile_page = self.main_view.apl.profile_page |
3347 | + |
3348 | + # print(profile_page.profile_user_photo.get_properties()) |
3349 | + |
3350 | + # print("IMAGE SRC: " + profile_page.profile_user_photo.source) |
3351 | + |
3352 | + sleep(3) |
3353 | + |
3354 | + if profile_page.select_user_photo() is None: |
3355 | + #User does not have a profile image |
3356 | + print('WARNING - Profiles - Contact does not have Profile image') |
3357 | + else: |
3358 | + self.assertThat(profile_page.select_user_photo() is not None, Equals(True)) |
3359 | + |
3360 | + # Check the user has a name |
3361 | + if profile_page.profile_user_name.text is None: |
3362 | + raise RuntimeError("Profiles - Contact does not have Name") |
3363 | + |
3364 | + # Check the user has a phone number |
3365 | + if profile_page.profile_user_phone_number.text is None: |
3366 | + raise RuntimeError("Profiles - Contact does not have valid Phone Number") |
3367 | \ No newline at end of file |
3368 | |
3369 | === added file 'telegram/autopilot/telegram/utilities.py' |
3370 | --- telegram/autopilot/telegram/utilities.py 1970-01-01 00:00:00 +0000 |
3371 | +++ telegram/autopilot/telegram/utilities.py 2016-11-14 11:39:33 +0000 |
3372 | @@ -0,0 +1,36 @@ |
3373 | +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
3374 | +# Copyright 2016 Canonical |
3375 | +# |
3376 | +# This file is part of telegram-app. |
3377 | +# |
3378 | +# telegram-app is free software: you can redistribute it and/or modify it |
3379 | +# under the terms of the GNU General Public License version 3, as published |
3380 | +# by the Free Software Foundation. |
3381 | + |
3382 | + |
3383 | +"""Telegram app helper functions""" |
3384 | + |
3385 | +from autopilot.input import Keyboard |
3386 | + |
3387 | +""" KEYBOARD UTILITIES """ |
3388 | + |
3389 | +global mainKeyboard |
3390 | + |
3391 | +def enter_text_in_text_area(text_area, text): |
3392 | + #Assign keyboard type |
3393 | + mainKeyboard = Keyboard.create() |
3394 | + |
3395 | + #Focus TextArea and begin typing |
3396 | + with mainKeyboard.focused_type(text_area) as kb: |
3397 | + kb.type(text) |
3398 | + |
3399 | +def enter_text_in_text_area_and_press_enter(text_area, text): |
3400 | + #Assign keyboard type |
3401 | + mainKeyboard = Keyboard.create() |
3402 | + |
3403 | + #Focus TextArea and begin typing |
3404 | + with mainKeyboard.focused_type(text_area) as kb: |
3405 | + kb.type(text) |
3406 | + |
3407 | + #Simulate 'Enter' key being pressed |
3408 | + mainKeyboard.press_and_release('Enter') |
3409 | \ No newline at end of file |
Please, fix conflicts "Text conflict in telegram/ app/qml/ components/ MessagesListIte m.qml"