mirror of
https://gitlab.linphone.org/BC/public/linphone-android.git
synced 2026-01-24 15:18:08 +00:00
add screen comparison for incoming call uitests
This commit is contained in:
parent
33627faca8
commit
945d444c47
20 changed files with 166 additions and 90 deletions
|
|
@ -326,8 +326,7 @@ def embedScreenshotsTask = task('embedScreenshots', group: 'reporting') {
|
|||
def name = failedTestCaseDescription.substring(pt1+1, pt2)
|
||||
def pt3 = failedTestCaseDescription.indexOf(".", pt2+1)
|
||||
if (pt3 != -1) {
|
||||
def pt4 = failedTestCaseDescription.indexOf(".", pt3+1)
|
||||
name += " (${failedTestCaseDescription.substring(pt3+1,pt4)})"
|
||||
name += " (${failedTestCaseDescription.substring(pt2+1,pt3)})"
|
||||
}
|
||||
|
||||
def failedTestClassJunitReportFile = new File(reportsDirectory, "${failedTestClassName}.html")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,71 @@
|
|||
package org.linphone.call
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.rule.GrantPermissionRule
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.linphone.methods.*
|
||||
import org.linphone.methods.UITestsScreenshots.takeScreenshot
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class IncomingCallPushUITests {
|
||||
|
||||
lateinit var methods: CallViewUITestsMethods
|
||||
|
||||
@get:Rule
|
||||
val screenshotsRule = ScreenshotsRule(true)
|
||||
|
||||
@get:Rule
|
||||
var mGrantPermissionRule = GrantPermissionRule.grant(*LinphonePermissions.CALL)
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
UITestsUtils.testAppSetup()
|
||||
methods = CallViewUITestsMethods()
|
||||
takeScreenshot("dialer_view")
|
||||
methods.startIncomingCall()
|
||||
takeScreenshot("dialer_view", "incoming_call_push")
|
||||
}
|
||||
|
||||
@After
|
||||
fun tearDown() {
|
||||
methods.endCall()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDisplayCallPush() {
|
||||
methods.endCall()
|
||||
takeScreenshot("dialer_view")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testNoAnswerCallPush() {
|
||||
methods.noAnswerCallFromPush()
|
||||
takeScreenshot("dialer_view")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testClickOnCallPush() {
|
||||
methods.openIncomingCallViewFromPush()
|
||||
takeScreenshot("incoming_call_view")
|
||||
methods.endCall()
|
||||
takeScreenshot("dialer_view")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDeclineCallPush() {
|
||||
methods.declineCallFromPush()
|
||||
takeScreenshot("dialer_view")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAnswerCallPush() {
|
||||
methods.answerCallFromPush()
|
||||
takeScreenshot("single_call_view")
|
||||
methods.endCall()
|
||||
takeScreenshot("dialer_view")
|
||||
}
|
||||
}
|
||||
|
|
@ -1,77 +1,64 @@
|
|||
package org.linphone.call
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.rule.GrantPermissionRule
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.linphone.methods.CallViewUITestsMethods
|
||||
import org.linphone.methods.UITestsUtils
|
||||
import org.linphone.methods.*
|
||||
import org.linphone.methods.UITestsScreenshots.takeScreenshot
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class IncomingCallUITests {
|
||||
|
||||
lateinit var methods: CallViewUITestsMethods
|
||||
|
||||
@get:Rule
|
||||
val screenshotsRule = ScreenshotsRule(true)
|
||||
|
||||
@get:Rule
|
||||
var mGrantPermissionRule = GrantPermissionRule.grant(*LinphonePermissions.CALL)
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
UITestsUtils.testAppSetup()
|
||||
methods = CallViewUITestsMethods()
|
||||
}
|
||||
|
||||
// notification tests
|
||||
@Test
|
||||
fun testDisplayCallPush() {
|
||||
methods.startIncomingCall()
|
||||
methods.endCall()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testNoAnswerCallPush() {
|
||||
methods.startIncomingCall()
|
||||
methods.noAnswerCallFromPush()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDeclineCallPush() {
|
||||
methods.startIncomingCall()
|
||||
methods.declineCallFromPush()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAnswerCallPush() {
|
||||
methods.startIncomingCall()
|
||||
methods.answerCallFromPush()
|
||||
methods.endCall()
|
||||
}
|
||||
|
||||
// incoming call view tests
|
||||
@Test
|
||||
fun testOpenIncomingCallView() {
|
||||
takeScreenshot("dialer_view")
|
||||
methods.startIncomingCall()
|
||||
methods.openIncomingCallViewFromPush()
|
||||
takeScreenshot("incoming_call_view")
|
||||
}
|
||||
|
||||
@After
|
||||
fun tearDown() {
|
||||
methods.endCall()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testOpenIncomingCallView() {
|
||||
methods.endCall()
|
||||
takeScreenshot("dialer_view")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testNoAnswerIncomingCallView() {
|
||||
methods.startIncomingCall()
|
||||
methods.openIncomingCallViewFromPush()
|
||||
methods.noAnswerCallFromIncomingCall()
|
||||
takeScreenshot("dialer_view")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDeclineIncomingCallView() {
|
||||
methods.startIncomingCall()
|
||||
methods.openIncomingCallViewFromPush()
|
||||
methods.declineCallFromIncomingCallView()
|
||||
methods.endCall()
|
||||
takeScreenshot("dialer_view")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAcceptIncomingCallView() {
|
||||
methods.startIncomingCall()
|
||||
methods.openIncomingCallViewFromPush()
|
||||
methods.answerCallFromIncomingCallView()
|
||||
takeScreenshot("single_call_view")
|
||||
methods.endCall()
|
||||
takeScreenshot("dialer_view")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,14 +25,7 @@ class OutgoingCallUITests {
|
|||
val screenshotsRule = ScreenshotsRule(true)
|
||||
|
||||
@get:Rule
|
||||
var mGrantPermissionRule = GrantPermissionRule.grant(
|
||||
"android.permission.READ_PHONE_NUMBERS",
|
||||
"android.permission.MANAGE_OWN_CALLS",
|
||||
"android.permission.POST_NOTIFICATIONS",
|
||||
"android.permission.READ_PHONE_STATE",
|
||||
"android.permission.BLUETOOTH_CONNECT",
|
||||
"android.permission.RECORD_AUDIO"
|
||||
)
|
||||
var mGrantPermissionRule = GrantPermissionRule.grant(*LinphonePermissions.CALL)
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,9 @@ package org.linphone.methods
|
|||
import android.app.Activity
|
||||
import android.app.NotificationManager
|
||||
import android.content.Context
|
||||
import android.widget.Chronometer
|
||||
import androidx.test.espresso.Espresso.onView
|
||||
import androidx.test.espresso.ViewInteraction
|
||||
import androidx.test.espresso.action.ViewActions.click
|
||||
import androidx.test.espresso.action.ViewActions.typeText
|
||||
import androidx.test.espresso.assertion.ViewAssertions.doesNotExist
|
||||
|
|
@ -42,6 +44,7 @@ class CallViewUITestsMethods {
|
|||
onView(withContentDescription(R.string.content_description_start_call)).perform(click())
|
||||
|
||||
onView(withId(R.id.outgoing_call_layout)).checkWithTimeout(matches(isDisplayed()), 5.0)
|
||||
checkCallTime(onView(withId(R.id.outgoing_call_timer)))
|
||||
}
|
||||
|
||||
fun endCall() {
|
||||
|
|
@ -50,7 +53,24 @@ class CallViewUITestsMethods {
|
|||
ghostAccount.terminateCall()
|
||||
ghostAccount.waitForCallState(Call.State.Released, 5.0)
|
||||
onView(withId(R.id.outgoing_call_layout)).checkWithTimeout(doesNotExist(), 5.0)
|
||||
// onView(withId(com.google.android.material.R.id.snackbar_text)).checkWithTimeout(doesNotExist(), 5.0)
|
||||
waitForCallNotification(false, 5.0)
|
||||
}
|
||||
|
||||
fun checkCallTime(view: ViewInteraction) = runBlocking {
|
||||
view.checkWithTimeout(matches(isDisplayed()), 2.0)
|
||||
launch(Dispatchers.Default) {
|
||||
val timerArray = arrayListOf<Int>()
|
||||
repeat(3) {
|
||||
view.check { view, _ ->
|
||||
val value = (view as Chronometer).text.toString()
|
||||
timerArray.add((value.split(":").last()).toInt())
|
||||
}
|
||||
delay(1000)
|
||||
}
|
||||
assert(timerArray.distinct().size >= 2) { "[UITests] Call Time is not correctly incremented, less than 2 differents values are displayed in 3 seconds" }
|
||||
assert(timerArray == timerArray.sorted()) { "[UITests] Call Time is not correctly incremented, it is not increasing" }
|
||||
assert(timerArray.first() <= 4) { "[UITests] Call Time is not correctly initialized, it is more than 4 right after the start (found: ${timerArray.first()}))" }
|
||||
}
|
||||
}
|
||||
|
||||
fun noAnswerCallFromPush() {
|
||||
|
|
@ -58,7 +78,7 @@ class CallViewUITestsMethods {
|
|||
}
|
||||
|
||||
fun declineCallFromPush() {
|
||||
val declineLabel = getString(R.string.incoming_call_notification_answer_action_label)
|
||||
val declineLabel = "Decline" // getString(R.string.incoming_call_notification_hangup_action_label)
|
||||
|
||||
try {
|
||||
val decline = device.findObject(By.textContains(declineLabel))
|
||||
|
|
@ -66,6 +86,7 @@ class CallViewUITestsMethods {
|
|||
} catch (e: java.lang.NullPointerException) {
|
||||
throw AssertionError("[UITests] Enable to find the \"$declineLabel\" button in the incoming call notification")
|
||||
}
|
||||
waitForCallNotification(false, 5.0)
|
||||
}
|
||||
|
||||
fun answerCallFromPush() {
|
||||
|
|
@ -76,6 +97,7 @@ class CallViewUITestsMethods {
|
|||
} catch (e: java.lang.NullPointerException) {
|
||||
throw AssertionError("[UITests] Enable to find the \"$answerLabel\" button in the incoming call notification")
|
||||
}
|
||||
waitForCallNotification(false, 5.0)
|
||||
onView(withId(R.id.single_call_layout)).checkWithTimeout(matches(isDisplayed()), 5.0)
|
||||
}
|
||||
|
||||
|
|
@ -87,6 +109,7 @@ class CallViewUITestsMethods {
|
|||
throw AssertionError("[UITests] Enable to find the incoming call notification")
|
||||
}
|
||||
onView(withId(R.id.incoming_call_layout)).checkWithTimeout(matches(isDisplayed()), 5.0)
|
||||
checkCallTime(onView(withId(R.id.outgoing_call_timer)))
|
||||
}
|
||||
|
||||
fun declineCallFromIncomingCallView() {
|
||||
|
|
@ -113,28 +136,15 @@ class CallViewUITestsMethods {
|
|||
|
||||
fun noAnswerCallFromOutgoingCall() {
|
||||
onView(withId(R.id.outgoing_call_layout)).checkWithTimeout(doesNotExist(), 30.0)
|
||||
/*
|
||||
val snackbar = onView(withId(com.google.android.material.R.id.snackbar_text))
|
||||
snackbar.checkWithTimeout(
|
||||
matches(
|
||||
allOf(
|
||||
withText(containsString("Error")),
|
||||
withText(containsString("Request Timeout"))
|
||||
)
|
||||
),
|
||||
5.0
|
||||
)
|
||||
snackbar.checkWithTimeout(doesNotExist(), 5.0)
|
||||
*/
|
||||
}
|
||||
|
||||
private fun waitForCallNotification(exist: Boolean, timeout: Double) = runBlocking {
|
||||
var result = false
|
||||
var result = !exist
|
||||
val wait = launch(Dispatchers.Default) {
|
||||
lateinit var activity: Activity
|
||||
activityScenario!!.onActivity { act -> activity = act }
|
||||
val manager = activity.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
repeat(timeout.toInt() * 10) {
|
||||
repeat((timeout * 10).toInt()) {
|
||||
for (notif in manager.activeNotifications) {
|
||||
if (notif.notification.channelId == getString(R.string.notification_channel_incoming_call_id)) {
|
||||
result = true
|
||||
|
|
@ -142,12 +152,13 @@ class CallViewUITestsMethods {
|
|||
}
|
||||
result = false
|
||||
}
|
||||
if (manager.activeNotifications.isEmpty()) result = false
|
||||
if (result == exist) { cancel() }
|
||||
delay(100)
|
||||
}
|
||||
}
|
||||
wait.join()
|
||||
delay(500)
|
||||
delay(1000)
|
||||
assert(result == exist) { "[UITests] Incoming call Notification still ${if (exist) "not " else ""}displayed after $timeout seconds" }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -309,33 +309,25 @@ class UITestsRegisteredLinphoneCore(authInfo: AuthInfo) {
|
|||
assert(result) { "[UITests] $registrationState registration state still not verified after $timeout seconds" }
|
||||
}
|
||||
|
||||
fun waitForCallState(callState: Call.State, timeout: Double) = runBlocking {
|
||||
fun waitForCallState(call_state: Call.State, timeout: Double) = runBlocking {
|
||||
var result = false
|
||||
val wait = launch { delay(timeout.toLong() * 1000) }
|
||||
val listener = object : CoreListenerStub() {
|
||||
override fun onCallStateChanged(
|
||||
core: Core,
|
||||
call: Call,
|
||||
state: Call.State?,
|
||||
message: String
|
||||
) {
|
||||
super.onCallStateChanged(core, call, state, message)
|
||||
if (callState == state) {
|
||||
val wait = launch(Dispatchers.Default) {
|
||||
repeat((timeout * 10).toInt()) {
|
||||
if (call_state == callState) {
|
||||
result = true
|
||||
wait.cancel()
|
||||
cancel()
|
||||
}
|
||||
delay(100)
|
||||
}
|
||||
}
|
||||
mCore.addListener(listener)
|
||||
wait.join()
|
||||
mCore.removeListener(listener)
|
||||
assert(result) { "[UITests] $callState call state still not verified after $timeout seconds" }
|
||||
assert(result) { "[UITests] $call_state call state still not verified after $timeout seconds (last known state: $callState)" }
|
||||
}
|
||||
|
||||
fun waitForRecordingState(recording: Boolean, onRemote: Boolean = false, timeout: Double) = runBlocking {
|
||||
var result = false
|
||||
val wait = launch(Dispatchers.Default) {
|
||||
repeat(timeout.toInt() * 10) { i ->
|
||||
repeat((timeout * 10).toInt()) {
|
||||
if (!onRemote && recording == mCore.currentCall?.params?.isRecording) {
|
||||
result = true
|
||||
cancel()
|
||||
|
|
|
|||
|
|
@ -2,10 +2,13 @@ package org.linphone.methods
|
|||
|
||||
import android.os.Environment.DIRECTORY_PICTURES
|
||||
import android.os.Environment.getExternalStoragePublicDirectory
|
||||
import android.view.View
|
||||
import androidx.test.runner.screenshot.BasicScreenCaptureProcessor
|
||||
import androidx.test.runner.screenshot.Screenshot
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.linphone.core.tools.Log
|
||||
|
||||
object UITestsScreenshots {
|
||||
|
|
@ -23,9 +26,9 @@ object UITestsScreenshots {
|
|||
)
|
||||
}
|
||||
|
||||
private fun screenshot(screenShotName: String) {
|
||||
private fun screenshot(screenShotName: String, view: View? = null) {
|
||||
Log.i("[UITests] Taking screenshot of '$screenShotName'")
|
||||
val screenCapture = Screenshot.capture()
|
||||
val screenCapture = if (view == null) Screenshot.capture() else Screenshot.capture(view)
|
||||
val processors = setOf(MyScreenCaptureProcessor())
|
||||
try {
|
||||
screenCapture.apply {
|
||||
|
|
@ -41,13 +44,16 @@ object UITestsScreenshots {
|
|||
fun takeScreenshot(
|
||||
name: String,
|
||||
variant: String? = null,
|
||||
delay: Double = 0.5,
|
||||
view: View? = null,
|
||||
line: Int = Throwable().stackTrace[1].lineNumber
|
||||
) {
|
||||
if (!screenshotComparison) return
|
||||
if (name.contains(".") || variant?.contains(".") == true) {
|
||||
throw Exception("[UITests] \".\" character is forbidden for takeScreenshot methods arguments name and variant")
|
||||
}
|
||||
screenshot(line.toString() + ".$name" + if (variant != null) ".$variant" else "")
|
||||
runBlocking { delay((delay * 1000).toLong()) }
|
||||
screenshot(line.toString() + ".$name" + if (variant != null) ".$variant" else "", view)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -39,6 +39,21 @@ class ScreenshotsRule(active: Boolean) : TestWatcher() {
|
|||
}
|
||||
}
|
||||
|
||||
object LinphonePermissions {
|
||||
|
||||
val LAUNCH = arrayListOf(
|
||||
"android.permission.READ_PHONE_NUMBERS",
|
||||
"android.permission.MANAGE_OWN_CALLS",
|
||||
"android.permission.POST_NOTIFICATIONS",
|
||||
"android.permission.READ_PHONE_STATE"
|
||||
).toTypedArray()
|
||||
|
||||
val CALL = LAUNCH + arrayListOf(
|
||||
"android.permission.BLUETOOTH_CONNECT",
|
||||
"android.permission.RECORD_AUDIO"
|
||||
).toTypedArray()
|
||||
}
|
||||
|
||||
object UITestsUtils {
|
||||
|
||||
private var mainActivityIntent = Intent(getApplicationContext(), MainActivity::class.java)
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 186 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 111 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 118 KiB After Width: | Height: | Size: 120 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 147 KiB |
|
|
@ -2,12 +2,14 @@ package org.linphone.testsuites
|
|||
|
||||
import org.junit.runner.RunWith
|
||||
import org.junit.runners.Suite
|
||||
import org.linphone.call.IncomingCallPushUITests
|
||||
import org.linphone.call.IncomingCallUITests
|
||||
import org.linphone.call.OutgoingCallUITests
|
||||
|
||||
@RunWith(Suite::class)
|
||||
@Suite.SuiteClasses(
|
||||
OutgoingCallUITests::class,
|
||||
IncomingCallUITests::class
|
||||
IncomingCallPushUITests::class,
|
||||
IncomingCallUITests::class,
|
||||
OutgoingCallUITests::class
|
||||
)
|
||||
class CallTestSuite
|
||||
|
|
|
|||
2
screport
2
screport
|
|
@ -1 +1 @@
|
|||
Subproject commit 1d7df53aece8df01de28eb680d03d6ffab37fce0
|
||||
Subproject commit edf429c2d535a64e9b31bbfad7411190c0669086
|
||||
Loading…
Add table
Reference in a new issue