Skip to content

Commit

Permalink
chore: add UI integration test (aws-amplify#33)
Browse files Browse the repository at this point in the history
* add integration test app

* make face liveness session extendable

* add UI integration test

* remove unused code

* fix build issue

* test: fix failed test
  • Loading branch information
phantumcode authored and devedup committed Sep 12, 2023
1 parent 810b0c4 commit 2c2885c
Show file tree
Hide file tree
Showing 34 changed files with 2,087 additions and 18 deletions.
18 changes: 16 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,26 @@ HostApp/dist/
HostApp/node_modules/
HostApp/generated-src/
HostApp/aws-exports.js
HostApp/.gitignore
HostApp/awsconfiguration.json
HostApp/amplifyconfiguration.json
HostApp/amplifyconfiguration.dart
HostApp/amplify-build-config.json
HostApp/amplify-gradle-config.json
HostApp/amplifytools.xcconfig
HostApp/.secret-*
HostApp/**.sample
HostApp/**.sample
Tests/IntegrationTestApp/amplify/
Tests/IntegrationTestApp/build/
Tests/IntegrationTestApp/dist/
Tests/IntegrationTestApp/node_modules/
Tests/IntegrationTestApp/generated-src/
Tests/IntegrationTestApp/aws-exports.js
Tests/IntegrationTestApp/awsconfiguration.json
Tests/IntegrationTestApp/amplifyconfiguration.json
Tests/IntegrationTestApp/amplifyconfiguration.dart
Tests/IntegrationTestApp/amplify-build-config.json
Tests/IntegrationTestApp/amplify-gradle-config.json
Tests/IntegrationTestApp/amplifytools.xcconfig
Tests/IntegrationTestApp/.secret-*
Tests/IntegrationTestApp/**.sample
Tests/IntegrationTestApp/*.xcodeproj
8 changes: 4 additions & 4 deletions Sources/FaceLiveness/AV/LivenessCaptureSession.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,18 @@
import UIKit
import AVFoundation

final class LivenessCaptureSession {
class LivenessCaptureSession {
let captureDevice: LivenessCaptureDevice
private let captureQueue = DispatchQueue(label: "com.amazonaws.faceliveness.cameracapturequeue")
private let outputDelegate: OutputSampleBufferCapturer
private var captureSession: AVCaptureSession?
let outputDelegate: OutputSampleBufferCapturer
var captureSession: AVCaptureSession?

init(captureDevice: LivenessCaptureDevice, outputDelegate: OutputSampleBufferCapturer) {
self.captureDevice = captureDevice
self.outputDelegate = outputDelegate
}

func startSession(frame: CGRect) throws -> AVCaptureVideoPreviewLayer {
func startSession(frame: CGRect) throws -> CALayer {
guard let camera = captureDevice.avCaptureDevice
else { throw LivenessCaptureSessionError.cameraUnavailable }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,46 @@ public struct FaceLivenessDetectorView: View {
)
)
}

init(
sessionID: String,
credentialsProvider: AWSCredentialsProvider? = nil,
region: String,
disableStartView: Bool = false,
isPresented: Binding<Bool>,
onCompletion: @escaping (Result<Void, FaceLivenessDetectionError>) -> Void,
captureSession: LivenessCaptureSession
) {
self.disableStartView = disableStartView
self._isPresented = isPresented
self.onCompletion = onCompletion

self.sessionTask = Task {
let session = try await AWSPredictionsPlugin.startFaceLivenessSession(
withID: sessionID,
credentialsProvider: credentialsProvider,
region: region,
options: .init(),
completion: map(detectionCompletion: onCompletion)
)
return session
}

let faceInOvalStateMatching = FaceInOvalMatching(
instructor: Instructor()
)

self._viewModel = StateObject(
wrappedValue: .init(
faceDetector: captureSession.outputDelegate.faceDetector,
faceInOvalMatching: faceInOvalStateMatching,
captureSession: captureSession,
videoChunker: captureSession.outputDelegate.videoChunker,
closeButtonAction: { onCompletion(.failure(.userCancelled)) },
sessionID: sessionID
)
)
}

public var body: some View {
switch displayState {
Expand Down Expand Up @@ -204,7 +244,7 @@ enum InstructionState {
case display(text: String)
}

fileprivate func map(detectionCompletion: @escaping (Result<Void, FaceLivenessDetectionError>) -> Void) -> ((Result<Void, FaceLivenessSessionError>) -> Void) {
private func map(detectionCompletion: @escaping (Result<Void, FaceLivenessDetectionError>) -> Void) -> ((Result<Void, FaceLivenessSessionError>) -> Void) {
{ result in
switch result {
case .success:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,11 +117,9 @@ class FaceLivenessDetectionViewModel: ObservableObject {
captureSession.stopRunning()
}

func startCamera(withinFrame frame: CGRect) -> AVCaptureVideoPreviewLayer? {
func startCamera(withinFrame frame: CGRect) -> CALayer? {
do {
let avLayer = try captureSession.startSession(frame: frame)
avLayer.frame = frame
layerRectConverted = avLayer.layerRectConverted(fromMetadataOutputRect:)
DispatchQueue.main.async {
self.livenessState.checkIsFacePrepared()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import Amplify

final class _LivenessViewController: UIViewController {
let viewModel: FaceLivenessDetectionViewModel
var previewLayer: AVCaptureVideoPreviewLayer!
var previewLayer: CALayer!

let faceShapeLayer = CAShapeLayer()
var ovalExists = false
Expand Down Expand Up @@ -86,13 +86,6 @@ final class _LivenessViewController: UIViewController {
}
}



func convert(rect: CGRect) -> CGRect {
let box = previewLayer.layerRectConverted(fromMetadataOutputRect: rect)
return box
}

var runningFreshness = false
var hasSentClientInformationEvent = false
var challengeID = UUID().uuidString
Expand Down
Loading

0 comments on commit 2c2885c

Please sign in to comment.