diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 0601958f2e8bbfa87f66d5a0b5123251df12f921..a906e2d705b430553529e04790ffc051301348c2 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -16,6 +16,7 @@ build:
stage: build
script:
- ./gradlew build
+ - ./gradlew assembleAndroidTest
artifacts:
paths:
- app/build/outputs/apk
diff --git a/app/build.gradle b/app/build.gradle
index fb5da052f89f9f4c4c5475d168e78096f7450936..82218632e31864100c75fe9cb0975d7d71d1db0e 100755
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -19,8 +19,8 @@ android {
targetSdkVersion Versions.target_sdk
versionCode versionMajor * 10000 + versionMinor * 1000 + versionPatch * 100
versionName "${versionMajor}.${versionMinor}.${versionPatch}"
- testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
-
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ testBuildType System.getProperty('testBuildType', 'release')
renderscriptTargetApi 28
renderscriptSupportModeEnabled true
}
@@ -33,7 +33,6 @@ android {
applicationIdSuffix '.debug'
signingConfig signingConfigs.debug
}
-
applicationVariants.all { variant ->
if (variant.buildType.name == "debug") {
variant.outputs.all { output ->
@@ -44,6 +43,7 @@ android {
}
}
+
signingConfigs {
debug {
storeFile file(getRootDir().path + "/keystore/debug.keystore")
@@ -150,6 +150,8 @@ dependencies {
androidTestImplementation Libs.AndroidX.Test.runner
androidTestImplementation Libs.AndroidX.Test.rules
implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0'
+ androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.2.0'
+
}
apply plugin: 'com.getkeepsafe.dexcount'
diff --git a/app/src/androidTest/java/foundation/e/blisslauncher/BlissLauncherTestSuite.java b/app/src/androidTest/java/foundation/e/blisslauncher/BlissLauncherTestSuite.java
new file mode 100644
index 0000000000000000000000000000000000000000..4abe0f2c6397fa5fd0482a6b47eb0d1ced2de3e1
--- /dev/null
+++ b/app/src/androidTest/java/foundation/e/blisslauncher/BlissLauncherTestSuite.java
@@ -0,0 +1,21 @@
+package foundation.e.blisslauncher;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+
+import foundation.e.blisslauncher.features.launcher.LauncherActivityUiTest;
+
+@RunWith(Suite.class)
+/* Here list all you tests classes that are part of the suite
+ * eg:
+ * mainActivityTest.class,
+ * secondActivityTest.class,
+ * serviceTest.class
+ */
+@Suite.SuiteClasses(
+ LauncherActivityUiTest.class
+)
+public class BlissLauncherTestSuite{
+
+}
diff --git a/app/src/androidTest/java/foundation/e/blisslauncher/ExampleInstrumentedTest.java b/app/src/androidTest/java/foundation/e/blisslauncher/ExampleInstrumentedTest.java
deleted file mode 100755
index f0223b542855e3e0a8796aa661923aa7d72ac19b..0000000000000000000000000000000000000000
--- a/app/src/androidTest/java/foundation/e/blisslauncher/ExampleInstrumentedTest.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2018 /e/.
- *
- * 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 foundation.e.blisslauncher;
-
-import static org.junit.Assert.*;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import android.content.Context;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
-
-/**
- * Instrumentation test, which will execute on an Android device.
- *
- * @see Testing documentation
- */
-@RunWith(AndroidJUnit4.class)
-public class ExampleInstrumentedTest {
- @Test
- public void useAppContext() {
- // Context of the app under test.
- Context appContext = InstrumentationRegistry.getTargetContext();
-
- assertEquals("org.indin.blisslaunchero", appContext.getPackageName());
- }
-}
diff --git a/app/src/androidTest/java/foundation/e/blisslauncher/features/launcher/LauncherActivityUiTest.java b/app/src/androidTest/java/foundation/e/blisslauncher/features/launcher/LauncherActivityUiTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..a0985bf07cfda699a8b412b7b4a802ce087cf8d0
--- /dev/null
+++ b/app/src/androidTest/java/foundation/e/blisslauncher/features/launcher/LauncherActivityUiTest.java
@@ -0,0 +1,153 @@
+package foundation.e.blisslauncher.features.launcher;
+
+
+import android.view.View;
+
+import androidx.test.espresso.ViewInteraction;
+import androidx.test.espresso.action.ViewActions;
+import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner;
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.rule.ActivityTestRule;
+import androidx.test.uiautomator.UiDevice;
+
+import org.hamcrest.Matcher;
+import org.hamcrest.core.IsInstanceOf;
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import java.io.IOException;
+import foundation.e.blisslauncher.R;
+
+import static androidx.test.espresso.Espresso.closeSoftKeyboard;
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.assertion.ViewAssertions.*;
+import static androidx.test.espresso.matcher.ViewMatchers.*;
+import static androidx.test.espresso.matcher.ViewMatchers.hasChildCount;
+import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static androidx.test.espresso.matcher.ViewMatchers.withHint;
+import static androidx.test.espresso.matcher.ViewMatchers.withId;
+import static androidx.test.espresso.matcher.ViewMatchers.withParent;
+import static androidx.test.espresso.matcher.ViewMatchers.withText;
+import static org.hamcrest.CoreMatchers.allOf;
+import static org.hamcrest.CoreMatchers.not;
+
+
+//instrument --package foundation.e.blisslauncher.features.launcher --class LauncherActivityUiTest --runner
+
+
+@RunWith(AndroidJUnit4ClassRunner.class)
+public class LauncherActivityUiTest {
+
+ private UiDevice device;
+ @Rule
+ public ActivityTestRule mLauncherActivityTestRule =
+ new ActivityTestRule(LauncherActivity.class);
+
+
+
+ @Test
+ public void displayLeftPanelTest() throws Exception{
+ //Swipe on the main view to display the left panel
+ onView(withId(R.id.appGrid)).perform(ViewActions.swipeRight());
+
+ //Check every element that should be here are here: Search bar, app suggestion, edit widget buttons and weather widget
+
+ //Check app suggestion is displayed
+ onView(allOf(withId(R.id.suggestedAppGrid), hasChildCount(4))).check(matches(isDisplayed()));
+
+ //check edit widget button is displayed
+ onView(withId(R.id.edit_widgets_button)).check(matches(isDisplayed()));
+
+ //check that search_input is displayed
+ //Note: it was a pain to find the "not(withParent(withParent(withParent(withId(swipe_search_container))))"
+ //because it told that was more than one match with other trials, but in the "run" window , there was only one
+ //I had to add breakpoint and analyse Object "editText" to find the other one then to find for difference between both...
+ final Matcher searchInputMatcher = allOf(withId(R.id.search_input), not( withParent( withParent( withParent( withId(R.id.swipe_search_container ) ) ) ) ) );
+ ViewInteraction editText = onView(searchInputMatcher);
+
+ editText.check(matches(withHint("Search")))
+ .check(matches( isDisplayed() ) );
+
+ //check that weather widget is displayed
+ onView(withId(R.id.weather_info_layout)).check(matches(isDisplayed()));
+ }
+
+ /**
+ * This test requires Calendar App to be installed on the device
+ * @throws Exception
+ */
+ @Test
+ public void searchCalendarAppTest() throws Exception{
+ final String Calendar_app_name = "Calendar";
+
+ device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+
+ //Swipe on the main view to display the left panel
+ onView(withId(R.id.appGrid)).perform(ViewActions.swipeRight());
+ final Matcher notChildOfSwipeSearchContainer = not( withParent( withParent( withParent( withId(R.id.swipe_search_container ) ) ) ) );
+ final Matcher searchInputMatcher = allOf(withId(R.id.search_input), notChildOfSwipeSearchContainer );
+
+
+ //Check there is 4 app suggested
+ final ViewInteraction appGrid = onView(allOf(withId(R.id.suggestedAppGrid), withParent(withParent(withId(R.id.used_apps_layout) ) ), isDisplayed() ) );
+ appGrid.check(matches(hasChildCount(4)));
+
+
+
+ //Click on "search input bar"
+ final ViewInteraction editText = onView(searchInputMatcher);
+ editText.perform(ViewActions.click());
+
+ final String checkKeyboardCmd = "dumpsys input_method | grep mInputShown";
+
+ //check soft keyboard displayed
+ boolean softKeyboardShown = false;
+ try {
+ softKeyboardShown = device.executeShellCommand(checkKeyboardCmd).contains("mInputShown=true");
+ } catch ( IOException e) {
+ System.out.println(e.toString());
+ throw new RuntimeException("Keyboard check failed", e);
+ }
+
+ Assert.assertTrue(softKeyboardShown);
+
+ //Type "Calendar" into the textBox
+ editText.perform(ViewActions.typeText(Calendar_app_name));
+
+ //Check the value is set in input
+ editText.check(matches(withText(Calendar_app_name)));
+
+
+
+ //check the clear button is present
+ onView(allOf(withId(R.id.clearSuggestionImageView), notChildOfSwipeSearchContainer) )
+ .check(matches( not(withEffectiveVisibility(Visibility.GONE))));
+
+
+ //close soft keyboard
+ closeSoftKeyboard();
+
+ Thread.sleep(5000); //required to wait for update of UI
+
+
+
+ //Check that there is only one app show in grid
+ final ViewInteraction appGrid2 = onView(allOf(withId(R.id.suggestedAppGrid), withParent(withParent(withId(R.id.used_apps_layout) ) ), isDisplayed() ) );
+ appGrid2.check(matches(hasChildCount(1))); //DOESN't WORK
+
+
+ // Check that Calendar icon is clickable
+ final ViewInteraction appLabel = onView(
+ allOf(
+ withId( R.id.app_label),
+ withText(Calendar_app_name),
+ withParent(
+ withParent(IsInstanceOf.instanceOf(android.widget.FrameLayout.class) )
+ ), isDisplayed()
+ ) ) ;
+
+ appLabel.check(matches(withParent(withChild(allOf(withId(R.id.app_icon), isClickable())))));
+ }
+
+}