mirror of
https://github.com/ARM-software/workload-automation.git
synced 2025-02-20 20:09:11 +00:00
Merge pull request #225 from jimboatarm/googlephotos_uxperf
Add googlephotos workload
This commit is contained in:
commit
ff2f88fbd7
89
wlauto/workloads/googlephotos/__init__.py
Executable file
89
wlauto/workloads/googlephotos/__init__.py
Executable file
@ -0,0 +1,89 @@
|
||||
# Copyright 2014-2016 ARM Limited
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
import os
|
||||
|
||||
from wlauto import AndroidUxPerfWorkload, Parameter, File
|
||||
from wlauto.exceptions import ValidationError
|
||||
from wlauto.utils.types import list_of_strings
|
||||
from wlauto.utils.misc import unique
|
||||
|
||||
|
||||
class Googlephotos(AndroidUxPerfWorkload):
|
||||
|
||||
name = 'googlephotos'
|
||||
package = 'com.google.android.apps.photos'
|
||||
min_apk_version = '1.21.0.123444480'
|
||||
activity = 'com.google.android.apps.photos.home.HomeActivity'
|
||||
view = [package + '/com.google.android.apps.consumerphotoeditor.fragments.ConsumerPhotoEditorActivity',
|
||||
package + '/com.google.android.apps.photos.home.HomeActivity',
|
||||
package + '/com.google.android.apps.photos.localmedia.ui.LocalPhotosActivity',
|
||||
package + '/com.google.android.apps.photos.onboarding.AccountPickerActivity',
|
||||
package + '/com.google.android.apps.photos.onboarding.IntroActivity']
|
||||
description = """
|
||||
A workload to perform standard productivity tasks with Google Photos. The workload carries out
|
||||
various tasks, such as browsing images, performing zooms, and post-processing the image.
|
||||
|
||||
Test description:
|
||||
1. Four images are copied to the device
|
||||
2. The application is started in offline access mode
|
||||
3. Gestures are performed to swipe between images and pinch zoom in and out of the selected
|
||||
image
|
||||
4. The colour of a selected image is edited by selecting the colour menu, incrementing the
|
||||
colour, resetting the colour and decrementing the colour using the seek bar.
|
||||
5. A crop test is performed on a selected image. UiAutomator does not allow the selection of
|
||||
the crop markers so the image is tilted positively, reset and then tilted negatively to get a
|
||||
similar cropping effect.
|
||||
6. A rotate test is performed on a selected image, rotating anticlockwise 90 degrees, 180
|
||||
degrees and 270 degrees.
|
||||
"""
|
||||
|
||||
default_test_images = [
|
||||
'uxperf_1200x1600.png', 'uxperf_1600x1200.jpg',
|
||||
'uxperf_2448x3264.png', 'uxperf_3264x2448.jpg',
|
||||
]
|
||||
|
||||
parameters = [
|
||||
Parameter('test_images', kind=list_of_strings, default=default_test_images,
|
||||
constraint=lambda x: len(unique(x)) == 4,
|
||||
description="""
|
||||
A list of four JPEG and/or PNG files to be pushed to the device.
|
||||
Absolute file paths may be used but tilde expansion must be escaped.
|
||||
"""),
|
||||
]
|
||||
|
||||
def __init__(self, device, **kwargs):
|
||||
super(Googlephotos, self).__init__(device, **kwargs)
|
||||
self.deployable_assets = self.test_images
|
||||
|
||||
def validate(self):
|
||||
super(Googlephotos, self).validate()
|
||||
|
||||
for image in self.test_images:
|
||||
if os.path.splitext(image.lower())[1] not in ['.jpg', '.jpeg', '.png']:
|
||||
raise ValidationError('{} must be a JPEG or PNG file'.format(image))
|
||||
|
||||
def setup(self, context):
|
||||
super(Googlephotos, self).setup(context)
|
||||
self.device.broadcast_media_mounted(self.device.working_directory)
|
||||
|
||||
def teardown(self, context):
|
||||
super(Googlephotos, self).teardown(context)
|
||||
self.device.broadcast_media_mounted(self.device.working_directory)
|
||||
|
||||
def finalize(self, context):
|
||||
super(Googlephotos, self).finalize(context)
|
||||
self.delete_assets()
|
||||
self.device.broadcast_media_mounted(self.device.working_directory)
|
Binary file not shown.
39
wlauto/workloads/googlephotos/uiauto/build.sh
Executable file
39
wlauto/workloads/googlephotos/uiauto/build.sh
Executable file
@ -0,0 +1,39 @@
|
||||
#!/bin/bash
|
||||
|
||||
# CD into build dir if possible - allows building from any directory
|
||||
script_path='.'
|
||||
if `readlink -f $0 &>/dev/null`; then
|
||||
script_path=`readlink -f $0 2>/dev/null`
|
||||
fi
|
||||
script_dir=`dirname $script_path`
|
||||
cd $script_dir
|
||||
|
||||
# Ensure build.xml exists before starting
|
||||
if [[ ! -f build.xml ]]; then
|
||||
echo 'Ant build.xml file not found! Check that you are in the right directory.'
|
||||
exit 9
|
||||
fi
|
||||
|
||||
# Copy base classes from wlauto dist
|
||||
class_dir=bin/classes/com/arm/wlauto/uiauto
|
||||
base_classes=`python -c "import os, wlauto; print os.path.join(os.path.dirname(wlauto.__file__), 'common', 'android', '*.class')"`
|
||||
mkdir -p $class_dir
|
||||
cp $base_classes $class_dir
|
||||
|
||||
# Build and return appropriate exit code if failed
|
||||
ant build
|
||||
exit_code=$?
|
||||
if [[ $exit_code -ne 0 ]]; then
|
||||
echo "ERROR: 'ant build' exited with code $exit_code"
|
||||
exit $exit_code
|
||||
fi
|
||||
|
||||
# If successful move JAR file to workload folder (overwrite previous)
|
||||
package=com.arm.wlauto.uiauto.googlephotos.jar
|
||||
rm -f ../$package
|
||||
if [[ -f bin/$package ]]; then
|
||||
cp bin/$package ..
|
||||
else
|
||||
echo 'ERROR: UiAutomator JAR could not be found!'
|
||||
exit 9
|
||||
fi
|
92
wlauto/workloads/googlephotos/uiauto/build.xml
Normal file
92
wlauto/workloads/googlephotos/uiauto/build.xml
Normal file
@ -0,0 +1,92 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="com.arm.wlauto.uiauto.googlephotos" default="help">
|
||||
|
||||
<!-- The local.properties file is created and updated by the 'android' tool.
|
||||
It contains the path to the SDK. It should *NOT* be checked into
|
||||
Version Control Systems. -->
|
||||
<property file="local.properties" />
|
||||
|
||||
<!-- The ant.properties file can be created by you. It is only edited by the
|
||||
'android' tool to add properties to it.
|
||||
This is the place to change some Ant specific build properties.
|
||||
Here are some properties you may want to change/update:
|
||||
|
||||
source.dir
|
||||
The name of the source directory. Default is 'src'.
|
||||
out.dir
|
||||
The name of the output directory. Default is 'bin'.
|
||||
|
||||
For other overridable properties, look at the beginning of the rules
|
||||
files in the SDK, at tools/ant/build.xml
|
||||
|
||||
Properties related to the SDK location or the project target should
|
||||
be updated using the 'android' tool with the 'update' action.
|
||||
|
||||
This file is an integral part of the build system for your
|
||||
application and should be checked into Version Control Systems.
|
||||
|
||||
-->
|
||||
<property file="ant.properties" />
|
||||
|
||||
<!-- if sdk.dir was not set from one of the property file, then
|
||||
get it from the ANDROID_HOME env var.
|
||||
This must be done before we load project.properties since
|
||||
the proguard config can use sdk.dir -->
|
||||
<property environment="env" />
|
||||
<condition property="sdk.dir" value="${env.ANDROID_HOME}">
|
||||
<isset property="env.ANDROID_HOME" />
|
||||
</condition>
|
||||
|
||||
<!-- The project.properties file is created and updated by the 'android'
|
||||
tool, as well as ADT.
|
||||
|
||||
This contains project specific properties such as project target, and library
|
||||
dependencies. Lower level build properties are stored in ant.properties
|
||||
(or in .classpath for Eclipse projects).
|
||||
|
||||
This file is an integral part of the build system for your
|
||||
application and should be checked into Version Control Systems. -->
|
||||
<loadproperties srcFile="project.properties" />
|
||||
|
||||
<!-- quick check on sdk.dir -->
|
||||
<fail
|
||||
message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
|
||||
unless="sdk.dir"
|
||||
/>
|
||||
|
||||
<!--
|
||||
Import per project custom build rules if present at the root of the project.
|
||||
This is the place to put custom intermediary targets such as:
|
||||
-pre-build
|
||||
-pre-compile
|
||||
-post-compile (This is typically used for code obfuscation.
|
||||
Compiled code location: ${out.classes.absolute.dir}
|
||||
If this is not done in place, override ${out.dex.input.absolute.dir})
|
||||
-post-package
|
||||
-post-build
|
||||
-pre-clean
|
||||
-->
|
||||
<import file="custom_rules.xml" optional="true" />
|
||||
|
||||
<!-- Import the actual build file.
|
||||
|
||||
To customize existing targets, there are two options:
|
||||
- Customize only one target:
|
||||
- copy/paste the target into this file, *before* the
|
||||
<import> task.
|
||||
- customize it to your needs.
|
||||
- Customize the whole content of build.xml
|
||||
- copy/paste the content of the rules files (minus the top node)
|
||||
into this file, replacing the <import> task.
|
||||
- customize to your needs.
|
||||
|
||||
***********************
|
||||
****** IMPORTANT ******
|
||||
***********************
|
||||
In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
|
||||
in order to avoid having your file be overridden by tools such as "android update project"
|
||||
-->
|
||||
<!-- version-tag: VERSION_TAG -->
|
||||
<import file="${sdk.dir}/tools/ant/uibuild.xml" />
|
||||
|
||||
</project>
|
14
wlauto/workloads/googlephotos/uiauto/project.properties
Normal file
14
wlauto/workloads/googlephotos/uiauto/project.properties
Normal file
@ -0,0 +1,14 @@
|
||||
# This file is automatically generated by Android Tools.
|
||||
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||
#
|
||||
# This file must be checked in Version Control Systems.
|
||||
#
|
||||
# To customize properties used by the Ant build system edit
|
||||
# "ant.properties", and override values to adapt the script to your
|
||||
# project structure.
|
||||
#
|
||||
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
|
||||
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
||||
|
||||
# Project target.
|
||||
target=android-18
|
486
wlauto/workloads/googlephotos/uiauto/src/com/arm/wlauto/uiauto/UiAutomation.java
Executable file
486
wlauto/workloads/googlephotos/uiauto/src/com/arm/wlauto/uiauto/UiAutomation.java
Executable file
@ -0,0 +1,486 @@
|
||||
/* Copyright 2014-2016 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.arm.wlauto.uiauto.googlephotos;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.graphics.Rect;
|
||||
|
||||
// Import the uiautomator libraries
|
||||
import com.android.uiautomator.core.UiObject;
|
||||
import com.android.uiautomator.core.UiObjectNotFoundException;
|
||||
import com.android.uiautomator.core.UiSelector;
|
||||
import com.android.uiautomator.core.UiScrollable;
|
||||
|
||||
import com.arm.wlauto.uiauto.UxPerfUiAutomation;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
public class UiAutomation extends UxPerfUiAutomation {
|
||||
|
||||
public static String TAG = "uxperf_googlephotos";
|
||||
|
||||
public Bundle parameters;
|
||||
public String packageName;
|
||||
public String packageID;
|
||||
|
||||
private int viewTimeoutSecs = 10;
|
||||
private long viewTimeout = TimeUnit.SECONDS.toMillis(viewTimeoutSecs);
|
||||
|
||||
public void runUiAutomation() throws Exception {
|
||||
parameters = getParams();
|
||||
packageName = parameters.getString("package");
|
||||
packageID = packageName + ":id/";
|
||||
|
||||
pauseForSplashScreen();
|
||||
setScreenOrientation(ScreenOrientation.NATURAL);
|
||||
dismissWelcomeView();
|
||||
closePromotionPopUp();
|
||||
selectWorkingGallery();
|
||||
gesturesTest();
|
||||
editPhotoColorTest();
|
||||
cropPhotoTest();
|
||||
rotatePhotoTest();
|
||||
unsetScreenOrientation();
|
||||
}
|
||||
|
||||
public void pauseForSplashScreen() {
|
||||
sleep(5); // Pause while splash screen loads
|
||||
}
|
||||
|
||||
public void dismissWelcomeView() throws Exception {
|
||||
|
||||
// Click through the first two pages and make sure that we don't sign
|
||||
// in to our google account. This ensures the same set of photographs
|
||||
// are placed in the camera directory for each run.
|
||||
UiObject getStartedButton =
|
||||
new UiObject(new UiSelector().textContains("Get started")
|
||||
.className("android.widget.Button"));
|
||||
|
||||
if (getStartedButton.waitForExists(viewTimeout)) {
|
||||
getStartedButton.click();
|
||||
}
|
||||
|
||||
// A network connection is not required for this workload. However,
|
||||
// when the Google Photos app is invoked from the multiapp workload a
|
||||
// connection is required for sharing content. Handle the different UI
|
||||
// pathways when dismissing welcome views here.
|
||||
UiObject doNotSignInButton =
|
||||
new UiObject(new UiSelector().resourceId(packageID + "dont_sign_in_button"));
|
||||
|
||||
// Folder containing test images (early check required)
|
||||
UiObject workingFolder = new UiObject(new UiSelector().text("wa-working"));
|
||||
|
||||
if (doNotSignInButton.exists()) {
|
||||
doNotSignInButton.click();
|
||||
} else {
|
||||
UiObject welcomeButton =
|
||||
getUiObjectByResourceId(packageID + "name",
|
||||
"android.widget.TextView");
|
||||
welcomeButton.click();
|
||||
|
||||
UiObject useWithoutAccount =
|
||||
getUiObjectByText("Use without an account", "android.widget.TextView");
|
||||
useWithoutAccount.clickAndWaitForNewWindow();
|
||||
|
||||
// On some devices the welcome views don't always appear so check
|
||||
// for the existence of the wa-working directory before attempting
|
||||
// to dismiss welcome views promoting app features
|
||||
if (!workingFolder.exists()) {
|
||||
sleep(1);
|
||||
uiDeviceSwipeLeft(10);
|
||||
sleep(1);
|
||||
uiDeviceSwipeLeft(10);
|
||||
sleep(1);
|
||||
uiDeviceSwipeLeft(10);
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
UiObject nextButton =
|
||||
new UiObject(new UiSelector().resourceId(packageID + "next_button")
|
||||
.className("android.widget.ImageView"));
|
||||
|
||||
if (nextButton.exists()) {
|
||||
nextButton.clickAndWaitForNewWindow();
|
||||
}
|
||||
}
|
||||
|
||||
private void gesturesTest() throws Exception {
|
||||
String testTag = "gestures";
|
||||
|
||||
// Perform a range of swipe tests while browsing photo gallery
|
||||
LinkedHashMap<String, GestureTestParams> testParams = new LinkedHashMap<String, GestureTestParams>();
|
||||
testParams.put("swipe_left", new GestureTestParams(GestureType.UIDEVICE_SWIPE, Direction.LEFT, 10));
|
||||
testParams.put("pinch_out", new GestureTestParams(GestureType.PINCH, PinchType.OUT, 100, 50));
|
||||
testParams.put("pinch_in", new GestureTestParams(GestureType.PINCH, PinchType.IN, 100, 50));
|
||||
testParams.put("swipe_right", new GestureTestParams(GestureType.UIDEVICE_SWIPE, Direction.RIGHT, 10));
|
||||
|
||||
Iterator<Entry<String, GestureTestParams>> it = testParams.entrySet().iterator();
|
||||
|
||||
// Select first photograph
|
||||
selectPhoto(1);
|
||||
|
||||
while (it.hasNext()) {
|
||||
Map.Entry<String, GestureTestParams> pair = it.next();
|
||||
GestureType type = pair.getValue().gestureType;
|
||||
Direction dir = pair.getValue().gestureDirection;
|
||||
PinchType pinch = pair.getValue().pinchType;
|
||||
int steps = pair.getValue().steps;
|
||||
int percent = pair.getValue().percent;
|
||||
|
||||
UiObject view = new UiObject(new UiSelector().enabled(true));
|
||||
|
||||
if (!view.waitForExists(viewTimeout)) {
|
||||
throw new UiObjectNotFoundException("Could not find \"photo view\".");
|
||||
}
|
||||
|
||||
String runName = String.format(testTag + "_" + pair.getKey());
|
||||
ActionLogger logger = new ActionLogger(runName, parameters);
|
||||
logger.start();
|
||||
|
||||
switch (type) {
|
||||
case UIDEVICE_SWIPE:
|
||||
uiDeviceSwipe(dir, steps);
|
||||
break;
|
||||
case UIOBJECT_SWIPE:
|
||||
uiObjectSwipe(view, dir, steps);
|
||||
break;
|
||||
case PINCH:
|
||||
uiObjectVertPinch(view, pinch, steps, percent);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
logger.stop();
|
||||
}
|
||||
|
||||
UiObject navigateUpButton =
|
||||
getUiObjectByDescription("Navigate Up", "android.widget.ImageButton");
|
||||
navigateUpButton.click();
|
||||
}
|
||||
|
||||
public enum Position { LEFT, RIGHT, CENTRE };
|
||||
|
||||
private class SeekBarTestParams {
|
||||
|
||||
private Position seekBarPosition;
|
||||
private int percent;
|
||||
private int steps;
|
||||
|
||||
SeekBarTestParams(final Position position, final int steps, final int percent) {
|
||||
this.seekBarPosition = position;
|
||||
this.steps = steps;
|
||||
this.percent = percent;
|
||||
}
|
||||
}
|
||||
|
||||
private void editPhotoColorTest() throws Exception {
|
||||
String testTag = "edit_photo";
|
||||
|
||||
// Perform a range of swipe tests while browsing photo gallery
|
||||
LinkedHashMap<String, SeekBarTestParams> testParams = new LinkedHashMap<String, SeekBarTestParams>();
|
||||
testParams.put("increment_color", new SeekBarTestParams(Position.RIGHT, 10, 20));
|
||||
testParams.put("reset_color", new SeekBarTestParams(Position.CENTRE, 0, 0));
|
||||
testParams.put("decrement_color", new SeekBarTestParams(Position.LEFT, 10, 20));
|
||||
|
||||
Iterator<Entry<String, SeekBarTestParams>> it = testParams.entrySet().iterator();
|
||||
|
||||
// Select second photograph
|
||||
selectPhoto(2);
|
||||
UiObject editView = getUiObjectByResourceId(packageID + "edit",
|
||||
"android.widget.ImageView");
|
||||
editView.click();
|
||||
|
||||
// Manage potential different spelling of UI element
|
||||
UiObject editColor = new UiObject(new UiSelector().text("Color"));
|
||||
UiObject editColour = new UiObject(new UiSelector().text("Colour"));
|
||||
|
||||
long timeout = TimeUnit.SECONDS.toMillis(3);
|
||||
|
||||
if (editColor.waitForExists(timeout)) {
|
||||
editColor.click();
|
||||
} else if (editColour.waitForExists(timeout)) {
|
||||
editColour.click();
|
||||
} else {
|
||||
throw new UiObjectNotFoundException(String.format("Could not find \"%s\" \"%s\"",
|
||||
"Color/Colour", "android.widget.RadioButton"));
|
||||
}
|
||||
|
||||
UiObject seekBar = getUiObjectByResourceId(packageID + "cpe_strength_seek_bar",
|
||||
"android.widget.SeekBar");
|
||||
|
||||
while (it.hasNext()) {
|
||||
Map.Entry<String, SeekBarTestParams> pair = it.next();
|
||||
Position pos = pair.getValue().seekBarPosition;
|
||||
int steps = pair.getValue().steps;
|
||||
int percent = pair.getValue().percent;
|
||||
|
||||
String runName = String.format(testTag + "_" + pair.getKey());
|
||||
ActionLogger logger = new ActionLogger(runName, parameters);
|
||||
|
||||
sleep(1); // pause for stability before editing the colour
|
||||
|
||||
logger.start();
|
||||
seekBarTest(seekBar, pos, steps);
|
||||
logger.stop();
|
||||
}
|
||||
|
||||
closeAndReturn(true);
|
||||
}
|
||||
|
||||
private void cropPhotoTest() throws Exception {
|
||||
String testTag = "crop_photo";
|
||||
|
||||
// To improve travel accuracy perform the slide bar operation slowly
|
||||
final int steps = 500;
|
||||
|
||||
// Perform a range of swipe tests while browsing photo gallery
|
||||
LinkedHashMap<String, Position> testParams = new LinkedHashMap<String, Position>();
|
||||
testParams.put("tilt_positive", Position.LEFT);
|
||||
testParams.put("tilt_reset", Position.RIGHT);
|
||||
testParams.put("tilt_negative", Position.RIGHT);
|
||||
|
||||
Iterator<Entry<String, Position>> it = testParams.entrySet().iterator();
|
||||
|
||||
// Select third photograph
|
||||
selectPhoto(3);
|
||||
UiObject editView = getUiObjectByResourceId(packageID + "edit",
|
||||
"android.widget.ImageView");
|
||||
editView.click();
|
||||
|
||||
UiObject cropTool = getUiObjectByResourceId(packageID + "cpe_crop_tool",
|
||||
"android.widget.ImageView");
|
||||
cropTool.click();
|
||||
|
||||
UiObject straightenSlider = getUiObjectByResourceId(packageID + "cpe_straighten_slider");
|
||||
|
||||
while (it.hasNext()) {
|
||||
Map.Entry<String, Position> pair = it.next();
|
||||
Position pos = pair.getValue();
|
||||
|
||||
String runName = String.format(testTag + "_" + pair.getKey());
|
||||
ActionLogger logger = new ActionLogger(runName, parameters);
|
||||
|
||||
logger.start();
|
||||
slideBarTest(straightenSlider, pos, steps);
|
||||
logger.stop();
|
||||
}
|
||||
|
||||
closeAndReturn(true);
|
||||
}
|
||||
|
||||
private void rotatePhotoTest() throws Exception {
|
||||
String testTag = "rotate_photo";
|
||||
|
||||
String[] subTests = {"anticlockwise_90", "anticlockwise_180", "anticlockwise_270"};
|
||||
|
||||
// Select fourth photograph
|
||||
selectPhoto(4);
|
||||
UiObject editView = getUiObjectByResourceId(packageID + "edit",
|
||||
"android.widget.ImageView");
|
||||
editView.click();
|
||||
|
||||
UiObject cropTool = getUiObjectByResourceId(packageID + "cpe_crop_tool");
|
||||
cropTool.click();
|
||||
|
||||
UiObject rotate = getUiObjectByResourceId(packageID + "cpe_rotate_90");
|
||||
|
||||
for (String subTest : subTests) {
|
||||
String runName = String.format(testTag + "_" + subTest);
|
||||
ActionLogger logger = new ActionLogger(runName, parameters);
|
||||
|
||||
logger.start();
|
||||
rotate.click();
|
||||
logger.stop();
|
||||
}
|
||||
|
||||
closeAndReturn(true);
|
||||
}
|
||||
|
||||
// Helper to slide the seekbar during photo edit.
|
||||
private void seekBarTest(final UiObject view, final Position pos, final int steps) throws Exception {
|
||||
final int SWIPE_MARGIN_LIMIT = 5;
|
||||
Rect rect = view.getVisibleBounds();
|
||||
|
||||
switch (pos) {
|
||||
case LEFT:
|
||||
getUiDevice().click(rect.left + SWIPE_MARGIN_LIMIT, rect.centerY());
|
||||
break;
|
||||
case RIGHT:
|
||||
getUiDevice().click(rect.right - SWIPE_MARGIN_LIMIT, rect.centerY());
|
||||
break;
|
||||
case CENTRE:
|
||||
view.click();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Helper to slide the slidebar during photo edit.
|
||||
private void slideBarTest(final UiObject view, final Position pos, final int steps) throws Exception {
|
||||
final int SWIPE_MARGIN_LIMIT = 5;
|
||||
Rect rect = view.getBounds();
|
||||
|
||||
switch (pos) {
|
||||
case LEFT:
|
||||
getUiDevice().drag(rect.left + SWIPE_MARGIN_LIMIT, rect.centerY(),
|
||||
rect.left + rect.width() / 4, rect.centerY(),
|
||||
steps);
|
||||
break;
|
||||
case RIGHT:
|
||||
getUiDevice().drag(rect.right - SWIPE_MARGIN_LIMIT, rect.centerY(),
|
||||
rect.right - rect.width() / 4, rect.centerY(),
|
||||
steps);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void closePromotionPopUp() throws Exception {
|
||||
UiObject promoCloseButton =
|
||||
new UiObject(new UiSelector().resourceId(packageID + "promo_close_button"));
|
||||
|
||||
if (promoCloseButton.exists()) {
|
||||
promoCloseButton.click();
|
||||
}
|
||||
}
|
||||
|
||||
// Helper to click on the wa-working gallery.
|
||||
public void selectWorkingGallery() throws Exception {
|
||||
UiObject workdir = new UiObject(new UiSelector().text("wa-working")
|
||||
.className("android.widget.TextView"));
|
||||
|
||||
// If the wa-working gallery is not present wait for a short time for
|
||||
// the media server to refresh its index.
|
||||
boolean discovered = workdir.waitForExists(viewTimeout);
|
||||
UiScrollable scrollView = new UiScrollable(new UiSelector().scrollable(true));
|
||||
|
||||
if (!discovered && scrollView.exists()) {
|
||||
// First check if the wa-working directory is visible on the first
|
||||
// screen and if not scroll to the bottom of the screen to look for it.
|
||||
discovered = scrollView.scrollIntoView(workdir);
|
||||
|
||||
// If still not discovered scroll back to the top of the screen and
|
||||
// wait for a longer amount of time for the media server to refresh
|
||||
// its index.
|
||||
if (!discovered) {
|
||||
// scrollView.scrollToBeggining() doesn't work for this
|
||||
// particular scrollable view so use device method instead
|
||||
for (int i = 0; i < 10; i++) {
|
||||
uiDeviceSwipeUp(20);
|
||||
}
|
||||
discovered = workdir.waitForExists(TimeUnit.SECONDS.toMillis(60));
|
||||
|
||||
// Scroll to the bottom of the screen one last time
|
||||
if (!discovered) {
|
||||
discovered = scrollView.scrollIntoView(workdir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (discovered) {
|
||||
workdir.clickAndWaitForNewWindow();
|
||||
} else {
|
||||
throw new UiObjectNotFoundException("Could not find \"wa-working\" folder");
|
||||
}
|
||||
}
|
||||
|
||||
// Helper to click on an individual photograph based on index in wa-working gallery.
|
||||
public void selectPhoto(final int index) throws Exception {
|
||||
UiObject photo =
|
||||
new UiObject(new UiSelector().resourceId(packageID + "recycler_view")
|
||||
.childSelector(new UiSelector()
|
||||
.index(index)));
|
||||
|
||||
// On some versions of the app a non-zero index is used for the
|
||||
// photographs position while on other versions a zero index is used.
|
||||
// Try both possiblities before throwing an exception.
|
||||
if (photo.exists()) {
|
||||
photo.click();
|
||||
} else {
|
||||
photo = new UiObject(new UiSelector().resourceId(packageID + "recycler_view")
|
||||
.childSelector(new UiSelector()
|
||||
.index(index - 1)));
|
||||
photo.click();
|
||||
}
|
||||
}
|
||||
|
||||
// Helper that accepts, closes and navigates back to application home screen after an edit operation.
|
||||
// dontsave - True will discard the image. False will save the image
|
||||
public void closeAndReturn(final boolean dontsave) throws Exception {
|
||||
UiObject accept = new UiObject(new UiSelector().description("Accept"));
|
||||
UiObject done = new UiObject(new UiSelector().resourceId(packageID + "cpe_save_button"));
|
||||
|
||||
long timeout = TimeUnit.SECONDS.toMillis(3);
|
||||
|
||||
// On some edit operations we can either confirm an edit with "Accept" or "DONE"
|
||||
if (accept.waitForExists(timeout)) {
|
||||
accept.click();
|
||||
} else if (done.waitForExists(timeout)) {
|
||||
done.click();
|
||||
} else {
|
||||
throw new UiObjectNotFoundException("Could not find \"Accept\" or \"DONE\" button.");
|
||||
}
|
||||
|
||||
if (dontsave) {
|
||||
UiObject close = getUiObjectByDescription("Close editor", "android.widget.ImageView");
|
||||
close.click();
|
||||
|
||||
UiObject discard = getUiObjectByText("DISCARD", "android.widget.Button");
|
||||
discard.waitForExists(viewTimeout);
|
||||
discard.click();
|
||||
} else {
|
||||
UiObject save = getUiObjectByText("SAVE", "android.widget.TextView");
|
||||
save.waitForExists(viewTimeout);
|
||||
save.click();
|
||||
}
|
||||
|
||||
UiObject navigateUpButton =
|
||||
new UiObject(new UiSelector().descriptionContains("Navigate Up")
|
||||
.className("android.widget.ImageButton"));
|
||||
navigateUpButton.waitForExists(viewTimeout);
|
||||
navigateUpButton.click();
|
||||
}
|
||||
|
||||
// Helper to tag an individual photograph based on the index in wa-working
|
||||
// gallery. After long clicking it tags the photograph with a tick in the
|
||||
// corner of the image to indicate that the photograph has been selected
|
||||
public void tagPhoto(final int index) throws Exception {
|
||||
UiObject photo =
|
||||
new UiObject(new UiSelector().resourceId(packageID + "recycler_view")
|
||||
.childSelector(new UiSelector()
|
||||
.index(index)));
|
||||
|
||||
// On some versions of the app a non-zero index is used for the
|
||||
// photographs position while on other versions a zero index is used.
|
||||
// Try both possiblities before throwing an exception.
|
||||
if (photo.exists()) {
|
||||
uiObjectPerformLongClick(photo, 100);
|
||||
} else {
|
||||
photo = new UiObject(new UiSelector().resourceId(packageID + "recycler_view")
|
||||
.childSelector(new UiSelector()
|
||||
.index(index - 1)));
|
||||
uiObjectPerformLongClick(photo, 100);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user