Commit 8e336818 authored by Vitaliy Vashchenko's avatar Vitaliy Vashchenko

Merge branch 'feature-itests' into 'V3.7'

Feature itests

See merge request !733
parents c688eec5 13066d44
...@@ -79,6 +79,8 @@ unitTest: ...@@ -79,6 +79,8 @@ unitTest:
iTest-desktop: iTest-desktop:
stage: iTest-desktop stage: iTest-desktop
only:
- schedules
script: script:
- ./gradlew desktop:runITestBundle - ./gradlew desktop:runITestBundle
artifacts: artifacts:
......
...@@ -218,6 +218,11 @@ task copyAndroidNatives() { ...@@ -218,6 +218,11 @@ task copyAndroidNatives() {
} }
task run(type: Exec) { task run(type: Exec) {
def adb = doAndroidSettings()
commandLine "$adb", 'shell', 'am', 'start', '-n', 'cz.nic.tablexia.android/cz.nic.tablexia.android.AndroidLauncher'
}
def doAndroidSettings() {
def path def path
def localProperties = project.file("../local.properties") def localProperties = project.file("../local.properties")
if (localProperties.exists()) { if (localProperties.exists()) {
...@@ -235,8 +240,7 @@ task run(type: Exec) { ...@@ -235,8 +240,7 @@ task run(type: Exec) {
path = "$System.env.ANDROID_HOME" path = "$System.env.ANDROID_HOME"
} }
def adb = path + "/platform-tools/adb" return path + "/platform-tools/adb"
commandLine "$adb", 'shell', 'am', 'start', '-n', 'cz.nic.tablexia.android/cz.nic.tablexia.android.AndroidLauncher'
} }
// sets up the Android Idea project, using the old Ant based build. // sets up the Android Idea project, using the old Ant based build.
...@@ -261,3 +265,128 @@ idea { ...@@ -261,3 +265,128 @@ idea {
} }
} }
} }
def runTest(String iTestName, String device) {
println "[iTest-" + device + "] STARTING TEST: " + iTestName
def adb = doAndroidSettings()
exec {
commandLine "$adb", '-s', device, 'shell', 'am', 'start', '-n', 'cz.nic.tablexia.itest/cz.nic.tablexia.android.AndroidITestLauncher', '-e', 'testClassName', iTestName
}
def adbStdOut = new ByteArrayOutputStream()
def timeout = 0;
while(timeout<1200) { //timeout is set to 20 minuts
if(adbStdOut.toString().trim().contains("PROCESSING")){
def adbPSOut = new ByteArrayOutputStream()
exec {
commandLine "$adb", '-s', device, 'shell', "ps", "|", "grep", "cz.nic.tablexia.itest"
standardOutput = adbPSOut
}
if(!adbPSOut.toString().contains("cz.nic.tablexia.itest")) return //stop if test is not running anymore
}
if(adbStdOut.toString().trim().contains("OK")) return
if(adbStdOut.toString().trim().contains("FAIL")) return
exec {
commandLine "$adb", '-s', device, 'shell', "ls", "/sdcard/iTest_results"
standardOutput = adbStdOut
}
sleep(1000)
timeout++;
}
println "[iTest-" + device + "] Test " + iTestName + " timed out."
}
String androidITestBundle(String device){
int testsCount = 0;
int successfulTestsCount = 0;
def tablexiaApk = project.tablexiaAppName + "-iTest-" + "$tablexiaVersionName" + ".apk"
def apkFolder = "${project(':android').projectDir}/build/outputs/apk/"
def sdCardResults = "/sdcard/iTest_results"
println "[iTest-" + device + "] INSTALLING " + tablexiaApk + " into connected Android device"
if(!new File(apkFolder + tablexiaApk).exists()){
throw new GradleException("Could not install " + tablexiaApk + " - file does not exists!")
return
}
def adb = doAndroidSettings()
exec {
commandLine "$adb", '-s', device, 'install', '-r', apkFolder + tablexiaApk
}
println "[iTest-" + device + "] INSTALLING Tablexia COMPLETED"
println "[iTest-" + device + "] CREATING NEW iTest OUTPUT DIRECTORY"
def iTestOutputFolder = "iTest_results-" + device
def iTestOutputFile = new File(apkFolder + iTestOutputFolder)
if (iTestOutputFile.exists()) {
println "[iTest-" + device + "] REMOVING OLD iTest OUTPUT DIRECTORY"
iTestOutputFile.deleteDir()
}
project.file(apkFolder + iTestOutputFolder).mkdirs()
new File("${project(':itest').projectDir}/iTestBundle.txt").eachLine { iTestName ->
exec {
commandLine "$adb", '-s', device, 'shell', 'rm', '-r', sdCardResults
}
println "[iTest-" + device + "] OLD FILES on SDCARD REMOVED"
testsCount++
runTest(iTestName, device)
println "[iTest-" + device + "] TEST: " + iTestName + " FINISHED"
exec {
commandLine "$adb", '-s', device, 'pull', sdCardResults, apkFolder + iTestOutputFolder+ "/"
}
println "[iTest-" + device + "] LOG FILES WERE MOVED INTO " + iTestOutputFile.toString()
}
file("$iTestOutputFile" + "/iTest_results").eachFile { logFile ->
if(logFile.toString().contains("OK")) successfulTestsCount++;
}
if (testsCount != successfulTestsCount){
println "[iTest-" + device + "] ONE OR MORE OF TESTS ON THIS DEVICE FINISHED WITH STATUS FAIL!"
return "[iTest-" + device + "] Failed to complete all iTests! Check iTest log files in: " + iTestOutputFile.toString() + "/iTest_results/\n"
}
else{
println "[iTest-" + device + "] ALL TESTS ON THIS DEVICE FINISHED WITH STATUS OK!"
return ""
}
}
task runAndroidITestBundle (dependsOn:'assembleITest'){
doLast {
def adbOut = new ByteArrayOutputStream()
def adb = doAndroidSettings()
exec {
commandLine "$adb", 'devices'
standardOutput = adbOut
}
def connectedDevices = 0
def exceptions = ""
def threads = []
adbOut.toString().eachLine { line ->
def th = new Thread({ //run devices parallel
if (!line.contains("List") && line.contains("device")) {
connectedDevices++
def device = line.split('\t')[0]
println "Connected device: " + device
def adbLsOut = new ByteArrayOutputStream()
exec {
commandLine "$adb", '-s', device, 'shell', 'ls'
standardOutput = adbLsOut
}
if (adbLsOut.toString().contains("error")) {
exceptions += "[iTest-" + device + "] Device does not meet requirements for running tests. Try to check out if device has SD card and SD card is accessible from computer."
println "[iTest-" + device + "] THIS DEVICE DOES NOT MEET REQUIREMENTS FOR RUNNING TESTS."
} else exceptions += androidITestBundle(device)
}
})
threads << th
}
threads.each { it.start() }
threads.each { it.join() }
if(connectedDevices<1) throw new GradleException("NO CONNECTED DEVICE WAS FOUND!")
if(exceptions!="") throw new GradleException(exceptions)
}
}
\ No newline at end of file
...@@ -57,6 +57,7 @@ import cz.nic.tablexia.game.games.crime_scene.model.bonus.BonusSoundsSetting; ...@@ -57,6 +57,7 @@ import cz.nic.tablexia.game.games.crime_scene.model.bonus.BonusSoundsSetting;
import cz.nic.tablexia.loader.application.ApplicationAtlasManager; import cz.nic.tablexia.loader.application.ApplicationAtlasManager;
import cz.nic.tablexia.loader.application.ApplicationInternalTextureManager; import cz.nic.tablexia.loader.application.ApplicationInternalTextureManager;
import cz.nic.tablexia.loader.application.ApplicationTextManager; import cz.nic.tablexia.loader.application.ApplicationTextManager;
import cz.nic.tablexia.screen.AbstractTablexiaScreen;
import cz.nic.tablexia.shared.model.Game; import cz.nic.tablexia.shared.model.Game;
import cz.nic.tablexia.shared.model.resolvers.CrimeSceneScoreResolver; import cz.nic.tablexia.shared.model.resolvers.CrimeSceneScoreResolver;
import cz.nic.tablexia.util.Log; import cz.nic.tablexia.util.Log;
...@@ -88,6 +89,7 @@ public class CrimeSceneGame extends AbstractTablexiaGame<CrimeSceneGameState> { ...@@ -88,6 +89,7 @@ public class CrimeSceneGame extends AbstractTablexiaGame<CrimeSceneGameState> {
public static final String EVENT_START_PLAY = "event start play"; public static final String EVENT_START_PLAY = "event start play";
public static final String EVENT_FINISH_SOUND = "event finish sound index: "; public static final String EVENT_FINISH_SOUND = "event finish sound index: ";
public static final String EVENT_ACTION_CONTROLLED = "event control action: "; public static final String EVENT_ACTION_CONTROLLED = "event control action: ";
public static final String EVENT_HIGHLIGHTED_GO = "higlighted object shown";
public static final int ACTION_CARD_DRAG_SIZE = 100; public static final int ACTION_CARD_DRAG_SIZE = 100;
...@@ -784,6 +786,7 @@ public class CrimeSceneGame extends AbstractTablexiaGame<CrimeSceneGameState> { ...@@ -784,6 +786,7 @@ public class CrimeSceneGame extends AbstractTablexiaGame<CrimeSceneGameState> {
public void setHighlightedGameObject(GameObject highlightedGameObject) { public void setHighlightedGameObject(GameObject highlightedGameObject) {
this.highlightedGameObject = highlightedGameObject; this.highlightedGameObject = highlightedGameObject;
if(highlightedGameObject!=null) AbstractTablexiaScreen.triggerScenarioStepEvent(EVENT_HIGHLIGHTED_GO);
} }
......
...@@ -22,6 +22,7 @@ import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable; ...@@ -22,6 +22,7 @@ import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
import cz.nic.tablexia.TablexiaSettings; import cz.nic.tablexia.TablexiaSettings;
import cz.nic.tablexia.game.games.crime_scene.CrimeSceneGame; import cz.nic.tablexia.game.games.crime_scene.CrimeSceneGame;
import cz.nic.tablexia.screen.AbstractTablexiaScreen;
import cz.nic.tablexia.util.ui.actionwidget.Action; import cz.nic.tablexia.util.ui.actionwidget.Action;
import cz.nic.tablexia.util.ui.actionwidget.ActionsStripWidget; import cz.nic.tablexia.util.ui.actionwidget.ActionsStripWidget;
import cz.nic.tablexia.util.ui.tilemapgenerator.Position; import cz.nic.tablexia.util.ui.tilemapgenerator.Position;
...@@ -32,6 +33,7 @@ import cz.nic.tablexia.util.ui.tilemapgenerator.Position; ...@@ -32,6 +33,7 @@ import cz.nic.tablexia.util.ui.tilemapgenerator.Position;
* Created by danilov on 18.4.16. * Created by danilov on 18.4.16.
*/ */
public class GameObject extends Group implements Action.ActionListener { public class GameObject extends Group implements Action.ActionListener {
public static final String EVENT_DROP_DOWN = "drop down card";
private ActionsStripWidget actionsStripWidget; private ActionsStripWidget actionsStripWidget;
private CrimeSceneGame crimeSceneGame; private CrimeSceneGame crimeSceneGame;
...@@ -74,7 +76,7 @@ public class GameObject extends Group implements Action.ActionListener { ...@@ -74,7 +76,7 @@ public class GameObject extends Group implements Action.ActionListener {
@Override @Override
public void onActionDrop(Action action, int collidesWithNumber) { public void onActionDrop(Action action, int collidesWithNumber) {
AbstractTablexiaScreen.triggerScenarioStepEvent(EVENT_DROP_DOWN);
if (collidesWithNumber != Action.NO_COLLISION_NUMBER) { if (collidesWithNumber != Action.NO_COLLISION_NUMBER) {
// FIXME: 10/30/17 why to store action number if using ordinal? // FIXME: 10/30/17 why to store action number if using ordinal?
if (!crimeSceneGame.isActionAdded(action)) actionsStripWidget.addSelectedAction(GameObjectType.values()[action.getActionNumber()].getActionTexturePath(), collidesWithNumber, crimeSceneGame, action.getActionNumber()); if (!crimeSceneGame.isActionAdded(action)) actionsStripWidget.addSelectedAction(GameObjectType.values()[action.getActionNumber()].getActionTexturePath(), collidesWithNumber, crimeSceneGame, action.getActionNumber());
......
...@@ -28,7 +28,6 @@ import cz.nic.tablexia.game.games.crime_scene.gameobject.GameObject; ...@@ -28,7 +28,6 @@ import cz.nic.tablexia.game.games.crime_scene.gameobject.GameObject;
import cz.nic.tablexia.util.entity.Touch; import cz.nic.tablexia.util.entity.Touch;
public class DesktopCrimeSceneDragListener extends CrimeSceneDragListener { public class DesktopCrimeSceneDragListener extends CrimeSceneDragListener {
private Timer timer; private Timer timer;
private static final float DELAY = 0.15f; private static final float DELAY = 0.15f;
Touch lastRecordedTouchDown; Touch lastRecordedTouchDown;
......
...@@ -30,6 +30,7 @@ import cz.nic.tablexia.TablexiaSettings; ...@@ -30,6 +30,7 @@ import cz.nic.tablexia.TablexiaSettings;
import cz.nic.tablexia.game.games.in_the_darkness.InTheDarknessDifficulty; import cz.nic.tablexia.game.games.in_the_darkness.InTheDarknessDifficulty;
import cz.nic.tablexia.game.games.in_the_darkness.InTheDarknessGame; import cz.nic.tablexia.game.games.in_the_darkness.InTheDarknessGame;
import cz.nic.tablexia.game.games.in_the_darkness.action.InTheDarknessActionType; import cz.nic.tablexia.game.games.in_the_darkness.action.InTheDarknessActionType;
import cz.nic.tablexia.screen.AbstractTablexiaScreen;
import cz.nic.tablexia.util.ui.actionwidget.Action; import cz.nic.tablexia.util.ui.actionwidget.Action;
import cz.nic.tablexia.util.ui.actionwidget.Action.ActionListener; import cz.nic.tablexia.util.ui.actionwidget.Action.ActionListener;
import cz.nic.tablexia.game.games.in_the_darkness.assets.InTheDarknessAssets; import cz.nic.tablexia.game.games.in_the_darkness.assets.InTheDarknessAssets;
...@@ -49,6 +50,7 @@ import static com.badlogic.gdx.scenes.scene2d.actions.Actions.sequence; ...@@ -49,6 +50,7 @@ import static com.badlogic.gdx.scenes.scene2d.actions.Actions.sequence;
* *
*/ */
public class ActionsWidget extends Group implements ActionListener { public class ActionsWidget extends Group implements ActionListener {
public static final String EVENT_DROP_DOWN = "drop down card";
public enum ActionLayer { public enum ActionLayer {
BACKGROUND_LAYER (0), BACKGROUND_LAYER (0),
...@@ -257,6 +259,7 @@ public class ActionsWidget extends Group implements ActionListener { ...@@ -257,6 +259,7 @@ public class ActionsWidget extends Group implements ActionListener {
@Override @Override
public void onActionDrop(Action action, int collidesWithNumber) { public void onActionDrop(Action action, int collidesWithNumber) {
AbstractTablexiaScreen.triggerScenarioStepEvent(EVENT_DROP_DOWN);
if (collidesWithNumber != Action.NO_COLLISION_NUMBER) { if (collidesWithNumber != Action.NO_COLLISION_NUMBER) {
actionsStripWidget.addSelectedAction(action.getTexturePath(), collidesWithNumber, inTheDarknessGame, action.getActionNumber()); actionsStripWidget.addSelectedAction(action.getTexturePath(), collidesWithNumber, inTheDarknessGame, action.getActionNumber());
currentTutorialStepNumber++; currentTutorialStepNumber++;
......
...@@ -72,7 +72,7 @@ public class RunesGame extends AbstractTablexiaGame<RunesGameState> { ...@@ -72,7 +72,7 @@ public class RunesGame extends AbstractTablexiaGame<RunesGameState> {
public static final String RUNES_GROUP = "runes group"; public static final String RUNES_GROUP = "runes group";
public static final String HEALTH_BAR = "health bar"; public static final String HEALTH_BAR = "health bar";
public static final String EVENT_NEXT_ROUND = "next round"; public static final String EVENT_ROUND_READY = "round ready";
private static final int ONE_SECOND_DELAY = 1; private static final int ONE_SECOND_DELAY = 1;
private static final int START_SOUND_BOUND = 8; private static final int START_SOUND_BOUND = 8;
...@@ -338,7 +338,12 @@ public class RunesGame extends AbstractTablexiaGame<RunesGameState> { ...@@ -338,7 +338,12 @@ public class RunesGame extends AbstractTablexiaGame<RunesGameState> {
private void nextRound() { private void nextRound() {
runesGroup.addAction(Actions.fadeIn(FADE_ANIMATION_DURATION)); runesGroup.addAction(Actions.sequence(Actions.fadeIn(FADE_ANIMATION_DURATION), Actions.run(new Runnable() {
@Override
public void run() {
triggerScenarioStepEvent(EVENT_ROUND_READY);
}
})));
getData().setPhase(RunesGameState.RunesGamePhase.GAME); getData().setPhase(RunesGameState.RunesGamePhase.GAME);
timeBar.startGameState(); timeBar.startGameState();
targetPlate.changeTargets(getData().getRound()); targetPlate.changeTargets(getData().getRound());
...@@ -347,8 +352,6 @@ public class RunesGame extends AbstractTablexiaGame<RunesGameState> { ...@@ -347,8 +352,6 @@ public class RunesGame extends AbstractTablexiaGame<RunesGameState> {
holderManager.clearHolders(); holderManager.clearHolders();
runesGroup.clearChildren(); runesGroup.clearChildren();
initHolders(); initHolders();
testCountRound++;
triggerScenarioStepEvent(EVENT_NEXT_ROUND+testCountRound);
} }
/** /**
......
...@@ -29,6 +29,7 @@ public interface IRune { ...@@ -29,6 +29,7 @@ public interface IRune {
Color DEFAULT_COLOR_BONUS = new Color(0, 0, 0, 0.2f); Color DEFAULT_COLOR_BONUS = new Color(0, 0, 0, 0.2f);
float CORRECT_ANIMATION_DURATION = 0.5f; float CORRECT_ANIMATION_DURATION = 0.5f;
float WRONG_ANIMATION_DURATION = 0.3f; float WRONG_ANIMATION_DURATION = 0.3f;
String EVENT_ANIMATE_RUNE_DONE = "animation of rune done";
enum AnimationType{ enum AnimationType{
CORRECT(Color.GREEN, CORRECT_ANIMATION_DURATION), CORRECT(Color.GREEN, CORRECT_ANIMATION_DURATION),
......
...@@ -25,6 +25,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.Image; ...@@ -25,6 +25,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.Image;
import cz.nic.tablexia.game.common.media.GfxLibrary; import cz.nic.tablexia.game.common.media.GfxLibrary;
import cz.nic.tablexia.game.games.runes.assets.RuneDefinition; import cz.nic.tablexia.game.games.runes.assets.RuneDefinition;
import cz.nic.tablexia.game.games.runes.helper.RuneDescription; import cz.nic.tablexia.game.games.runes.helper.RuneDescription;
import cz.nic.tablexia.screen.AbstractTablexiaScreen;
/** /**
* Created by Vitaliy Vashchenko on 8.4.16. * Created by Vitaliy Vashchenko on 8.4.16.
...@@ -63,8 +64,13 @@ public class Rune extends Image implements IRune { ...@@ -63,8 +64,13 @@ public class Rune extends Image implements IRune {
@Override @Override
public void showAnimation(AnimationType animationType) { public void showAnimation(AnimationType animationType) {
if (!hasActions()) { if (!hasActions()) {
addAction(Actions.sequence(Actions.color(animationType.getColor(), animationType.getDuration()), Actions.color(defaultColor, animationType.getDuration()))); addAction(Actions.sequence(Actions.color(animationType.getColor(), animationType.getDuration()), Actions.color(DEFAULT_COLOR, animationType.getDuration())));
addAction(Actions.after(Actions.color(defaultColor))); addAction(Actions.after(Actions.sequence(Actions.color(DEFAULT_COLOR), Actions.run(new Runnable() {
@Override
public void run() {
AbstractTablexiaScreen.triggerScenarioStepEvent(EVENT_ANIMATE_RUNE_DONE);
}
}))));
} }
} }
......
...@@ -27,6 +27,7 @@ import cz.nic.tablexia.game.common.TablexiaRandom; ...@@ -27,6 +27,7 @@ import cz.nic.tablexia.game.common.TablexiaRandom;
import cz.nic.tablexia.game.common.media.GfxLibrary; import cz.nic.tablexia.game.common.media.GfxLibrary;
import cz.nic.tablexia.game.games.runes.assets.RuneDefinition; import cz.nic.tablexia.game.games.runes.assets.RuneDefinition;
import cz.nic.tablexia.game.games.runes.helper.RuneDescription; import cz.nic.tablexia.game.games.runes.helper.RuneDescription;
import cz.nic.tablexia.screen.AbstractTablexiaScreen;
/** /**
* Created by Vitaliy Vashchenko on 27.4.16. * Created by Vitaliy Vashchenko on 27.4.16.
...@@ -111,8 +112,13 @@ public class RunesCluster extends Group implements IRune { ...@@ -111,8 +112,13 @@ public class RunesCluster extends Group implements IRune {
private void animateRune(Rune rune, AnimationType animationType) { private void animateRune(Rune rune, AnimationType animationType) {
if (!rune.hasActions()) { if (!rune.hasActions()) {
rune.addAction(Actions.sequence(Actions.color(animationType.getColor()), Actions.color(defaultColor, animationType.getDuration()))); rune.addAction(Actions.sequence(Actions.color(animationType.getColor()), Actions.color(DEFAULT_COLOR, animationType.getDuration())));
rune.addAction(Actions.after(Actions.color(defaultColor))); rune.addAction(Actions.after(Actions.sequence(Actions.color(DEFAULT_COLOR), Actions.run(new Runnable() {
@Override
public void run() {
AbstractTablexiaScreen.triggerScenarioStepEvent(EVENT_ANIMATE_RUNE_DONE);
}
}))));
} }
} }
......
...@@ -111,6 +111,9 @@ public class FormScreen extends AbstractTablexiaScreen<Void> { ...@@ -111,6 +111,9 @@ public class FormScreen extends AbstractTablexiaScreen<Void> {
public static final String SCENARIO_STEP_MUGSHOTS_VISIBLE = "mugshot images visible"; public static final String SCENARIO_STEP_MUGSHOTS_VISIBLE = "mugshot images visible";
public static final String SCENARIO_STEP_IMAGE_CHOSEN = "image chosen"; public static final String SCENARIO_STEP_IMAGE_CHOSEN = "image chosen";
public static final String SCENARIO_STEP_TEXT_FIELD_TIMEOUT = "text field timeout"; public static final String SCENARIO_STEP_TEXT_FIELD_TIMEOUT = "text field timeout";
public static final String PEN_SHAKED = "pen shaked";
public static final String ALTERNATIVE_TEXT_FIELD_SHOWN = "alternative text field shown";
public static final String ALTERNATIVE_NAME_FIELD_HIDDEN = "alternative name field hidden";
public static final String FORM_SIGNATURE_DIALOG = "signature dialog"; public static final String FORM_SIGNATURE_DIALOG = "signature dialog";
...@@ -122,6 +125,8 @@ public class FormScreen extends AbstractTablexiaScreen<Void> { ...@@ -122,6 +125,8 @@ public class FormScreen extends AbstractTablexiaScreen<Void> {
public static final String FORM_SIGNATURE = "formSignature"; public static final String FORM_SIGNATURE = "formSignature";
public static final String FORM_AVATAR_IMAGE = "avatar image"; public static final String FORM_AVATAR_IMAGE = "avatar image";
public static final String FORM_STAMP = "formStamp"; public static final String FORM_STAMP = "formStamp";
public static final String ALTERNATIVE_TEXT_FIELD = "alternative text field";
public static final String YES_ICON = "yes icon";
private static final int PRIVACY_LABEL_WIDTH = 340; private static final int PRIVACY_LABEL_WIDTH = 340;
private static final int PRIVACY_LABEL_HEIGHT = 40; private static final int PRIVACY_LABEL_HEIGHT = 40;
...@@ -360,6 +365,7 @@ public class FormScreen extends AbstractTablexiaScreen<Void> { ...@@ -360,6 +365,7 @@ public class FormScreen extends AbstractTablexiaScreen<Void> {
if(TablexiaSettings.getInstance().getPlatform() != TablexiaSettings.Platform.DESKTOP) { if(TablexiaSettings.getInstance().getPlatform() != TablexiaSettings.Platform.DESKTOP) {
Gdx.input.setOnscreenKeyboardVisible(true); Gdx.input.setOnscreenKeyboardVisible(true);
showAlternativeTextField(); showAlternativeTextField();
triggerScenarioStepEvent(ALTERNATIVE_TEXT_FIELD_SHOWN);
} }
} }
}); });
...@@ -542,6 +548,7 @@ public class FormScreen extends AbstractTablexiaScreen<Void> { ...@@ -542,6 +548,7 @@ public class FormScreen extends AbstractTablexiaScreen<Void> {
alternativeTextField.setPosition(getStage().getWidth()/2 - alternativeTextField.getWidth()/2, 3*getStage().getHeight()/5); alternativeTextField.setPosition(getStage().getWidth()/2 - alternativeTextField.getWidth()/2, 3*getStage().getHeight()/5);
alternativeTextField.setFocusTraversal(false); alternativeTextField.setFocusTraversal(false);
alternativeTextField.setMaxLength(MAX_NAME_LENGTH); alternativeTextField.setMaxLength(MAX_NAME_LENGTH);
alternativeTextField.setName(ALTERNATIVE_TEXT_FIELD);
alternativeTextField.addListener(new InputListener() { alternativeTextField.addListener(new InputListener() {
@Override @Override
public boolean keyTyped(InputEvent event, char character) { public boolean keyTyped(InputEvent event, char character) {
...@@ -570,6 +577,7 @@ public class FormScreen extends AbstractTablexiaScreen<Void> { ...@@ -570,6 +577,7 @@ public class FormScreen extends AbstractTablexiaScreen<Void> {
noIcon.setPosition(alternativeTextField.getX() - PRIVACY_LABEL_OFFSET_X - noIcon.getWidth(), alternativeTextField.getY()); noIcon.setPosition(alternativeTextField.getX() - PRIVACY_LABEL_OFFSET_X - noIcon.getWidth(), alternativeTextField.getY());
yesIcon = new Image(getScreenTextureRegion(FormScreenAssets.YES_ICON)); yesIcon = new Image(getScreenTextureRegion(FormScreenAssets.YES_ICON));
yesIcon.setName(YES_ICON);
yesIcon.addListener(new ClickListener(){ yesIcon.addListener(new ClickListener(){
@Override @Override
public void clicked(InputEvent event, float x, float y) { public void clicked(InputEvent event, float x, float y) {
...@@ -577,6 +585,7 @@ public class FormScreen extends AbstractTablexiaScreen<Void> { ...@@ -577,6 +585,7 @@ public class FormScreen extends AbstractTablexiaScreen<Void> {
hideAlternativeField(); hideAlternativeField();
validate(); validate();
Gdx.input.setOnscreenKeyboardVisible(false); Gdx.input.setOnscreenKeyboardVisible(false);
triggerScenarioStepEvent(ALTERNATIVE_NAME_FIELD_HIDDEN);
} }
}); });
yesIcon.setPosition(alternativeTextField.getX() + alternativeTextField.getWidth() + PRIVACY_LABEL_OFFSET_X, alternativeTextField.getY()); yesIcon.setPosition(alternativeTextField.getX() + alternativeTextField.getWidth() + PRIVACY_LABEL_OFFSET_X, alternativeTextField.getY());
...@@ -669,7 +678,12 @@ public class FormScreen extends AbstractTablexiaScreen<Void> { ...@@ -669,7 +678,12 @@ public class FormScreen extends AbstractTablexiaScreen<Void> {
if (isValid(FormValidationEnum.SIGNATURE) == false) { if (isValid(FormValidationEnum.SIGNATURE) == false) {
displayHintDialog(FormValidationEnum.SIGNATURE, signaturePlace); displayHintDialog(FormValidationEnum.SIGNATURE, signaturePlace);
playValidationSound(FormScreenAssets.VALIDATION_SIGNATURE_SOUND); playValidationSound(FormScreenAssets.VALIDATION_SIGNATURE_SOUND);
pen.addAction(Actions.forever(Actions.sequence(Actions.repeat(SHAKE_ANIMATION_REPEAT_COUNT, Actions.sequence(Actions.moveBy(SHAKE_ANIMATION_OFFSET, 0, SHAKE_ANIMATION_STEP_DURATION), Actions.moveBy(-SHAKE_ANIMATION_OFFSET, 0, SHAKE_ANIMATION_STEP_DURATION))), Actions.delay(1)))); pen.addAction(Actions.forever(Actions.sequence(Actions.repeat(SHAKE_ANIMATION_REPEAT_COUNT, Actions.sequence(Actions.moveBy(SHAKE_ANIMATION_OFFSET, 0, SHAKE_ANIMATION_STEP_DURATION), Actions.moveBy(-SHAKE_ANIMATION_OFFSET, 0, SHAKE_ANIMATION_STEP_DURATION))), Actions.delay(1), Actions.run(new Runnable() {
@Override
public void run() {
triggerScenarioStepEvent(PEN_SHAKED);
}
}))));
return false; return false;
} }
......
# <b>How to run intergation tests</b> # <b>How to run intergation tests</b>
## <b>Run selected test</b> ## <b>Run selected test</b>
Use This option to run only one selected test on one device.
Available tests are in tablexia/itest/listOfAvailableITests.txt.
<b>Desktop version</b> <b>Desktop version</b>
Run selected test (from tablexia/desktop/build/libs): Run selected test (jar file is in tablexia/desktop/build/libs):
``` ```
java -jar Tablexia\ \(feature-gitlab-ci\)-iTest-<VERSION>.jar <TEST_CLASS_NAME> java -jar Tablexia\ \(feature-gitlab-ci\)-iTest-<VERSION>.jar <TEST_CLASS_NAME>
``` ```
...@@ -14,16 +17,16 @@ Log file will be saved into tablexia/desktop/build/libs/iTest_results. ...@@ -14,16 +17,16 @@ Log file will be saved into tablexia/desktop/build/libs/iTest_results.
``` ```
adb shell am start -a android.intent.action.MAIN -n cz.nic.tablexia.itest/cz.nic.tablexia.android.AndroidITestLauncher -e testClassName <TEST_CLASS_NAME> adb shell am start -a android.intent.action.MAIN -n cz.nic.tablexia.itest/cz.nic.tablexia.android.AndroidITestLauncher -e testClassName <TEST_CLASS_NAME>
``` ```
You can run the test from Android Studio using Edit Configurations -> Launch Flags: You can run the test from Android Studio using Edit Configurations -> Launch Flags:
``` ```
-e testClassName <TEST_CLASS_NAME> -e testClassName <TEST_CLASS_NAME>
``` ```
and build variant iTest. and build variant iTest.
Log file will be saved into tablexia/android/build/outputs/apk/iTest_results. Log file will be saved into external memory of connected device in to a folder iTest_results.
<b>iOS version</b> <b>iOS version</b>
For running tests on iOS devices, you need an utility "ideviceinstaller"(http://macappstore.org/ideviceinstaller/) For running tests on iOS devices, you need a utility "ideviceinstaller"(http://macappstore.org/ideviceinstaller/)
Command ```ideviceinstaller -l``` shows installed applications on your connected iOS device. Command ```ideviceinstaller -l``` shows installed applications on your connected iOS device.
For example : For example :
...@@ -37,31 +40,32 @@ For example: ...@@ -37,31 +40,32 @@ For example:
``` ```
idevicedebug run "cz.nic.tablexia.devel" "myParameter" idevicedebug run "cz.nic.tablexia.devel" "myParameter"
``` ```
If there are more than one connected iOS device, you need to specify what device you want to use using parameter: If there are more than one connected iOS devices, you need to specify what device you want to use using parameter:
``` ```
-u "<FORTY_LOCAL_UDID_OF_DEVICE>" -u "<FORTY_LOCAL_UDID_OF_DEVICE>"
``` ```
<br /> <br />
### <b>Run tests using gradle</b> ### <b>Run set of tests using gradle</b>
Put tests, that you want to run in tablexia/itest/iTestBundle.txt (each one to one line)
You can use file listOfAvailableITests.txt to see which tests are available to use or you can use prepared sets in tablexia/itest/testSets.
<b>Desktop version</b> <b>Desktop version</b>
Put tests, that you want to run in tablexia/itest/iTestBundle.txt (each one to one line) Command for run desktop tests:
You can use file listOfAvailableITests.txt to see which tests are able to use.
Run using gradle:
``` ```
./gradlew desktop:runITestBundle ./gradlew desktop:runITestBundle
``` ```
or commit and push changes to gitlab.
Tests will be run one by one as they are written in tablexia/itest/iTestBundle.txt and log files will be saved into tablexia/desktop/build/libs/iTest_results. Tests will be run one by one as they are written in tablexia/itest/iTestBundle.txt and log files will be saved into tablexia/desktop/build/libs/iTest_results.
<b>Android version</b> <b>Android version</b>
For running tests, you must have installed apk (iTest version) in your connected Android device. You can run set of tests on one or more connected devices at the same time.
Put tests, that you want to run in tablexia/itest/iTestBundle.txt (each one to one line) For running tests, you must have set all connected devices to developer mode and have permition to USB debugging.
For running tests one by one on Android device, use script runAndroidITests.sh (from tablexia/itest):
Command for run android tests:
``` ```
./runAndroidITests.sh ./gradlew runAndroidITestBundle
``` ```
Tests will be run one by one as they are written in tablexia/itest/iTestBundle.txt and log files will be saved into tablexia/android/build/outputs/apk/iTest_results. Tests will be run one by one as they are written in tablexia/itest/iTestBundle.txt and log files will be saved into tablexia/android/build/outputs/apk/iTest_results-<DEVICENAME>/iTest_results.
TestGameKidnappingEasyNoneStar NewUserScenario
TestGameKidnappingEasyOneStar TestScenarioSpecial
TestScenarioHallOfFameRobberyTrophies
TestScenarioHeapOfTrophies
TestGameShootingRangeEasyNoneStar
TestGameRobberyMediumOneStar
TestGameInTheDarknessMedium
TestGameNightWatchMediumNoneStar
TestGamePursuitHardThreeStar
TestGameCrimeSceneHardOneStar
TestGameKidnappingEasyTwoStar TestGameKidnappingEasyTwoStar
TestGameKidnappingEasyThreeStar TestGameRunesMediumThreeStar
TestGameKidnappingMediumNoneStar TestGameProtocolEasyOneStar
TestGameKidnappingMediumOneStar TestGameSafeHardNoneStars
TestGameKidnappingMediumTwoStar TestStatisticsInTheDarkness
TestGameKidnappingMediumThreeStar TestEncyclopedia
TestGameKidnappingHardNoneStar TestProfile
TestGameKidnappingHardOneStar OfficeTestScenario
TestGameKidnappingHardTwoStar \ No newline at end of file
TestGameKidnappingHardThreeStar
\ No newline at end of file
NewUserScenario NewUserScenario
TestScenarioSpecial TestScenarioSpecial
TestScenarioHallOfFameRobberyTrophies TestScenarioHallOfFameRobberyTrophies
TestScenarioHallOfFamePursuitTrophies TestScenarioHallOfFamePursuitTrophies
TestScenarioHallOfFameKidnappingTrophies TestScenarioHallOfFameKidnappingTrophies
TestScenarioHallOfFameNightWatchTrophies TestScenarioHallOfFameNightWatchTrophies
TestScenarioHallOfFameShootingRangeTrophies TestScenarioHallOfFameShootingRangeTrophies
TestScenarioHallOfFameInTheDarknessTrophies TestScenarioHallOfFameInTheDarknessTrophies
TestScenarioHallOfFameCrimeSceneTrophies TestScenarioHallOfFameCrimeSceneTrophies
TestScenarioHallOfFameRunesTrophies TestScenarioHallOfFameRunesTrophies
TestScenarioHeapOfTrophies TestScenarioHallOfFameProtocolTrophies
TestGameShootingRangeEasyNoneStar TestScenarioHallOfFameSafeTrophies
TestGameShootingRangeEasyOneStar TestScenarioHeapOfTrophies
TestGameShootingRangeEasyTwoStar TestGameShootingRangeEasyNoneStar
TestGameShootingRangeEasyThreeStar TestGameShootingRangeEasyOneStar
TestGameShootingRangeMediumNoneStar TestGameShootingRangeEasyTwoStar
TestGameShootingRangeMediumOneStar TestGameShootingRangeEasyThreeStar
TestGameShootingRangeMediumTwoStar TestGameShootingRangeMediumNoneStar
TestGameShootingRangeMediumThreeStar TestGameShootingRangeMediumOneStar
TestGameShootingRangeHardNoneStar TestGameShootingRangeMediumTwoStar
TestGameShootingRangeHardOneStar