Skip to content

Commit 921b3c0

Browse files
Merge branch 'develop'
2 parents fa4800f + fcdb8f9 commit 921b3c0

File tree

35 files changed

+866
-81
lines changed

35 files changed

+866
-81
lines changed

.github/workflows/e2e-test-cron.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ jobs:
8080
uses: actions/[email protected]
8181
if: failure()
8282
with:
83-
name: logs_${{ env.ANDROID_API_LEVEL }}
83+
name: test_artifacts_${{ env.ANDROID_API_LEVEL }}
8484
path: |
8585
fastlane/recordings/*
8686
fastlane/video-buddy-server.log

.github/workflows/e2e-test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ jobs:
8888
if: failure()
8989
timeout-minutes: 10
9090
with:
91-
name: logs_${{ matrix.batch }}
91+
name: test_artifacts_${{ matrix.batch }}
9292
path: |
9393
fastlane/recordings/*
9494
fastlane/video-buddy-server.log

buildSrc/src/main/kotlin/io/getstream/video/android/Configuration.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@ object Configuration {
66
const val minSdk = 24
77
const val majorVersion = 1
88
const val minorVersion = 6
9-
const val patchVersion = 0
9+
const val patchVersion = 1
1010
const val versionName = "$majorVersion.$minorVersion.$patchVersion"
11-
const val versionCode = 56
11+
const val versionCode = 57
12+
const val snapshotBasedVersionName = "$majorVersion.$minorVersion.${patchVersion + 1}"
1213
const val snapshotVersionName = "$majorVersion.$minorVersion.${patchVersion + 1}-SNAPSHOT"
1314
const val artifactGroup = "io.getstream"
1415
const val streamVideoCallGooglePlayVersion = "1.6.0"

demo-app/src/androidTestE2etestingDebug/kotlin/io/getstream/video/android/pages/CallPage.kt

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ class CallPage {
3636
val chatButton = By.res("Stream_ChatButton")
3737
val connectionQualityIndicator = By.res("Stream_ParticipantNetworkQualityIndicator")
3838
val callInfoView = By.res("Stream_CallInfoView") // duration, recording, reconnecting
39+
val recordingIcon = By.res("Stream_RecordingIcon")
40+
val videoView = By.res("Stream_VideoView")
41+
val videoViewWithMediaTrack = By.res("Stream_VideoViewWithMediaTrack")
3942

4043
// val participantEvent = By.res("") // not implemented in the demo app yet
4144
// val minimizedCallView = By.res("") // not implemented in the demo app yet
@@ -51,7 +54,7 @@ class CallPage {
5154

5255
class RecordingButtons {
5356
companion object {
54-
val start = By.text("Continue")
57+
val accept = By.text("Continue")
5558
val leave = By.text("Leave")
5659
val end = By.text("End")
5760
val cancel = By.text("Cancel")
@@ -79,8 +82,8 @@ class CallPage {
7982
val networkQualityIndicator = By.res("Stream_ParticipantNetworkQualityIndicator")
8083
val microphoneEnabledIcon = By.res("Stream_ParticipantMicrophone_Enabled_true")
8184
val microphoneDisabledIcon = By.res("Stream_ParticipantMicrophone_Enabled_false")
82-
val videoWindow = By.res("Stream_ParticipantVideoView")
83-
val videoWindowWithCamera = By.res("Stream_ParticipantVideoWithCamera")
85+
val videoView = CallPage.videoView
86+
val videoViewWithMediaTrack = CallPage.videoViewWithMediaTrack
8487
val spotlightView = By.res("Stream_SpotlightView")
8588
val gridView = By.res("Stream_GridView")
8689
val screenSharingLabel = By.res("Stream_ParticipantScreenSharingLabel")

demo-app/src/androidTestE2etestingDebug/kotlin/io/getstream/video/android/robots/UserRobot.kt

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,17 @@ class UserRobot {
225225
return this
226226
}
227227

228-
fun waitForParticipantsToJoin(count: Int, timeOutMillis: Long = 30.seconds): UserRobot {
228+
fun acceptCallRecording(): UserRobot {
229+
CallPage.RecordingButtons.accept.waitToAppear(timeOutMillis = 10.seconds).click()
230+
return this
231+
}
232+
233+
fun declineCallRecording(): UserRobot {
234+
CallPage.RecordingButtons.leave.waitToAppear(timeOutMillis = 10.seconds).click()
235+
return this
236+
}
237+
238+
fun waitForParticipantsToJoin(count: Int = 1, timeOutMillis: Long = 30.seconds): UserRobot {
229239
val user = 1
230240
val participants = user + count
231241
CallPage.participantsCountBadge

demo-app/src/androidTestE2etestingDebug/kotlin/io/getstream/video/android/robots/UserRobotCallAsserts.kt

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,17 @@
1717
package io.getstream.video.android.robots
1818

1919
import io.getstream.video.android.pages.CallPage
20+
import io.getstream.video.android.uiautomator.findObject
21+
import io.getstream.video.android.uiautomator.findObjects
2022
import io.getstream.video.android.uiautomator.isDisplayed
23+
import io.getstream.video.android.uiautomator.seconds
24+
import io.getstream.video.android.uiautomator.waitForCount
2125
import io.getstream.video.android.uiautomator.waitForText
2226
import io.getstream.video.android.uiautomator.waitToAppear
27+
import io.getstream.video.android.uiautomator.waitToDisappear
28+
import org.junit.Assert.assertEquals
29+
import org.junit.Assert.assertFalse
30+
import org.junit.Assert.assertNotEquals
2331
import org.junit.Assert.assertTrue
2432

2533
fun UserRobot.assertCallControls(microphone: Boolean, camera: Boolean): UserRobot {
@@ -51,3 +59,58 @@ fun UserRobot.assertParticipantsCountOnCall(count: Int): UserRobot {
5159
.waitForText(expectedText = participants.toString())
5260
return this
5361
}
62+
63+
fun UserRobot.assertParticipantMicrophone(isEnabled: Boolean): UserRobot {
64+
if (isEnabled) {
65+
assertTrue(CallPage.ParticipantView.microphoneEnabledIcon.waitToAppear().isDisplayed())
66+
} else {
67+
assertTrue(CallPage.ParticipantView.microphoneDisabledIcon.waitToAppear().isDisplayed())
68+
}
69+
return this
70+
}
71+
72+
fun UserRobot.assertMediaTracks(count: Int): UserRobot {
73+
if (count > 0) {
74+
val mediaTracks = CallPage.ParticipantView.videoViewWithMediaTrack.waitForCount(count)
75+
assertEquals(count, mediaTracks.size)
76+
} else {
77+
CallPage.ParticipantView.videoViewWithMediaTrack.waitToDisappear()
78+
assertEquals(count, CallPage.ParticipantView.videoViewWithMediaTrack.findObjects().size)
79+
}
80+
return this
81+
}
82+
83+
fun UserRobot.assertConnectionQualityIndicator(): UserRobot {
84+
assertTrue(CallPage.ParticipantView.networkQualityIndicator.waitToAppear().isDisplayed())
85+
return this
86+
}
87+
88+
fun UserRobot.assertRecordingView(isDisplayed: Boolean): UserRobot {
89+
val label = "Recording"
90+
if (isDisplayed) {
91+
assertTrue(CallPage.recordingIcon.waitToAppear().isDisplayed())
92+
assertEquals(label, CallPage.callInfoView.findObject().text)
93+
} else {
94+
assertFalse(CallPage.recordingIcon.waitToDisappear().isDisplayed())
95+
assertNotEquals(label, CallPage.callInfoView.findObject().text)
96+
}
97+
return this
98+
}
99+
100+
fun UserRobot.assertCallDurationView(isDisplayed: Boolean): UserRobot {
101+
val callDurationViewText = CallPage.callInfoView.waitToAppear().text
102+
assertEquals(isDisplayed, Regex("\\d+s").containsMatchIn(callDurationViewText))
103+
return this
104+
}
105+
106+
fun UserRobot.assertParticipantScreenSharingView(isDisplayed: Boolean): UserRobot {
107+
val screenSharingView = CallPage.ParticipantView.screenSharingView
108+
if (isDisplayed) {
109+
assertTrue(screenSharingView.waitToAppear(timeOutMillis = 10.seconds).isDisplayed())
110+
assertTrue(CallPage.ParticipantView.screenSharingLabel.waitToAppear().isDisplayed())
111+
} else {
112+
assertFalse(screenSharingView.waitToDisappear(timeOutMillis = 10.seconds).isDisplayed())
113+
assertFalse(CallPage.ParticipantView.screenSharingLabel.waitToDisappear().isDisplayed())
114+
}
115+
return this
116+
}
Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
/*
2+
* Copyright (c) 2014-2024 Stream.io Inc. All rights reserved.
3+
*
4+
* Licensed under the Stream License;
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://github.com/GetStream/stream-video-android/blob/main/LICENSE
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.getstream.video.android.tests
18+
19+
import io.getstream.video.android.robots.ParticipantRobot.Actions
20+
import io.getstream.video.android.robots.ParticipantRobot.Options
21+
import io.getstream.video.android.robots.UserControls
22+
import io.getstream.video.android.robots.assertCallDurationView
23+
import io.getstream.video.android.robots.assertConnectionQualityIndicator
24+
import io.getstream.video.android.robots.assertMediaTracks
25+
import io.getstream.video.android.robots.assertParticipantMicrophone
26+
import io.getstream.video.android.robots.assertParticipantScreenSharingView
27+
import io.getstream.video.android.robots.assertRecordingView
28+
import io.qameta.allure.kotlin.Allure.step
29+
import io.qameta.allure.kotlin.AllureId
30+
import org.junit.Test
31+
32+
class ParticipantActionsTests : StreamTestCase() {
33+
34+
@AllureId("6985")
35+
@Test
36+
fun testParticipantEnablesMicrophone() {
37+
step("GIVEN user starts a call") {
38+
userRobot.joinCall()
39+
}
40+
step("AND participant joins the call and turns on mic") {
41+
participantRobot.joinCall(callId, arrayOf(Options.WITH_MICROPHONE))
42+
userRobot.waitForParticipantsToJoin()
43+
}
44+
for (view in allViews) {
45+
step("WHEN user turns on ${view.name} view") {
46+
userRobot.setView(view)
47+
}
48+
step("THEN user observes that participant's microphone is enabled") {
49+
userRobot.assertParticipantMicrophone(isEnabled = true)
50+
}
51+
}
52+
}
53+
54+
@AllureId("6987")
55+
@Test
56+
fun testParticipantDisablesMicrophone() {
57+
step("GIVEN user starts a call") {
58+
userRobot.joinCall()
59+
}
60+
step("AND participant joins the call and turns off mic") {
61+
participantRobot.joinCall(callId)
62+
userRobot.waitForParticipantsToJoin()
63+
}
64+
for (view in allViews) {
65+
step("WHEN user turns on ${view.name} view") {
66+
userRobot.setView(view)
67+
}
68+
step("THEN user observes that participant's microphone is disabled") {
69+
userRobot.assertParticipantMicrophone(isEnabled = false)
70+
}
71+
}
72+
}
73+
74+
@AllureId("7007")
75+
@Test
76+
fun testParticipantEnablesCamera() {
77+
step("GIVEN user starts a call") {
78+
userRobot.joinCall(camera = UserControls.DISABLE)
79+
}
80+
step("AND participant joins the call and turns camera on") {
81+
participantRobot.joinCall(callId, arrayOf(Options.WITH_CAMERA))
82+
userRobot.waitForParticipantsToJoin()
83+
}
84+
for (view in allViews) {
85+
step("WHEN user turns on ${view.name} view") {
86+
userRobot.setView(view)
87+
}
88+
step("THEN user observes that participant's camera is enabled") {
89+
userRobot.assertMediaTracks(count = 1)
90+
}
91+
}
92+
}
93+
94+
@AllureId("7006")
95+
@Test
96+
fun testParticipantDisablesCamera() {
97+
step("GIVEN user starts a call") {
98+
userRobot.joinCall(camera = UserControls.DISABLE)
99+
}
100+
step("AND participant joins the call and turns camera off") {
101+
participantRobot.joinCall(callId)
102+
userRobot.waitForParticipantsToJoin()
103+
}
104+
for (view in allViews) {
105+
step("WHEN user turns on ${view.name} view") {
106+
userRobot.setView(view)
107+
}
108+
step("THEN user observes that participant's camera is disabled") {
109+
userRobot.assertMediaTracks(count = 0)
110+
}
111+
}
112+
}
113+
114+
@AllureId("6927")
115+
@Test
116+
fun testParticipantConnectionQualityIndicator() {
117+
step("GIVEN user starts a call") {
118+
userRobot.joinCall()
119+
}
120+
step("AND participant joins the call") {
121+
participantRobot.joinCall(callId, arrayOf(Options.WITH_CAMERA))
122+
userRobot.waitForParticipantsToJoin()
123+
}
124+
for (view in allViews) {
125+
step("WHEN user turns on ${view.name} view") {
126+
userRobot.setView(view)
127+
}
128+
step("THEN user observers participant's connection indicator icon") {
129+
userRobot.assertConnectionQualityIndicator()
130+
}
131+
}
132+
}
133+
134+
@AllureId("6933")
135+
@Test
136+
fun testParticipantRecordsCall() {
137+
step("GIVEN user starts a call") {
138+
userRobot.joinCall()
139+
}
140+
step("AND participant joins the call and starts recording the call for 10 seconds") {
141+
participantRobot
142+
.setCallRecordingDuration(15)
143+
.joinCall(callId, actions = arrayOf(Actions.RECORD_CALL))
144+
}
145+
step("WHEN participants join the call and one of them starts recording") {
146+
userRobot
147+
.waitForParticipantsToJoin()
148+
.acceptCallRecording()
149+
}
150+
for (view in allViews) {
151+
step("THEN user turns on ${view.name} view and observes the recording icon appeared") {
152+
userRobot
153+
.setView(view)
154+
.assertRecordingView(isDisplayed = true)
155+
.assertCallDurationView(isDisplayed = false)
156+
}
157+
}
158+
step("WHEN participant stops recording") {
159+
// presumably some stopRecording() call goes here if applicable
160+
}
161+
for (view in allViews) {
162+
step(
163+
"THEN user turns on ${view.name} view and observes the recording icon disappeared",
164+
) {
165+
userRobot
166+
.setView(view)
167+
.assertRecordingView(isDisplayed = false)
168+
.assertCallDurationView(isDisplayed = true)
169+
}
170+
}
171+
}
172+
173+
@AllureId("6993")
174+
@Test
175+
fun testParticipantSharesScreen() {
176+
step("GIVEN user starts a call") {
177+
userRobot.joinCall()
178+
}
179+
step("WHEN participant joins the call and shares the screen for 3 seconds") {
180+
participantRobot
181+
.setScreenSharingDuration(10)
182+
.joinCall(callId, actions = arrayOf(Actions.SHARE_SCREEN))
183+
userRobot.waitForParticipantsToJoin()
184+
}
185+
step("THEN user observers participant's screen") {
186+
userRobot.assertParticipantScreenSharingView(isDisplayed = true)
187+
}
188+
step("AND participant stops sharing screen") {
189+
userRobot.assertParticipantScreenSharingView(isDisplayed = false)
190+
}
191+
}
192+
}

demo-app/src/androidTestE2etestingDebug/kotlin/io/getstream/video/android/tests/StreamTestCase.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import android.annotation.SuppressLint
3131
import io.getstream.chat.android.e2e.test.rules.RetryRule
3232
import io.getstream.video.android.robots.ParticipantRobot
3333
import io.getstream.video.android.robots.UserRobot
34+
import io.getstream.video.android.robots.VideoView
3435
import io.getstream.video.android.uiautomator.device
3536
import io.getstream.video.android.uiautomator.grantPermission
3637
import io.getstream.video.android.uiautomator.startApp
@@ -46,6 +47,7 @@ abstract class StreamTestCase {
4647

4748
val userRobot = UserRobot()
4849
lateinit var participantRobot: ParticipantRobot
50+
val allViews: Array<VideoView> = arrayOf(VideoView.GRID, VideoView.DYNAMIC, VideoView.SPOTLIGHT)
4951
lateinit var callId: String
5052
private val headlessBrowser = true
5153
private val recordBrowser = true

demo-app/src/main/kotlin/io/getstream/video/android/ui/call/CallScreen.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,7 @@ fun CallScreen(
432432
},
433433
videoRenderer = { modifier, call, participant, style ->
434434
ParticipantVideo(
435-
modifier = modifier.testTag("Stream_ParticipantVideoView"),
435+
modifier = modifier.testTag("Stream_VideoView"),
436436
call = call,
437437
participant = participant,
438438
style = style,

fastlane/Fastfile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ before_all do |lane|
1717
end
1818
end
1919

20-
lane :start_video_buddy do
21-
install_video_buddy
20+
lane :start_video_buddy do |options|
21+
install_video_buddy unless options[:debug]
2222
stop_video_buddy if is_localhost
2323
sh("stream-video-buddy server --port #{video_buddy_port} > video-buddy-server.log 2>&1 &")
2424
end
@@ -124,7 +124,7 @@ lane :install_video_buddy do
124124
sh("npm install -g playwright@#{playwright_version}")
125125
sh('npx playwright install chromium')
126126

127-
stream_video_buddy_version = '1.6.26'
127+
stream_video_buddy_version = '1.6.27'
128128
sh("npm list -g stream-video-buddy | grep -q '#{stream_video_buddy_version}' || " \
129129
"npm install -g 'https://github.com/GetStream/stream-video-buddy##{stream_video_buddy_version}'")
130130
end

0 commit comments

Comments
 (0)