Browse Source

Fastlane integration

(cherry picked from commit ab41d9367d)
3.3.x
Nicolas Pomepuy 6 years ago
parent
commit
866259c18f
  1. 1
      .gitignore
  2. 42
      application/app/build.gradle
  3. 30
      application/app/src/androidTest/AndroidManifest.xml
  4. 24
      application/app/src/androidTest/java/org/videolan/mobile/app/ExampleInstrumentedTest.kt
  5. 2
      application/app/src/androidTest/java/org/videolan/vlc/BaseUITest.kt
  6. 67
      application/app/src/androidTest/java/org/videolan/vlc/DemoModeEnabler.kt
  7. 44
      application/app/src/androidTest/java/org/videolan/vlc/DemoModeRule.kt
  8. 0
      application/app/src/androidTest/java/org/videolan/vlc/MultidexTestRunner.kt
  9. 158
      application/app/src/androidTest/java/org/videolan/vlc/PhoneScreenhotsInstrumentedTest.kt
  10. 1
      application/app/src/androidTest/java/org/videolan/vlc/PreferenceMatcher.kt
  11. 156
      application/app/src/androidTest/java/org/videolan/vlc/TvScreenhotsInstrumentedTest.kt
  12. 2
      application/app/src/androidTest/java/org/videolan/vlc/UtilAdapterMatcher.kt
  13. 16
      application/app/src/androidTest/java/org/videolan/vlc/UtilViewActions.kt
  14. 28
      application/app/src/androidTest/java/org/videolan/vlc/UtilViewMatchers.kt
  15. 2
      application/app/src/androidTest/java/org/videolan/vlc/database/BrowserFavDaoTest.kt
  16. 0
      application/app/src/androidTest/java/org/videolan/vlc/database/CustomDirectoryDaoTest.kt
  17. 0
      application/app/src/androidTest/java/org/videolan/vlc/database/DbTest.kt
  18. 0
      application/app/src/androidTest/java/org/videolan/vlc/database/ExternalSubDaoTest.kt
  19. 26
      application/app/src/androidTest/java/org/videolan/vlc/database/MigrationTest.kt
  20. 0
      application/app/src/androidTest/java/org/videolan/vlc/database/SlaveDaoTest.kt
  21. 0
      application/app/src/androidTest/java/org/videolan/vlc/database/helpers/SqliteDatabaseTestHelper.kt
  22. 0
      application/app/src/androidTest/java/org/videolan/vlc/database/helpers/SqliteTestDbOpenHelper.kt
  23. 0
      application/app/src/androidTest/java/org/videolan/vlc/gui/PlaylistActivityUITest.kt
  24. 8
      application/app/src/androidTest/java/org/videolan/vlc/gui/PlaylistFragmentUITest.kt
  25. 0
      application/app/src/androidTest/java/org/videolan/vlc/gui/browser/FileBrowserFragmentUITest.kt
  26. 61
      application/app/src/androidTest/java/org/videolan/vlc/gui/browser/FilePickerFragmentUITest.kt
  27. 0
      application/app/src/androidTest/java/org/videolan/vlc/gui/browser/StorageBrowserFragmentUITest.kt
  28. 2
      application/app/src/androidTest/java/org/videolan/vlc/gui/preferences/BasePreferenceUITest.kt
  29. 0
      application/app/src/androidTest/java/org/videolan/vlc/gui/preferences/PreferencesAudioUITest.kt
  30. 0
      application/app/src/androidTest/java/org/videolan/vlc/gui/preferences/PreferencesCastingUITest.kt
  31. 0
      application/app/src/androidTest/java/org/videolan/vlc/gui/preferences/PreferencesFragmentUITest.kt
  32. 0
      application/app/src/androidTest/java/org/videolan/vlc/gui/preferences/PreferencesSubtitlesUITest.kt
  33. 0
      application/app/src/androidTest/java/org/videolan/vlc/gui/preferences/PreferencesUIUITest.kt
  34. 0
      application/app/src/androidTest/java/org/videolan/vlc/gui/preferences/PreferencesVideoUITest.kt
  35. 53
      application/app/src/androidTest/java/org/videolan/vlc/util/DpadHelper.kt
  36. 0
      application/app/src/androidTest/java/org/videolan/vlc/util/KExtensions.kt
  37. 16
      application/app/src/androidTest/java/org/videolan/vlc/util/LiveDataTestUtil.kt
  38. 0
      application/app/src/androidTest/java/org/videolan/vlc/util/MockitoExt.kt
  39. 36
      application/app/src/androidTest/java/org/videolan/vlc/util/ScreenshotUtil.kt
  40. 0
      application/app/src/androidTest/java/org/videolan/vlc/util/TestCoroutineContextProvider.kt
  41. 0
      application/app/src/androidTest/java/org/videolan/vlc/util/TestUtil.kt
  42. 150
      application/app/src/androidTest/java/org/videolan/vlc/util/UiUtils.kt
  43. 2
      application/resources/build.gradle
  44. 2
      application/television/build.gradle
  45. 2
      application/vlc-android/AndroidManifest.xml
  46. 42
      application/vlc-android/androidTest/org/videolan/vlc/gui/browser/FilePickerFragmentUITest.kt
  47. 10
      application/vlc-android/build.gradle
  48. 23
      application/vlc-android/res/layout/toolbar.xml
  49. 10
      application/vlc-android/src/debug/AndroidManifest.xml
  50. 6
      application/vlc-android/src/org/videolan/vlc/gui/MainActivity.kt
  51. 2
      application/vlc-android/src/org/videolan/vlc/gui/browser/BaseBrowserAdapter.kt
  52. 6
      application/vlc-android/test/org/videolan/vlc/viewmodels/HistoryModelTest.kt
  53. 4
      application/vlc-android/test/org/videolan/vlc/viewmodels/browser/FilePickerModelTest.kt
  54. 10
      build.gradle
  55. 10
      buildsystem/automation/Gemfile
  56. 87
      buildsystem/automation/README.md
  57. 1
      buildsystem/automation/certificates
  58. 2
      buildsystem/automation/fastlane/Appfile
  59. 84
      buildsystem/automation/fastlane/Fastfile
  60. 5
      buildsystem/automation/fastlane/Pluginfile
  61. 15
      buildsystem/automation/fastlane/Screengrabfile
  62. 36
      extension-api/src/androidTest/java/org/videolan/vlc/plugin/api/ApplicationTest.java
  63. 2
      gradle.properties

1
.gitignore

@ -68,3 +68,4 @@ libvlc.pc
libvlc.pc.backup
libvlcpp.pc
lib/
/buildsystem/automation/certificates/

42
application/app/build.gradle

@ -2,8 +2,21 @@ apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
android {
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = JavaVersion.VERSION_1_8.toString()
}
packagingOptions {
exclude 'META-INF/main.kotlin_module'
exclude 'META-INF/donations_debug.kotlin_module'
exclude 'META-INF/mediadb_debug.kotlin_module'
exclude 'META-INF/resources_debug.kotlin_module'
exclude 'META-INF/television_debug.kotlin_module'
pickFirst 'lib/armeabi-v7a/libc++_shared.so'
pickFirst 'lib/armeabi/libc++_shared.so'
pickFirst 'lib/arm64-v8a/libc++_shared.so'
@ -40,7 +53,11 @@ android {
vectorDrawables.useSupportLibrary = true
multiDexEnabled true
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
testInstrumentationRunner "org.videolan.vlc.MultidexTestRunner"
// The following argument makes the Android Test Orchestrator run its
// "pm clear" command after each test invocation. This command ensures
// that the app's state is completely cleared between tests.
testInstrumentationRunnerArguments clearPackageData: 'true'
}
signingConfigs {
@ -135,4 +152,27 @@ android {
dependencies {
implementation project(':application:vlc-android')
implementation project(':application:television')
testImplementation project(':application:television')
androidTestApi "androidx.test.espresso:espresso-contrib:$rootProject.espressoVersion"
androidTestApi "androidx.test.espresso:espresso-core:$rootProject.espressoVersion"
androidTestApi "androidx.test.espresso:espresso-intents:$rootProject.espressoVersion"
testApi "junit:junit:$rootProject.ext.junitVersion"
androidTestApi "androidx.room:room-testing:$rootProject.ext.roomVersion"
testApi "androidx.arch.core:core-testing:$rootProject.ext.archVersion"
androidTestApi "androidx.arch.core:core-testing:$rootProject.ext.archVersion"
androidTestApi "androidx.test.ext:junit:$rootProject.ext.supportTest"
androidTestUtil "androidx.test:orchestrator:$rootProject.ext.orchestrator"
testApi "androidx.test:core:$rootProject.ext.testCore"
testApi "org.jetbrains.kotlinx:kotlinx-coroutines-test:$rootProject.ext.kotlinx_version"
testApi "org.mockito:mockito-core:$rootProject.ext.mockito"
testApi "io.mockk:mockk:$rootProject.ext.mockk"
testApi "org.powermock:powermock-api-mockito2:$rootProject.ext.powerMock"
testApi "org.powermock:powermock-module-junit4:$rootProject.ext.powerMock"
testApi "com.jraska.livedata:testing-ktx:$rootProject.ext.livedataTest"
testApi "org.robolectric:robolectric:$rootProject.ext.robolectric"
androidTestApi "com.android.support:multidex:1.0.3"
androidTestImplementation "androidx.test.uiautomator:uiautomator:2.2.0"
androidTestApi 'androidx.test:rules:1.3.0'
androidTestImplementation 'tools.fastlane:screengrab:2.0.0'
}

30
application/app/src/androidTest/AndroidManifest.xml

@ -0,0 +1,30 @@
<!--
~ *************************************************************************
~ AndroidManifest.xml
~ **************************************************************************
~ Copyright © 2020 VLC authors and VideoLAN
~ Author: Nicolas POMEPUY
~ This program is free software; you can redistribute it and/or modify
~ it under the terms of the GNU General Public License as published by
~ the Free Software Foundation; either version 2 of the License, or
~ (at your option) any later version.
~
~ This program is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
~ GNU General Public License for more details.
~
~ You should have received a copy of the GNU General Public License
~ along with this program; if not, write to the Free Software
~ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
~ ***************************************************************************
~
~
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="org.videolan.mobile.app">
<uses-sdk tools:overrideLibrary="android_libs.ub_uiautomator, tools.fastlane.screengrab" />
</manifest>

24
application/app/src/androidTest/java/org/videolan/mobile/app/ExampleInstrumentedTest.kt

@ -1,24 +0,0 @@
package org.videolan.mobile.app
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Assert.*
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("org.videolan.mobile.app", appContext.packageName)
}
}

2
application/vlc-android/androidTest/org/videolan/vlc/BaseUITest.kt → application/app/src/androidTest/java/org/videolan/vlc/BaseUITest.kt

@ -10,7 +10,6 @@ import org.junit.runner.RunWith
import org.videolan.resources.util.startMedialibrary
import org.videolan.vlc.util.TestCoroutineContextProvider
@RunWith(AndroidJUnit4::class)
abstract class BaseUITest {
@Rule
@ -18,7 +17,6 @@ abstract class BaseUITest {
val storagePermissionGrant = GrantPermissionRule.grant(
"android.permission.READ_EXTERNAL_STORAGE")
val context: Context = ApplicationProvider.getApplicationContext()
@Before

67
application/app/src/androidTest/java/org/videolan/vlc/DemoModeEnabler.kt

@ -0,0 +1,67 @@
/*
* ************************************************************************
* DemoModeEnabler.kt
* *************************************************************************
* Copyright © 2020 VLC authors and VideoLAN
* Author: Nicolas POMEPUY
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
* **************************************************************************
*
*
*/
package org.videolan.vlc
import android.os.ParcelFileDescriptor
import androidx.test.platform.app.InstrumentationRegistry
import java.io.BufferedReader
import java.io.InputStreamReader
class DemoModeEnabler {
fun enable() {
executeShellCommand("settings put global sysui_demo_allowed 1")
sendCommand("exit")
sendCommand("enter")
sendCommand("notifications", "visible" to "false")
sendCommand("network", "wifi" to "show", "level" to "4", "fully" to "true")
sendCommand("network", "mobile" to "show", "level" to "4", "datatype" to "4g")
sendCommand("battery", "level" to "100", "plugged" to "true")
sendCommand("clock", "hhmm" to "1000")
}
fun disable() {
sendCommand("exit")
}
private fun sendCommand(command: String, vararg extras: Pair<String, Any>) {
val exec = StringBuilder("am broadcast -a com.android.systemui.demo -e command $command")
for ((key, value) in extras) {
exec.append(" -e $key $value")
}
executeShellCommand(exec.toString())
}
private fun executeShellCommand(command: String) {
waitForCompletion(InstrumentationRegistry.getInstrumentation().uiAutomation.executeShellCommand(command))
}
private fun waitForCompletion(descriptor: ParcelFileDescriptor) {
val reader = BufferedReader(InputStreamReader(ParcelFileDescriptor.AutoCloseInputStream(descriptor)))
reader.use {
it.readText()
}
}
}

44
application/app/src/androidTest/java/org/videolan/vlc/DemoModeRule.kt

@ -0,0 +1,44 @@
/*
* ************************************************************************
* DemoModeRule.kt
* *************************************************************************
* Copyright © 2020 VLC authors and VideoLAN
* Author: Nicolas POMEPUY
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
* **************************************************************************
*
*
*/
package org.videolan.vlc
import org.junit.rules.TestRule
import org.junit.runner.Description
import org.junit.runners.model.Statement
class DemoModeRule : TestRule {
private val helper = DemoModeEnabler()
override fun apply(base: Statement, description: Description): Statement = DemoModeStatement(base)
private inner class DemoModeStatement(private val base: Statement) : Statement() {
override fun evaluate() {
helper.enable()
base.evaluate()
helper.disable()
}
}
}

0
application/vlc-android/androidTest/org/videolan/vlc/MultidexTestRunner.kt → application/app/src/androidTest/java/org/videolan/vlc/MultidexTestRunner.kt

158
application/app/src/androidTest/java/org/videolan/vlc/PhoneScreenhotsInstrumentedTest.kt

@ -0,0 +1,158 @@
/*
* ************************************************************************
* PhoneScreenhotsInstrumentedTest.kt
* *************************************************************************
* Copyright © 2020 VLC authors and VideoLAN
* Author: Nicolas POMEPUY
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
* **************************************************************************
*
*
*/
package org.videolan.vlc
import android.content.Intent
import android.os.SystemClock
import android.util.Log
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.Espresso.pressBack
import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.matcher.ViewMatchers.isRoot
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.rule.ActivityTestRule
import androidx.test.uiautomator.UiDevice
import kotlinx.coroutines.ObsoleteCoroutinesApi
import org.junit.ClassRule
import org.junit.Rule
import org.junit.Test
import org.videolan.resources.EXTRA_TARGET
import org.videolan.tools.Settings
import org.videolan.vlc.gui.MainActivity
import org.videolan.vlc.util.DpadHelper.pressHome
import org.videolan.vlc.util.DpadHelper.pressPip
import org.videolan.vlc.util.DpadHelper.pressStop
import org.videolan.vlc.util.ScreenshotUtil
import org.videolan.vlc.util.UiUtils.waitId
import org.videolan.vlc.util.UiUtils.waitUntilLoaded
import tools.fastlane.screengrab.Screengrab
import tools.fastlane.screengrab.UiAutomatorScreenshotStrategy
import tools.fastlane.screengrab.locale.LocaleTestRule
//@RunWith(AndroidJUnit4::class)
class PhoneScreenhotsInstrumentedTest : BaseUITest() {
@Rule
@JvmField
val activityTestRule = ActivityTestRule(MainActivity::class.java, true, false)
@Rule
@JvmField
val demoModeRule = DemoModeRule()
lateinit var activity: MainActivity
@ObsoleteCoroutinesApi
@Test
fun testTakeScreenshot() {
onView(isRoot()).perform(waitId(R.id.audio_list, 5000))
//Audio
// ScreenshotUtil.takeScreenshot("01_trash")
onView(withId(R.id.sliding_tabs)).perform(TabsMatcher(0))
waitUntilLoaded { activity.findViewById(R.id.audio_list) }
SystemClock.sleep(300)
ScreenshotUtil.takeScreenshot(3, "audio_list")
onView(withId(R.id.sliding_tabs)).perform(TabsMatcher(2))
waitUntilLoaded { activity.findViewById(R.id.audio_list) }
onView(withId(R.id.ml_menu_last_playlist)).perform(click())
onView(isRoot()).perform(waitId(R.id.header, 5000))
// ScreenshotUtil.takeScreenshot(7,"audio_player_collapsed")
onView(withId(R.id.header)).perform(click())
SystemClock.sleep(300)
ScreenshotUtil.takeScreenshot(6,"audio_player_playlist")
onView(withId(R.id.playlist_switch)).perform(click())
ScreenshotUtil.takeScreenshot(5,"audio_player")
onView(withId(R.id.playlist_switch)).perform(click())
//close audio player
onView(withId(R.id.header)).perform(click())
pressStop()
}
@ObsoleteCoroutinesApi
@Test
fun testTakeScreenshotVideo() {
onView(withId(R.id.nav_video))
.perform(click())
Log.d("Espresso", "0")
waitUntilLoaded { activity.findViewById(R.id.video_grid) }
Log.d("Espresso", "1")
ScreenshotUtil.takeScreenshot(1, "video_list")
val rvMatcher = withRecyclerView(R.id.video_grid)
Log.d("Espresso", "2")
onView(rvMatcher.atPosition(3)).perform(click())
Log.d("Espresso", "3")
rotateLandscape()
onView(isRoot()).perform(orientationLandscape())
onView(isRoot()).perform(waitId(R.id.player_root, 5000))
SystemClock.sleep(1500)
onView(withId(R.id.player_root)).perform(click())
SystemClock.sleep(500)
ScreenshotUtil.takeScreenshot(2, "video_player")
onView(withId(R.id.player_overlay_adv_function)).perform(ForceClickAction())
SystemClock.sleep(500)
ScreenshotUtil.takeScreenshot(7,"video_player_advanced_options")
disableRotateLandscape()
SystemClock.sleep(500)
onView(withRecyclerView(R.id.options_list).atPositionOnView(4, R.id.option_title)).perform(click())
// ScreenshotUtil.takeScreenshot(9,"video_player_equalizer")
pressBack()
pressPip()
pressHome()
pressPip()
ScreenshotUtil.takeScreenshot(8,"pip")
}
@ObsoleteCoroutinesApi
@Test
fun testTakeScreenshotBrowser() {
onView(withId(R.id.nav_directories))
.perform(click())
ScreenshotUtil.takeScreenshot(4,"browser")
}
private fun rotateLandscape() = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()).setOrientationLeft()
private fun disableRotateLandscape() = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()).setOrientationNatural()
companion object {
@ClassRule
@JvmField
val localeTestRule = LocaleTestRule()
}
override fun beforeTest() {
Screengrab.setDefaultScreenshotStrategy(UiAutomatorScreenshotStrategy())
Settings.getInstance(context).edit().putBoolean("auto_rescan", false).putBoolean("audio_resume_card", false).commit()
val intent = Intent().apply {
putExtra(EXTRA_TARGET, R.id.nav_audio)
}
activityTestRule.launchActivity(intent)
activity = activityTestRule.activity
}
}

1
application/vlc-android/androidTest/org/videolan/vlc/PreferenceMatcher.kt → application/app/src/androidTest/java/org/videolan/vlc/PreferenceMatcher.kt

@ -107,7 +107,6 @@ object PreferenceMatchers {
} catch (ignored: Resources.NotFoundException) {
/* view could be from a context unaware of the resource id. */
}
}
return if (null != expectedText && preference.title != null) {
expectedText == preference.title.toString()

156
application/app/src/androidTest/java/org/videolan/vlc/TvScreenhotsInstrumentedTest.kt

@ -0,0 +1,156 @@
/*
* ************************************************************************
* TvScreenhotsInstrumentedTest.kt
* *************************************************************************
* Copyright © 2020 VLC authors and VideoLAN
* Author: Nicolas POMEPUY
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
* **************************************************************************
*
*
*/
package org.videolan.vlc
import android.app.Activity
import android.content.Intent
import android.os.SystemClock
import androidx.test.espresso.Espresso
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.matcher.ViewMatchers.*
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.rule.ActivityTestRule
import androidx.test.runner.lifecycle.ActivityLifecycleMonitorRegistry
import androidx.test.runner.lifecycle.Stage
import androidx.test.uiautomator.Direction
import kotlinx.coroutines.ObsoleteCoroutinesApi
import org.hamcrest.Matchers.allOf
import org.junit.ClassRule
import org.junit.Rule
import org.junit.Test
import org.videolan.resources.EXTRA_TARGET
import org.videolan.television.ui.MainTvActivity
import org.videolan.television.ui.audioplayer.AudioPlayerActivity
import org.videolan.television.ui.browser.VerticalGridActivity
import org.videolan.tools.Settings
import org.videolan.vlc.util.DpadHelper.pressBack
import org.videolan.vlc.util.DpadHelper.pressDPad
import org.videolan.vlc.util.DpadHelper.pressDPadCenter
import org.videolan.vlc.util.DpadHelper.pressHome
import org.videolan.vlc.util.DpadHelper.pressPip
import org.videolan.vlc.util.ScreenshotUtil
import org.videolan.vlc.util.UiUtils
import org.videolan.vlc.util.UiUtils.waitForActivity
import org.videolan.vlc.util.UiUtils.waitId
import tools.fastlane.screengrab.Screengrab
import tools.fastlane.screengrab.UiAutomatorScreenshotStrategy
import tools.fastlane.screengrab.locale.LocaleTestRule
//@RunWith(AndroidJUnit4::class)
class TvScreenhotsInstrumentedTest : BaseUITest() {
@Rule
@JvmField
val activityTestRule = ActivityTestRule(MainTvActivity::class.java, true, false)
@Rule
@JvmField
val demoModeRule = DemoModeRule()
lateinit var activity: MainTvActivity
companion object {
@ClassRule
@JvmField
val localeTestRule = LocaleTestRule()
}
override fun beforeTest() {
Screengrab.setDefaultScreenshotStrategy(UiAutomatorScreenshotStrategy())
Settings.getInstance(context).edit().putBoolean("auto_rescan", false).putBoolean("audio_resume_card", false).commit()
val intent = Intent().apply {
putExtra(EXTRA_TARGET, R.id.nav_audio)
}
activityTestRule.launchActivity(intent)
activity = activityTestRule.activity
}
fun getCurrentActivity(): Activity? {
var currentActivity: Activity? = null
InstrumentationRegistry.getInstrumentation().runOnMainSync { run { currentActivity = ActivityLifecycleMonitorRegistry.getInstance().getActivitiesInStage(Stage.RESUMED).elementAtOrNull(0) } }
return currentActivity
}
@ObsoleteCoroutinesApi
@Test
fun testTakeScreenshot() {
SystemClock.sleep(1500)
//Audio
ScreenshotUtil.takeScreenshot(1, "tv_home")
onView(allOf(withId(R.id.row_header), withText(activity.getString(R.string.audio)), withEffectiveVisibility(Visibility.VISIBLE))).perform(click())
pressDPad(Direction.RIGHT, 4)
pressDPadCenter()
waitForActivity(VerticalGridActivity::class.java)
waitId(org.videolan.television.R.id.list, 5000)
getCurrentActivity()?.let { activity ->
UiUtils.waitUntilLoaded { activity.findViewById(org.videolan.television.R.id.list) }
} ?: throw IllegalStateException("Cannot find activity")
ScreenshotUtil.takeScreenshot(4,"tv_audio_list")
pressDPad(Direction.DOWN, 4)
pressDPadCenter()
waitForActivity(AudioPlayerActivity::class.java)
waitId(org.videolan.television.R.id.album_cover, 5000)
ScreenshotUtil.takeScreenshot(6,"tv_audio_player")
pressBack()
pressBack()
pressDPad(Direction.DOWN, 2)
pressDPadCenter()
waitForActivity(VerticalGridActivity::class.java)
waitId(org.videolan.television.R.id.list, 5000)
getCurrentActivity()?.let { activity ->
UiUtils.waitUntilLoaded { activity.findViewById(org.videolan.television.R.id.list) }
}
ScreenshotUtil.takeScreenshot(5,"tv_files")
pressBack()
pressDPad(Direction.LEFT)
onView(allOf(withId(R.id.row_header), withText(activity.getString(R.string.video)), withEffectiveVisibility(Visibility.VISIBLE))).perform(click())
pressDPadCenter()
pressDPadCenter()
waitForActivity(VerticalGridActivity::class.java)
waitId(org.videolan.television.R.id.list, 5000)
getCurrentActivity()?.let { activity ->
UiUtils.waitUntilLoaded { activity.findViewById(org.videolan.television.R.id.list) }
}
ScreenshotUtil.takeScreenshot(2,"tv_video_list")
pressDPad(Direction.DOWN, 3)
pressDPadCenter()
SystemClock.sleep(1500)
pressDPad(Direction.DOWN)
SystemClock.sleep(600)
ScreenshotUtil.takeScreenshot(3,"tv_video_player")
Espresso.pressBack()
pressPip()
pressHome()
pressPip()
SystemClock.sleep(1500)
ScreenshotUtil.takeScreenshot(7,"tv_pip")
}
}

2
application/vlc-android/androidTest/org/videolan/vlc/UtilAdapterMatcher.kt → application/app/src/androidTest/java/org/videolan/vlc/UtilAdapterMatcher.kt

@ -85,7 +85,7 @@ fun findFirstPreferencePosition(@IdRes recyclerViewId: Int, vararg matchers: Mat
return -1 to count
}
fun onPreferenceRow(@IdRes recyclerViewId: Int, vararg matchers: Matcher<Preference>): ViewInteraction? = findFirstPreferencePosition(recyclerViewId, *matchers).let {(i, count) ->
fun onPreferenceRow(@IdRes recyclerViewId: Int, vararg matchers: Matcher<Preference>): ViewInteraction? = findFirstPreferencePosition(recyclerViewId, *matchers).let { (i, count) ->
if (i != -1) {
// FIXME: Fails to scroll to the bottom of recycler view
onView(withId(recyclerViewId))

16
application/vlc-android/androidTest/org/videolan/vlc/UtilViewActions.kt → application/app/src/androidTest/java/org/videolan/vlc/UtilViewActions.kt

@ -1,13 +1,14 @@
package org.videolan.vlc
import android.content.pm.ActivityInfo
import androidx.test.espresso.ViewAction
import android.app.Activity
import android.content.Context
import android.content.ContextWrapper
import android.content.pm.ActivityInfo
import android.view.View
import android.view.ViewGroup
import androidx.test.espresso.UiController
import androidx.test.espresso.ViewAction
import androidx.test.espresso.matcher.ViewMatchers.isEnabled
import androidx.test.espresso.matcher.ViewMatchers.isRoot
import androidx.test.runner.lifecycle.ActivityLifecycleMonitorRegistry
import androidx.test.runner.lifecycle.Stage
@ -75,12 +76,21 @@ class OrientationChangeAction internal constructor(private val orientation: Int)
if (context is Activity) {
return context
}
context = (context as ContextWrapper).baseContext
context = context.baseContext
}
return null
}
}
class ForceClickAction : ViewAction {
override fun getConstraints() = isEnabled()
override fun getDescription() = "Force click a view even if 90% condition is not satisfied"
override fun perform(uiController: UiController?, view: View?) {
view?.performClick()
}
}
fun orientationLandscape(): ViewAction {
return OrientationChangeAction(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)
}

28
application/vlc-android/androidTest/org/videolan/vlc/UtilViewMatchers.kt → application/app/src/androidTest/java/org/videolan/vlc/UtilViewMatchers.kt

@ -17,15 +17,17 @@ import androidx.appcompat.view.menu.ActionMenuItemView
import androidx.core.content.ContextCompat
import androidx.databinding.ViewDataBinding
import androidx.recyclerview.widget.RecyclerView
import androidx.test.espresso.UiController
import androidx.test.espresso.ViewAction
import androidx.test.espresso.matcher.BoundedMatcher
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import com.google.android.material.tabs.TabLayout
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.ObsoleteCoroutinesApi
import org.hamcrest.BaseMatcher
import org.hamcrest.Description
import org.hamcrest.Matcher
import org.hamcrest.TypeSafeMatcher
import org.videolan.medialibrary.interfaces.media.MediaWrapper
import org.videolan.vlc.gui.browser.BaseBrowserAdapter
import org.videolan.vlc.gui.helpers.SelectorViewHolder
import org.videolan.vlc.gui.helpers.ThreeStatesCheckbox
@ -106,10 +108,7 @@ class MediaRecyclerViewMatcher<VH : SelectorViewHolder<out ViewDataBinding>>(@Id
override fun matchesSafely(view: View): Boolean {
if (!fillMatchesIfRequired(mapVH, view.rootView) { vh ->
if (vh is BaseBrowserAdapter.MediaViewHolder) {
val item = (vh as BaseBrowserAdapter.MediaViewHolder).binding.item as? MediaWrapper
item?.type == mediaType
} else false
false
}) return false
return mapVH[view]?.let {
@ -147,6 +146,23 @@ class MediaRecyclerViewMatcher<VH : SelectorViewHolder<out ViewDataBinding>>(@Id
}
}
class TabsMatcher internal constructor(var position: Int) : ViewAction {
override fun getConstraints(): Matcher<View> = isDisplayed()
override fun getDescription(): String = "Click on tab"
override fun perform(uiController: UiController?, view: View) {
if (view is TabLayout) {
val tabLayout: TabLayout = view as TabLayout
val tab: TabLayout.Tab? = tabLayout.getTabAt(position)
if (tab != null) {
tab.select()
}
}
}
}
class FirstViewMatcher : BaseMatcher<View>() {
var matchedBefore = false

2
application/vlc-android/androidTest/org/videolan/vlc/database/BrowserFavDaoTest.kt → application/app/src/androidTest/java/org/videolan/vlc/database/BrowserFavDaoTest.kt

@ -25,8 +25,8 @@ import org.hamcrest.MatcherAssert.assertThat
import org.hamcrest.Matchers.*
import org.junit.Test
import org.junit.runner.RunWith
import org.videolan.vlc.util.getValue
import org.videolan.vlc.util.TestUtil
import org.videolan.vlc.util.getValue
@RunWith(AndroidJUnit4::class)

0
application/vlc-android/androidTest/org/videolan/vlc/database/CustomDirectoryDaoTest.kt → application/app/src/androidTest/java/org/videolan/vlc/database/CustomDirectoryDaoTest.kt

0
application/vlc-android/androidTest/org/videolan/vlc/database/DbTest.kt → application/app/src/androidTest/java/org/videolan/vlc/database/DbTest.kt

0
application/vlc-android/androidTest/org/videolan/vlc/database/ExternalSubDaoTest.kt → application/app/src/androidTest/java/org/videolan/vlc/database/ExternalSubDaoTest.kt

26
application/vlc-android/androidTest/org/videolan/vlc/database/MigrationTest.kt → application/app/src/androidTest/java/org/videolan/vlc/database/MigrationTest.kt

@ -1,3 +1,27 @@
/*
* ************************************************************************
* MigrationTest.kt
* *************************************************************************
* Copyright © 2020 VLC authors and VideoLAN
* Author: Nicolas POMEPUY
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
* **************************************************************************
*
*
*/
/*******************************************************************************
* MigrationTest.kt
* ****************************************************************************
@ -120,7 +144,7 @@ class MigrationTest {
fun getMigratedRoomDatabase(vararg migrations:Migration): MediaDatabase {
val database: MediaDatabase = Room.databaseBuilder(
InstrumentationRegistry.getTargetContext(),
MediaDatabase::class.java, TEST_DB_NAME )
MediaDatabase::class.java, TEST_DB_NAME)
.addMigrations(*migrations)
.build()

0
application/vlc-android/androidTest/org/videolan/vlc/database/SlaveDaoTest.kt → application/app/src/androidTest/java/org/videolan/vlc/database/SlaveDaoTest.kt

0
application/vlc-android/androidTest/org/videolan/vlc/database/helpers/SqliteDatabaseTestHelper.kt → application/app/src/androidTest/java/org/videolan/vlc/database/helpers/SqliteDatabaseTestHelper.kt

0
application/vlc-android/androidTest/org/videolan/vlc/database/helpers/SqliteTestDbOpenHelper.kt → application/app/src/androidTest/java/org/videolan/vlc/database/helpers/SqliteTestDbOpenHelper.kt

0
application/vlc-android/androidTest/org/videolan/vlc/gui/PlaylistActivityUITest.kt → application/app/src/androidTest/java/org/videolan/vlc/gui/PlaylistActivityUITest.kt

8
application/vlc-android/androidTest/org/videolan/vlc/gui/PlaylistFragmentUITest.kt → application/app/src/androidTest/java/org/videolan/vlc/gui/PlaylistFragmentUITest.kt

@ -66,8 +66,8 @@ class PlaylistFragmentUITest: BaseUITest() {
@Test
fun whenPlaylistAddedFromDirectoriesView_checkPlaylistUpdated() {
// Navigate to directories view
onView(withId(R.id.root_container))
.perform(open())
// onView(withId(R.id.root_container))
// .perform(open())
onView(allOf(instanceOf(NavigationMenuItemView::class.java), hasDescendant(withText(R.string.directories))))
.check(matches(isDisplayed()))
@ -85,8 +85,8 @@ class PlaylistFragmentUITest: BaseUITest() {
.perform(click())
// Navigate back to playlists view
onView(withId(R.id.root_container))
.perform(open())
// onView(withId(R.id.root_container))
// .perform(open())
onView(allOf(instanceOf(NavigationMenuItemView::class.java), hasDescendant(withText(R.string.playlists))))
.check(matches(isDisplayed()))

0
application/vlc-android/androidTest/org/videolan/vlc/gui/browser/FileBrowserFragmentUITest.kt → application/app/src/androidTest/java/org/videolan/vlc/gui/browser/FileBrowserFragmentUITest.kt

61
application/app/src/androidTest/java/org/videolan/vlc/gui/browser/FilePickerFragmentUITest.kt

@ -0,0 +1,61 @@
/*
* ************************************************************************
* FilePickerFragmentUITest.kt
* *************************************************************************
* Copyright © 2020 VLC authors and VideoLAN
* Author: Nicolas POMEPUY
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
* **************************************************************************
*
*
*/
package org.videolan.vlc.gui.browser
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.rule.ActivityTestRule
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.ObsoleteCoroutinesApi
import org.hamcrest.Matchers.equalTo
import org.hamcrest.Matchers.greaterThan
import org.junit.Rule
import org.junit.Test
import org.videolan.vlc.R
@ObsoleteCoroutinesApi
@ExperimentalCoroutinesApi
class FilePickerFragmentUITest : org.videolan.vlc.BaseUITest() {
@Rule
@JvmField
val activityTestRule = ActivityTestRule(FilePickerActivity::class.java)
lateinit var activity: FilePickerActivity
override fun beforeTest() {
activity = activityTestRule.activity
}
@Test
fun whenAtSomeFolder_clickOnHomeIconReturnsBackToRoot() {
onView(org.videolan.vlc.withRecyclerView(R.id.network_list).atPosition(0)).perform(click())
onView(org.videolan.vlc.withRecyclerView(R.id.network_list).atPosition(0)).perform(click())
onView(withId(R.id.network_list)).check(matches(org.videolan.vlc.withCount(greaterThan(2))))
}
}

0
application/vlc-android/androidTest/org/videolan/vlc/gui/browser/StorageBrowserFragmentUITest.kt → application/app/src/androidTest/java/org/videolan/vlc/gui/browser/StorageBrowserFragmentUITest.kt

2
application/vlc-android/androidTest/org/videolan/vlc/gui/preferences/BasePreferenceUITest.kt → application/app/src/androidTest/java/org/videolan/vlc/gui/preferences/BasePreferenceUITest.kt

@ -9,11 +9,11 @@ import androidx.test.espresso.assertion.ViewAssertions
import androidx.test.espresso.matcher.ViewMatchers
import org.hamcrest.Matchers
import org.hamcrest.Matchers.allOf
import org.videolan.tools.Settings
import org.videolan.vlc.BaseUITest
import org.videolan.vlc.PreferenceMatchers
import org.videolan.vlc.R
import org.videolan.vlc.onPreferenceRow
import org.videolan.tools.Settings
abstract class BasePreferenceUITest : BaseUITest() {
val settings: SharedPreferences = Settings.getInstance(context)

0
application/vlc-android/androidTest/org/videolan/vlc/gui/preferences/PreferencesAudioUITest.kt → application/app/src/androidTest/java/org/videolan/vlc/gui/preferences/PreferencesAudioUITest.kt

0
application/vlc-android/androidTest/org/videolan/vlc/gui/preferences/PreferencesCastingUITest.kt → application/app/src/androidTest/java/org/videolan/vlc/gui/preferences/PreferencesCastingUITest.kt

0
application/vlc-android/androidTest/org/videolan/vlc/gui/preferences/PreferencesFragmentUITest.kt → application/app/src/androidTest/java/org/videolan/vlc/gui/preferences/PreferencesFragmentUITest.kt

0
application/vlc-android/androidTest/org/videolan/vlc/gui/preferences/PreferencesSubtitlesUITest.kt → application/app/src/androidTest/java/org/videolan/vlc/gui/preferences/PreferencesSubtitlesUITest.kt

0
application/vlc-android/androidTest/org/videolan/vlc/gui/preferences/PreferencesUIUITest.kt → application/app/src/androidTest/java/org/videolan/vlc/gui/preferences/PreferencesUIUITest.kt

0
application/vlc-android/androidTest/org/videolan/vlc/gui/preferences/PreferencesVideoUITest.kt → application/app/src/androidTest/java/org/videolan/vlc/gui/preferences/PreferencesVideoUITest.kt

53
application/app/src/androidTest/java/org/videolan/vlc/util/DpadHelper.kt

@ -0,0 +1,53 @@
/*
* ************************************************************************
* DpadHelper.kt
* *************************************************************************
* Copyright © 2020 VLC authors and VideoLAN
* Author: Nicolas POMEPUY
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
* **************************************************************************
*
*
*/
package org.videolan.vlc.util
import android.os.SystemClock
import android.view.KeyEvent
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.Direction
import androidx.test.uiautomator.UiDevice
object DpadHelper {
private val device: UiDevice by lazy { UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) }
fun pressDPad(direction: Direction?, nbTimes: Int = 1) {
for (i in 0 until nbTimes) {
when (direction) {
Direction.DOWN -> device.pressDPadDown()
Direction.LEFT -> device.pressDPadLeft()
Direction.UP -> device.pressDPadUp()
Direction.RIGHT -> device.pressDPadRight()
}
if (i < nbTimes - 1) SystemClock.sleep(300)
}
}
fun pressHome() = device.pressHome()
fun pressPip() = device.pressKeyCode(KeyEvent.KEYCODE_WINDOW)
fun pressStop() = device.pressKeyCode(KeyEvent.KEYCODE_MEDIA_STOP)
fun pressBack() = device.pressBack()
fun pressDPadCenter() = device.pressDPadCenter()
}

0
application/vlc-android/test-common/org/videolan/vlc/util/KExtensions.kt → application/app/src/androidTest/java/org/videolan/vlc/util/KExtensions.kt

16
application/vlc-android/test-common/org/videolan/vlc/util/LiveDataTestUtil.kt → application/app/src/androidTest/java/org/videolan/vlc/util/LiveDataTestUtil.kt

@ -21,6 +21,8 @@
package org.videolan.vlc.util
import androidx.lifecycle.LiveData
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.onEach
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit
@ -43,6 +45,20 @@ fun <T> getValue(liveData: LiveData<T>): T {
}
latch.await(2, TimeUnit.SECONDS)
@Suppress("UNCHECKED_CAST")
return data[0] as T
}
@Throws(InterruptedException::class)
fun <T> getValue(liveData: Flow<T>): T {
val data = arrayOfNulls<Any>(1)
val latch = CountDownLatch(1)
liveData.onEach { o ->
data[0] = o
latch.countDown()
}
latch.await(2, TimeUnit.SECONDS)
@Suppress("UNCHECKED_CAST")
return data[0] as T
}

0
application/vlc-android/test-common/org/videolan/vlc/util/MockitoExt.kt → application/app/src/androidTest/java/org/videolan/vlc/util/MockitoExt.kt

36
application/app/src/androidTest/java/org/videolan/vlc/util/ScreenshotUtil.kt

@ -0,0 +1,36 @@
/*
* ************************************************************************
* ScreenshotUtil.kt
* *************************************************************************
* Copyright © 2020 VLC authors and VideoLAN
* Author: Nicolas POMEPUY
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
* **************************************************************************
*
*
*/
package org.videolan.vlc.util
import tools.fastlane.screengrab.Screengrab
object ScreenshotUtil {
fun takeScreenshot(number:Int, title:String) {
Screengrab.screenshot("${normalizeNumber(number)}_$title")
}
private fun normalizeNumber(number:Int) = if (number < 10) "0$number" else "$number"
}

0
application/vlc-android/test-common/org/videolan/vlc/util/TestCoroutineContextProvider.kt → application/app/src/androidTest/java/org/videolan/vlc/util/TestCoroutineContextProvider.kt

0
application/vlc-android/test-common/org/videolan/vlc/util/TestUtil.kt → application/app/src/androidTest/java/org/videolan/vlc/util/TestUtil.kt

150
application/app/src/androidTest/java/org/videolan/vlc/util/UiUtils.kt

@ -0,0 +1,150 @@
/*
* ************************************************************************
* UiUtils.kt
* *************************************************************************
* Copyright © 2020 VLC authors and VideoLAN
* Author: Nicolas POMEPUY
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
* **************************************************************************
*
*
*/
package org.videolan.vlc.util
import android.app.Activity
import android.os.SystemClock
import android.view.View
import androidx.recyclerview.widget.RecyclerView
import androidx.test.espresso.Espresso
import androidx.test.espresso.PerformException
import androidx.test.espresso.UiController
import androidx.test.espresso.ViewAction
import androidx.test.espresso.matcher.ViewMatchers
import androidx.test.espresso.util.HumanReadables
import androidx.test.espresso.util.TreeIterables
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.runner.lifecycle.ActivityLifecycleMonitorRegistry
import androidx.test.runner.lifecycle.Stage
import org.hamcrest.Matcher
import java.util.concurrent.TimeoutException
object UiUtils {
/**
* Perform action of waiting for a specific view id.
* @param viewId The id of the view to wait for.
* @param millis The timeout of until when to wait for.
*/
fun waitId(viewId: Int, millis: Long): ViewAction? {
return object : ViewAction {
override fun getConstraints(): Matcher<View> = ViewMatchers.isEnabled()
override fun getDescription() = "wait for a specific view with id <$viewId> during $millis millis."
override fun perform(uiController: UiController, view: View?) {
uiController.loopMainThreadUntilIdle()
val startTime = System.currentTimeMillis()
val endTime = startTime + millis
val viewMatcher: Matcher<View> = ViewMatchers.withId(viewId)
val alphaViewMatcher = ViewMatchers.withAlpha(1F)
do {
for (child in TreeIterables.breadthFirstViewTraversal(view)) { // found view with required ID
if (viewMatcher.matches(child)) {
if (alphaViewMatcher.matches(child))
return
}
}
uiController.loopMainThreadForAtLeast(50)
} while (System.currentTimeMillis() < endTime)
throw PerformException.Builder()
.withActionDescription(description)
.withViewDescription(HumanReadables.describe(view))
.withCause(TimeoutException())
.build()
}
}
}
/**
* Stop the test until RecyclerView's data gets loaded.
*
* Passed [recyclerProvider] will be activated in UI thread, allowing you to retrieve the View.
*
* Workaround for https://issuetracker.google.com/issues/123653014
*/
inline fun waitUntilLoaded(crossinline recyclerProvider: () -> RecyclerView) {
Espresso.onIdle()
lateinit var recycler: RecyclerView
InstrumentationRegistry.getInstrumentation().runOnMainSync {
recycler = recyclerProvider()
}
while (recycler.hasPendingAdapterUpdates()) {
Thread.sleep(10)
}
}
fun waitForActivity(activityType: Class<out Activity>, timeout: Int = 10): Boolean {
val endTime = System.currentTimeMillis() + (timeout * 1000)
do {
val currentActivity = getActivityInstance()
// THIS LINE IS MY ISSUE **********************************************
if (currentActivity != null && activityType.isInstance(currentActivity::class.java))
return true
// ********************************************************************
SystemClock.sleep(100)
} while (System.currentTimeMillis() < endTime)
return false
}
private fun getActivityInstance(): Activity? {
val activity = arrayOfNulls<Activity>(1)
InstrumentationRegistry.getInstrumentation().runOnMainSync {
val currentActivity: Activity?
val resumedActivities = ActivityLifecycleMonitorRegistry.getInstance().getActivitiesInStage(Stage.RESUMED)
if (resumedActivities.iterator().hasNext()) {
currentActivity = resumedActivities.iterator().next() as Activity
activity[0] = currentActivity
}
}
return activity[0]
}
/**
* Stop the test until RecyclerView's has children.
*
* Passed [recyclerProvider] will be activated in UI thread, allowing you to retrieve the View.
*
* Workaround for https://issuetracker.google.com/issues/123653014
*/
inline fun waitUntilHasChildren(crossinline recyclerProvider: () -> RecyclerView) {
Espresso.onIdle()
lateinit var recycler: RecyclerView
InstrumentationRegistry.getInstrumentation().runOnMainSync {
recycler = recyclerProvider()
}
while (recycler.childCount == 0) {
Thread.sleep(10)
}
}
}

2
application/resources/build.gradle

@ -66,6 +66,8 @@ dependencies {
api "com.squareup.moshi:moshi-adapters:$rootProject.ext.moshi"
api "androidx.core:core-ktx:$rootProject.ext.androidxCoreVersion"
testApi "androidx.test:core:$rootProject.ext.testCore"
androidTestApi "androidx.test.ext:junit:$rootProject.ext.supportTest"
}
repositories {
mavenCentral()

2
application/television/build.gradle

@ -45,4 +45,6 @@ android {
dependencies {
implementation project(':application:vlc-android')
api project(':application:moviepedia')
testApi "androidx.test:core:$rootProject.ext.testCore"
androidTestApi "androidx.test.ext:junit:$rootProject.ext.supportTest"
}

2
application/vlc-android/AndroidManifest.xml

@ -3,7 +3,7 @@
xmlns:tools="http://schemas.android.com/tools"
package="org.videolan.vlc">
<uses-sdk tools:overrideLibrary="com.jraska.livedata.ktx, com.jraska.livedata"/>
<uses-sdk tools:overrideLibrary="com.jraska.livedata.ktx, com.jraska.livedata, tools.fastlane.screengrab, android_libs.ub_uiautomator"/>
<uses-permission
android:name="android.permission.READ_LOGS"

42
application/vlc-android/androidTest/org/videolan/vlc/gui/browser/FilePickerFragmentUITest.kt

@ -1,42 +0,0 @@
package org.videolan.vlc.gui.browser
import androidx.test.rule.ActivityTestRule
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.action.ViewActions.*
import androidx.test.espresso.assertion.ViewAssertions.*
import androidx.test.espresso.matcher.ViewMatchers.*
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.ObsoleteCoroutinesApi
import org.hamcrest.Matchers.*
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.videolan.vlc.BaseUITest
import org.videolan.vlc.R
import org.videolan.vlc.*
@ObsoleteCoroutinesApi
@ExperimentalCoroutinesApi
class FilePickerFragmentUITest : BaseUITest() {
@Rule
@JvmField
val activityTestRule = ActivityTestRule(FilePickerActivity::class.java)
lateinit var activity: FilePickerActivity
override fun beforeTest() {
activity = activityTestRule.activity
}
@Test
fun whenAtSomeFolder_clickOnHomeIconReturnsBackToRoot() {
onView(withRecyclerView(R.id.network_list).atPosition(0)).perform(click())
onView(withRecyclerView(R.id.network_list).atPosition(0)).perform(click())
onView(withId(R.id.network_list)).check(matches(withCount(greaterThan(2))))
onView(withId(R.id.button_home)).perform(click())
onView(withId(R.id.network_list)).check(matches(withCount(equalTo(1))))
}
}

10
application/vlc-android/build.gradle

@ -12,7 +12,7 @@ android {
dataBinding {
enabled = true
}
packagingOptions {
pickFirst '**/*.so'
}
@ -46,6 +46,7 @@ android {
}
testOptions {
animationsDisabled = true
execution 'ANDROIDX_TEST_ORCHESTRATOR'
unitTests {
includeAndroidResources = true
@ -195,8 +196,8 @@ dependencies {
testApi "androidx.arch.core:core-testing:$rootProject.ext.archVersion"
androidTestApi "androidx.arch.core:core-testing:$rootProject.ext.archVersion"
androidTestApi "androidx.test.ext:junit:$rootProject.ext.supportTest"
androidTestUtil "androidx.test:orchestrator:$rootProject.ext.supportTest"
testApi "androidx.test:core:$rootProject.ext.supportTest"
androidTestUtil "androidx.test:orchestrator:$rootProject.ext.orchestrator"
testApi "androidx.test:core:$rootProject.ext.testCore"
testApi "org.jetbrains.kotlinx:kotlinx-coroutines-test:$rootProject.ext.kotlinx_version"
testApi "org.mockito:mockito-core:$rootProject.ext.mockito"
testApi "io.mockk:mockk:$rootProject.ext.mockk"
@ -204,7 +205,8 @@ dependencies {
testApi "org.powermock:powermock-module-junit4:$rootProject.ext.powerMock"
testApi "com.jraska.livedata:testing-ktx:$rootProject.ext.livedataTest"
testApi "org.robolectric:robolectric:$rootProject.ext.robolectric"
androidTestApi 'androidx.test:rules:1.3.0-alpha05'
androidTestApi "androidx.test:rules:$rootProject.ext.testCore"
androidTestImplementation 'tools.fastlane:screengrab:2.0.0'
}

23
application/vlc-android/res/layout/toolbar.xml

@ -57,27 +57,4 @@
android:visibility="gone" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/mainLoading"
android:layout_width="match_parent"
android:layout_height="2dp"
android:visibility="gone">
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline8"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.5" />
<ProgressBar
android:id="@+id/mainLoadingProgress"
style="@style/Base.Widget.AppCompat.ProgressBar.Horizontal"
android:layout_width="match_parent"
android:layout_height="16dp"
android:indeterminateOnly="true"
android:padding="0dp"
app:layout_constraintBottom_toBottomOf="@id/guideline8"
app:layout_constraintTop_toTopOf="@id/guideline8" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.appbar.AppBarLayout>

10
application/vlc-android/src/debug/AndroidManifest.xml

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="org.videolan.vlc"
android:installLocation="auto">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CHANGE_CONFIGURATION" />
</manifest>

6
application/vlc-android/src/org/videolan/vlc/gui/MainActivity.kt

@ -73,7 +73,6 @@ class MainActivity : ContentActivity(),
{
var refreshing: Boolean = false
set(value) {
mainLoading.visibility = if (value) View.VISIBLE else View.GONE
field = value
}
private lateinit var mediaLibrary: Medialibrary
@ -96,11 +95,6 @@ class MainActivity : ContentActivity(),
if (BuildConfig.DEBUG) extensionsManager = ExtensionsManager.getInstance()
mediaLibrary = Medialibrary.getInstance()
val color = TypedValue().run {
theme.resolveAttribute(R.attr.progress_indeterminate_tint, this, true)
data
}
mainLoadingProgress.indeterminateDrawable.setColorFilter(color, android.graphics.PorterDuff.Mode.SRC_IN)
VLCBilling.getInstance(application).retrieveSkus()
}

2
application/vlc-android/src/org/videolan/vlc/gui/browser/BaseBrowserAdapter.kt

@ -183,7 +183,7 @@ open class BaseBrowserAdapter(val browserContainer: BrowserContainer<MediaLibrar
}
@TargetApi(Build.VERSION_CODES.M)
internal inner class MediaViewHolder(val bindingContainer: BrowserItemBindingContainer) : ViewHolder<ViewDataBinding>(bindingContainer.binding), MarqueeViewHolder {
inner class MediaViewHolder(val bindingContainer: BrowserItemBindingContainer) : ViewHolder<ViewDataBinding>(bindingContainer.binding), MarqueeViewHolder {
override val titleView: TextView? = bindingContainer.title
var job : Job? = null

6
application/vlc-android/test/org/videolan/vlc/viewmodels/HistoryModelTest.kt

@ -22,12 +22,12 @@ class HistoryModelTest : BaseTest() {
override fun beforeTest() {
super.beforeTest()
mediaLibrary.clearHistory()
historyModel = HistoryModel(context, TestCoroutineContextProvider())
historyModel = HistoryModel(context, org.videolan.vlc.util.TestCoroutineContextProvider())
}
@Test
fun whenRefreshCalled_ListIsUpdated() {
val fakeMediaStrings = TestUtil.createLocalUris(2)
val fakeMediaStrings = org.videolan.vlc.util.TestUtil.createLocalUris(2)
historyModel.refresh()
@ -54,7 +54,7 @@ class HistoryModelTest : BaseTest() {
@Test
fun whenListHasTwoItemsAndLastIsMovedUp_ListHasUpdatedItemsOrder() {
val fakeMediaStrings = TestUtil.createLocalUris(2)
val fakeMediaStrings = org.videolan.vlc.util.TestUtil.createLocalUris(2)
val result = fakeMediaStrings.map {
val media = MLServiceLocator.getAbstractMediaWrapper(it.toUri()).apply { type = MediaWrapper.TYPE_VIDEO }

4
application/vlc-android/test/org/videolan/vlc/viewmodels/browser/FilePickerModelTest.kt

@ -46,14 +46,14 @@ class FilePickerModelTest : BaseTest() {
mediaBrowser = spyk(MediaBrowser(mockedLibVlc, null, handler))
mediaBrowser
}
BrowserProvider.registerCreator(clazz = CoroutineContextProvider::class.java) { TestCoroutineContextProvider() }
BrowserProvider.registerCreator(clazz = CoroutineContextProvider::class.java) { org.videolan.vlc.util.TestCoroutineContextProvider() }
}
override fun beforeTest() {
super.beforeTest()
dummyUrl = temporaryFolder.root.absolutePath
browserModel = BrowserModel(application, dummyUrl, TYPE_PICKER, false, true, TestCoroutineContextProvider())
browserModel = BrowserModel(application, dummyUrl, TYPE_PICKER, false, true, org.videolan.vlc.util.TestCoroutineContextProvider())
browserProvider = browserModel.provider
setupTestFiles()

10
build.gradle

@ -60,16 +60,18 @@ ext {
archVersion = '2.1.0'
roomVersion = '2.2.5'
pagingVersion = '2.1.2'
junitVersion = '4.12'
mockito = '2.8.9'
junitVersion = '4.13'
mockito = '2.25.0'
retrofit = '2.6.1'
moshi = '1.8.0'
powerMock = '2.0.2'
espressoVersion = '3.1.1'
espressoVersion = '3.3.0'
livedataTest = '1.1.0'
robolectric = '4.3.1'
mockk = '1.9.3'
supportTest = '1.1.0'
supportTest = '1.1.2'
orchestrator = '1.1.0'
testCore = '1.3.0'
// versionCode scheme is T M NN RR AA
// T: Target/Flavour (1 for Android, 2 for Chrome?)
// M: Major version from 0 to 9

10
buildsystem/automation/Gemfile

@ -0,0 +1,10 @@
# Autogenerated by fastlane
#
# Ensure this file is checked in to source control!
source "https://rubygems.org"
gem 'fastlane'
plugins_path = File.join(File.dirname(__FILE__), 'fastlane', 'Pluginfile')
eval_gemfile(plugins_path) if File.exist?(plugins_path)

87
buildsystem/automation/README.md

@ -0,0 +1,87 @@
# Automating screenshots
## Installation
### fastlane
Install [fastlane](https://docs.fastlane.tools/)
Even if Linux is not officially supported, it can be installed easily.
`sudo apt install ruby ruby-dev`
`export LC_ALL=en_US.UTF-8`
`export LANG=en_US.UTF-8`
`sudo gem install fastlane`
### Android SDK
The Android SDK has to be installed and you have to set an env variable to its path
`export ANDROID_SDK=/path/to/sdk/`
## Usage
To launch a fastlane command, run `bundle exec fastlane [command] [option_key1]:[option_value_1] ...`
Available lanes:
### Deployment
Once the build is done by the CI and signed, copy the apks into this directory
#### Play Store:
**Prerequisites**:
Get the Play Store certificate and copy the file at `./certificates/vlc.json`
Export an env variable named `K8S_SECRET_VLC_PLAYSTORE_PUBLIC_API_KEY` with the Play Stire API key
Export an env variable named `SLACK_URL` with the slack webhook URL
- `deploy_release` sends a release to the Play Store in draft
- `deploy_beta` sends a beta to the Play Store in draft
Options: `version` is the version string in the apk name.
For example: `bundle exec fastlane deploy_beta version:"3.3.1-Beta-1"` creates a draft beta version on the Play Store for apks:
```
VLC-Android-3.3.1-Beta-1-arm64-v8a.apk
VLC-Android-3.3.1-Beta-1-armeabi-v7a.apk
VLC-Android-3.3.1-Beta-1-x86.apk
VLC-Android-3.3.1-Beta-1-x86_64.apk
```
#### Huawei
**Prerequisites**:
you need to export 3 env variables: HUAWEI_CLIENT_ID, HUAWEI_CLIENT_SECRET and HUAWEI_APP_ID
- `deploy_huawei` sends a release to the Huawei AppGallery in draft
Options: `version` is the version string in the apk name.
### Screenshots
#### Take screenshots
**Prerequisites**:
In order to make the script work, you have to **create 3 AVDs**, **install VLC** and **add the samples**
You should also skip the welcome screens and let the scanning occur.
- `screenshots`, `screenshots_seven`, `screenshots_ten`, `screenshots_tv` lanes launch respectively the screenshot UI tests for mobile, 7" tablets, 10" tablets and TV
Before running, the app and the test apks will be generated automatically
#### Upload the screenshots
- `deploy_screenshots`

1
buildsystem/automation/certificates

@ -0,0 +1 @@
/home/nicolas/Documents/vlc/release

2
buildsystem/automation/fastlane/Appfile

@ -0,0 +1,2 @@
json_key_file("certificates/vlc.json") # Path to the json secret file - Follow https://docs.fastlane.tools/actions/supply/#setup to get one
package_name("org.videolan.vlc")

84
buildsystem/automation/fastlane/Fastfile

@ -0,0 +1,84 @@
# This file contains the fastlane.tools configuration
# You can find the documentation at https://docs.fastlane.tools
#
# For a list of all available actions, check out
#
# https://docs.fastlane.tools/actions
#
# For a list of all available plugins, check out
#
# https://docs.fastlane.tools/plugins/available-plugins
#
# Uncomment the line if you want fastlane to automatically update itself
# update_fastlane
default_platform(:android)
platform :android do
desc "Runs all the tests"
lane :test do
gradle(task: "test")
end
desc "Deploy a new version to the Google Play"
lane :deploy_release do |options|
upload_to_play_store(skip_upload_changelogs:true, skip_upload_images:true, skip_upload_screenshots:true, release_status:"draft", apk_paths:["VLC-Android-"+options[:version]+"-arm64-v8a.apk", "VLC-Android-"+options[:version]+"-armeabi-v7a.apk", "VLC-Android-"+options[:version]+"-x86.apk", "VLC-Android-"+options[:version]+"-x86_64.apk"])
slack(message: 'Successfully created a new draft for '+options[:version])
end
lane :deploy_screenshots do
upload_to_play_store(skip_upload_changelogs:true, skip_upload_images:true, skip_upload_apk:true, release_status:"draft", apk_paths:["VLC-Android-3.3.0-arm64-v8a.apk", "VLC-Android-3.3.0-armeabi-v7a.apk", "VLC-Android-3.3.0-x86.apk", "VLC-Android-3.3.0-x86_64.apk"])
slack(message: 'Successfully uploaded screenshots to Play Store')
end
lane :deploy_beta do |options|
upload_to_play_store(skip_upload_changelogs:true, track: 'beta', skip_upload_images:true, skip_upload_screenshots:true, skip_upload_apk:false, release_status:"draft", apk_paths:["VLC-Android-"+options[:version]+"-arm64-v8a.apk", "VLC-Android-"+options[:version]+"-armeabi-v7a.apk", "VLC-Android-"+options[:version]+"-x86.apk", "VLC-Android-"+options[:version]+"-x86_64.apk"])
slack(message: 'Successfully created a new beta draft for '+options[:version])
end
lane :screenshots do
gradle(task: 'assemble', build_type: 'Debug', project_dir:'../..')
gradle(task: ':application:app:assemble', build_type: 'DebugAndroidTest', project_dir:'../..')
capture_android_screenshots(app_apk_path:"../../application/app/build/outputs/apk/debug/VLC-Android-3.3.0-debug-all.apk", tests_apk_path:"../../application/app/build/outputs/apk/androidTest/debug/app-debug-androidTest.apk")
end
lane :screenshots_seven do
gradle(task: 'assemble', build_type: 'Debug', project_dir:'../..')
gradle(task: ':application:app:assemble', build_type: 'DebugAndroidTest', project_dir:'../..')
capture_android_screenshots(device_type:"sevenInch" ,app_apk_path:"../../application/app/build/outputs/apk/debug/VLC-Android-3.3.0-debug-all.apk", tests_apk_path:"../../application/app/build/outputs/apk/androidTest/debug/app-debug-androidTest.apk")
end
lane :screenshots_ten do
gradle(task: 'assemble', build_type: 'Debug', project_dir:'../..')
gradle(task: ':application:app:assemble', build_type: 'DebugAndroidTest', project_dir:'../..')
capture_android_screenshots(device_type:"tenInch" ,app_apk_path:"../../application/app/build/outputs/apk/debug/VLC-Android-3.3.0-debug-all.apk", tests_apk_path:"../../application/app/build/outputs/apk/androidTest/debug/app-debug-androidTest.apk")
end
lane :screenshots_tv do
gradle(task: 'assemble', build_type: 'Debug', project_dir:'../..')
gradle(task: ':application:app:assemble', build_type: 'DebugAndroidTest', project_dir:'../..')
capture_android_screenshots(device_type:"tv",use_tests_in_classes:'org.videolan.vlc.TvScreenhotsInstrumentedTest', app_apk_path:"../../application/app/build/outputs/apk/debug/VLC-Android-3.3.0-debug-all.apk", tests_apk_path:"../../application/app/build/outputs/apk/androidTest/debug/app-debug-androidTest.apk")
end
lane :huawei_info do
huawei_appgallery_connect_get_app_info(
client_id: ENV["HUAWEI_CLIENT_ID"],
client_secret: ENV["HUAWEI_CLIENT_SECRET"],
app_id: ENV["HUAWEI_APP_ID"]
)
end
lane :deploy_huawei do |options|
#gradle(task: 'assemble', build_type: 'Release')
huawei_appgallery_connect(
client_id: ENV["HUAWEI_CLIENT_ID"],
client_secret: ENV["HUAWEI_CLIENT_SECRET"],
app_id: ENV["HUAWEI_APP_ID"],
apk_path: "VLC-Android-"+options[:version]+"-arm64-v8a.apk",
submit_for_review: false,
)
slack(message: 'Successfully created a new draft for '+options[:version]+' on Huawei AppGallery')
end
end

5
buildsystem/automation/fastlane/Pluginfile

@ -0,0 +1,5 @@
# Autogenerated by fastlane
#
# Ensure this file is checked in to source control!
gem 'fastlane-plugin-huawei_appgallery_connect'

15
buildsystem/automation/fastlane/Screengrabfile

@ -0,0 +1,15 @@
# remove the leading '#' to uncomment lines
app_package_name("org.videolan.vlc.debug")
use_tests_in_classes(['org.videolan.vlc.PhoneScreenhotsInstrumentedTest'])
use_adb_root(true)
test_instrumentation_runner("org.videolan.vlc.MultidexTestRunner")
#locales(['en-US', 'fr-FR', 'it-IT', 'ko-KR', 'ja-JP'])
locales(['en-US', 'fr-FR', 'it-IT'])
# clear all previously generated screenshots in your local output directory before creating new ones
clear_previous_screenshots(true)
# For more information about all available options run
# fastlane screengrab --help

36
extension-api/src/androidTest/java/org/videolan/vlc/plugin/api/ApplicationTest.java

@ -1,36 +0,0 @@
/*
* *************************************************************************
* ApplicationTest.java
* **************************************************************************
* Copyright © 2015 VLC authors and VideoLAN
* Author: Geoffrey Métais
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
* ***************************************************************************
*/
package org.videolan.vlc.extensions.api;
import android.app.Application;
import android.test.ApplicationTestCase;
/**
* <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
*/
public class ApplicationTest extends ApplicationTestCase<Application> {
public ApplicationTest() {
super(Application.class);
}
}

2
gradle.properties

@ -4,5 +4,5 @@ android.databinding.incremental=true
kapt.incremental.apt=true
kapt.use.worker.api=true
kapt.include.compile.classpath=false
org.gradle.jvmargs=-Xmx4g -XX:MaxPermSize=2048m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
org.gradle.jvmargs=-Xms512M -Xmx4g -XX:MaxPermSize=2048m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
org.gradle.parallel=true

Loading…
Cancel
Save