@@ -27,6 +27,7 @@ import com.amplifyframework.predictions.models.FaceLivenessSessionInformation
27
27
import com.amplifyframework.predictions.options.FaceLivenessSessionOptions
28
28
import com.amplifyframework.ui.liveness.camera.FrameAnalyzer
29
29
import com.amplifyframework.ui.liveness.ml.FaceDetector
30
+ import com.amplifyframework.ui.liveness.model.LivenessCheckState
30
31
import com.amplifyframework.ui.liveness.state.LivenessState
31
32
import com.amplifyframework.ui.liveness.ui.FaceLivenessDetector
32
33
import io.mockk.CapturingSlot
@@ -66,7 +67,8 @@ class LivenessFlowInstrumentationTest {
66
67
private lateinit var noFaceString: String
67
68
private lateinit var multipleFaceString: String
68
69
private lateinit var connectingString: String
69
- private lateinit var countdownString: String
70
+ private lateinit var moveCloserString: String
71
+ private lateinit var holdStillString: String
70
72
71
73
@get:Rule
72
74
val composeTestRule = createComposeRule()
@@ -102,8 +104,9 @@ class LivenessFlowInstrumentationTest {
102
104
R .string.amplify_ui_liveness_challenge_instruction_multiple_faces_detected,
103
105
)
104
106
connectingString = context.getString(R .string.amplify_ui_liveness_challenge_connecting)
105
- countdownString = context.getString(
106
- R .string.amplify_ui_liveness_challenge_instruction_hold_face_during_countdown,
107
+ moveCloserString = context.getString(R .string.amplify_ui_liveness_challenge_instruction_move_face_closer)
108
+ holdStillString = context.getString(
109
+ R .string.amplify_ui_liveness_challenge_instruction_hold_face_during_freshness,
107
110
)
108
111
}
109
112
@@ -303,10 +306,11 @@ class LivenessFlowInstrumentationTest {
303
306
every { faceTargetMatchingParameters.faceIouHeightThreshold }.returns(0.15f )
304
307
305
308
val faceTargetChallenge = mockk<FaceTargetChallenge >()
306
- every { faceTargetChallenge.targetWidth }.returns(422f )
307
- every { faceTargetChallenge.targetHeight }.returns(683f )
308
- every { faceTargetChallenge.targetCenterX }.returns(230f )
309
- every { faceTargetChallenge.targetCenterY }.returns(292f )
309
+ val faceRect = RectF (19f , - 49f , 441f , 633f )
310
+ every { faceTargetChallenge.targetWidth }.returns(faceRect.right - faceRect.left)
311
+ every { faceTargetChallenge.targetHeight }.returns(faceRect.bottom - faceRect.top)
312
+ every { faceTargetChallenge.targetCenterX }.returns((faceRect.left + faceRect.right) / 2 )
313
+ every { faceTargetChallenge.targetCenterY }.returns((faceRect.top + faceRect.bottom) / 2 )
310
314
every { faceTargetChallenge.faceTargetMatching }.returns(faceTargetMatchingParameters)
311
315
312
316
val colors = listOf (
@@ -350,23 +354,44 @@ class LivenessFlowInstrumentationTest {
350
354
),
351
355
)
352
356
353
- composeTestRule.waitUntil(5000 ) {
354
- composeTestRule.onAllNodesWithText(" asdlkfjasdf" )
357
+ // update face location to show oval
358
+ livenessState?.onFrameFaceUpdate(
359
+ RectF (0f , 0f , 400f , 400f ),
360
+ FaceDetector .Landmark (60f , 60f ),
361
+ FaceDetector .Landmark (140f , 60f ),
362
+ FaceDetector .Landmark (100f , 160f ),
363
+ )
364
+
365
+ // in the same spot as it was originally, the face is too far
366
+ composeTestRule.waitUntil(1000 ) {
367
+ composeTestRule.onAllNodesWithText(moveCloserString)
355
368
.fetchSemanticsNodes().size == 1
356
369
}
357
370
358
371
composeTestRule.waitForIdle()
359
372
373
+ // update face to be inside the oval position
374
+ livenessState?.onFrameFaceUpdate(
375
+ faceRect,
376
+ FaceDetector .Landmark (60f , 60f ),
377
+ FaceDetector .Landmark (140f , 60f ),
378
+ FaceDetector .Landmark (100f , 160f ),
379
+ )
380
+
381
+ // now, the face is inside the oval. wait for the colors to finish
382
+ composeTestRule.waitForIdle()
383
+
384
+ assertTrue(livenessState?.readyToSendFinalEvents == true )
385
+ val state = livenessState?.livenessCheckState?.value
386
+ assertTrue(state is LivenessCheckState .Success )
387
+ assertTrue((state as LivenessCheckState .Success ).faceGuideRect == faceRect)
388
+
360
389
onLivenessComplete.captured.call()
361
390
assertTrue(completesSuccessfully)
362
391
363
392
unmockkConstructor(FrameAnalyzer ::class )
364
393
}
365
394
366
- // TODO: this gets to the camera page! next up:
367
- // 1. figure out how to trigger the next step
368
- // 2. test on virtual device, might be fine...
369
-
370
395
companion object {
371
396
@BeforeClass
372
397
@JvmStatic
0 commit comments