462 lines
18 KiB
Swift
462 lines
18 KiB
Swift
//
|
|
// Copyright Amazon.com Inc. or its affiliates.
|
|
// All Rights Reserved.
|
|
//
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
//
|
|
|
|
import XCTest
|
|
@testable import Amplify
|
|
@testable import AmplifyTestCommon
|
|
|
|
class AmplifyOperationHubTests: XCTestCase {
|
|
|
|
override func setUp() async throws {
|
|
await Amplify.reset()
|
|
|
|
let storageConfiguration =
|
|
StorageCategoryConfiguration(plugins: ["MockDispatchingStoragePlugin": nil])
|
|
let config = AmplifyConfiguration(storage: storageConfiguration)
|
|
do {
|
|
try Amplify.add(plugin: MockDispatchingStoragePlugin())
|
|
try Amplify.configure(config)
|
|
} catch {
|
|
XCTFail("Error setting up Amplify: \(error)")
|
|
}
|
|
}
|
|
|
|
override func tearDown() async throws {
|
|
await Amplify.reset()
|
|
}
|
|
|
|
/// Given: An AmplifyOperation
|
|
/// When: I invoke Hub.listen(to: operation)
|
|
/// Then: I am notified of events for that operation, in the operation event listener format
|
|
func testlistenerViaListenToOperation() async throws {
|
|
let options = StorageListRequest.Options(pluginOptions: ["pluginDelay": 0.5])
|
|
let request = StorageListRequest(options: options)
|
|
|
|
let operation = MockDispatchingStorageListOperation(request: request)
|
|
|
|
let listenerWasInvoked = expectation(description: "listener was invoked")
|
|
|
|
let token = Amplify.Hub.listenForResult(to: operation) { _ in
|
|
listenerWasInvoked.fulfill()
|
|
}
|
|
|
|
try await waitForToken(token)
|
|
|
|
operation.doMockDispatch()
|
|
|
|
await waitForExpectations(timeout: 1.0)
|
|
}
|
|
|
|
/// Given: A configured system
|
|
/// When: I perform an operation with an `listener` listener
|
|
/// Then: That listener is notified when an event occurs
|
|
func testlistenerViaOperationInit() throws {
|
|
throw XCTSkip("Storage listeners removed")
|
|
// TODO: consider rewriting with async API
|
|
// let listenerInvoked = expectation(description: "listener was invoked")
|
|
// let operation = Amplify.Storage.getURL(key: "foo") { _ in
|
|
// listenerInvoked.fulfill()
|
|
// }
|
|
// if let mockOperation = operation as? MockDispatchingStorageGetURLOperation {
|
|
// mockOperation.doMockDispatch()
|
|
// }
|
|
// waitForExpectations(timeout: 1.0)
|
|
}
|
|
|
|
/// Given: A configured system
|
|
/// When: I subscribe to Hub events filtered by operation ID
|
|
/// Then: My listener receives events for that ID
|
|
func testListenerViaHubListen() throws {
|
|
throw XCTSkip("Storage listeners removed")
|
|
// TODO: consider rewriting with async API
|
|
// let listenerInvoked = expectation(description: "listener was invoked")
|
|
// let operation = Amplify.Storage.getURL(key: "foo") { _ in
|
|
// listenerInvoked.fulfill()
|
|
// }
|
|
//
|
|
// let operationId = operation.id
|
|
//
|
|
// let token = Amplify.Hub.listen(to: .storage) { payload in
|
|
// guard let context = payload.context as? AmplifyOperationContext<StorageListRequest> else {
|
|
// return
|
|
// }
|
|
//
|
|
// if context.operationId == operationId {
|
|
// listenerInvoked.fulfill()
|
|
// }
|
|
// }
|
|
//
|
|
// try waitForToken(token)
|
|
//
|
|
// if let mockOperation = operation as? MockDispatchingStorageGetURLOperation {
|
|
// mockOperation.doMockDispatch()
|
|
// }
|
|
//
|
|
// waitForExpectations(timeout: 1.0)
|
|
}
|
|
|
|
// Convenience to let tests wait for a listener to be registered. Instead of returning a bool, simply throws if the
|
|
// listener is not registered
|
|
private func waitForToken(_ token: UnsubscribeToken) async throws {
|
|
// swiftlint:disable:next force_cast
|
|
let hubPlugin = try Amplify.Hub.getPlugin(for: AWSHubPlugin.key) as! AWSHubPlugin
|
|
guard try await HubListenerTestUtilities.waitForListener(with: token, plugin: hubPlugin, timeout: 1.0) else {
|
|
throw "Listener not registered"
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
class MockDispatchingStoragePlugin: StorageCategoryPlugin {
|
|
|
|
var key: PluginKey = "MockDispatchingStoragePlugin"
|
|
|
|
let queue = DispatchQueue(label: "MockDispatchingStoragePlugin.dispatch")
|
|
|
|
func configure(using configuration: Any?) throws {}
|
|
|
|
func getURL(key: String,
|
|
options: StorageGetURLRequest.Options? = nil,
|
|
resultListener: StorageGetURLOperation.ResultListener? = nil) -> StorageGetURLOperation {
|
|
let options = options ?? StorageGetURLRequest.Options()
|
|
|
|
let request = StorageGetURLRequest(key: key, options: options)
|
|
|
|
let operation = MockDispatchingStorageGetURLOperation(request: request,
|
|
resultListener: resultListener)
|
|
return operation
|
|
}
|
|
|
|
func downloadData(key: String,
|
|
options: StorageDownloadDataRequest.Options? = nil,
|
|
progressListener: ProgressListener? = nil,
|
|
resultListener: StorageDownloadDataOperation.ResultListener? = nil
|
|
) -> StorageDownloadDataOperation {
|
|
let options = options ?? StorageDownloadDataRequest.Options()
|
|
|
|
let request = StorageDownloadDataRequest(key: key, options: options)
|
|
|
|
let operation = MockDispatchingStorageDownloadDataOperation(request: request,
|
|
progressListener: progressListener,
|
|
resultListener: resultListener)
|
|
return operation
|
|
}
|
|
|
|
func downloadFile(key: String,
|
|
local: URL,
|
|
options: StorageDownloadFileRequest.Options? = nil,
|
|
progressListener: ProgressListener? = nil,
|
|
resultListener: StorageDownloadFileOperation.ResultListener? = nil
|
|
) -> StorageDownloadFileOperation {
|
|
let options = options ?? StorageDownloadFileRequest.Options()
|
|
|
|
let request = StorageDownloadFileRequest(key: key, local: local, options: options)
|
|
|
|
let operation = MockDispatchingStorageDownloadFileOperation(request: request,
|
|
progressListener: progressListener,
|
|
resultListener: resultListener)
|
|
return operation
|
|
}
|
|
|
|
func uploadData(key: String,
|
|
data: Data,
|
|
options: StorageUploadDataRequest.Options? = nil,
|
|
progressListener: ProgressListener? = nil,
|
|
resultListener: StorageUploadDataOperation.ResultListener? = nil
|
|
) -> StorageUploadDataOperation {
|
|
let options = options ?? StorageUploadDataRequest.Options()
|
|
|
|
let request = StorageUploadDataRequest(key: key, data: data, options: options)
|
|
|
|
let operation = MockDispatchingStorageUploadDataOperation(request: request,
|
|
progressListener: progressListener,
|
|
resultListener: resultListener)
|
|
return operation
|
|
}
|
|
|
|
func uploadFile(key: String,
|
|
local: URL,
|
|
options: StorageUploadFileRequest.Options? = nil,
|
|
progressListener: ProgressListener? = nil,
|
|
resultListener: StorageUploadFileOperation.ResultListener? = nil
|
|
) -> StorageUploadFileOperation {
|
|
let options = options ?? StorageUploadFileRequest.Options()
|
|
|
|
let request = StorageUploadFileRequest(key: key, local: local, options: options)
|
|
|
|
let operation = MockDispatchingStorageUploadFileOperation(request: request,
|
|
progressListener: progressListener,
|
|
resultListener: resultListener)
|
|
return operation
|
|
}
|
|
|
|
func remove(key: String,
|
|
options: StorageRemoveRequest.Options? = nil,
|
|
resultListener: StorageRemoveOperation.ResultListener? = nil) -> StorageRemoveOperation {
|
|
let options = options ?? StorageRemoveRequest.Options()
|
|
|
|
let request = StorageRemoveRequest(key: key, options: options)
|
|
|
|
let operation = MockDispatchingStorageRemoveOperation(request: request,
|
|
resultListener: resultListener)
|
|
return operation
|
|
}
|
|
|
|
func list(options: StorageListRequest.Options?,
|
|
resultListener: StorageListOperation.ResultListener?) -> StorageListOperation {
|
|
let options = options ?? StorageListRequest.Options()
|
|
|
|
let request = StorageListRequest(options: options)
|
|
|
|
let operation = MockDispatchingStorageListOperation(request: request,
|
|
resultListener: resultListener)
|
|
return operation
|
|
}
|
|
|
|
func handleBackgroundEvents(identifier: String) async -> Bool {
|
|
false
|
|
}
|
|
|
|
func reset() {
|
|
// Do nothing
|
|
}
|
|
|
|
// MARK: - Async API -
|
|
|
|
@discardableResult
|
|
func getURL(key: String,
|
|
options: StorageGetURLOperation.Request.Options?) async throws -> URL {
|
|
let options = options ?? StorageGetURLRequest.Options()
|
|
let request = StorageGetURLRequest(key: key, options: options)
|
|
let operation = MockStorageGetURLOperation(request: request)
|
|
let taskAdapter = AmplifyOperationTaskAdapter(operation: operation)
|
|
return try await taskAdapter.value
|
|
}
|
|
|
|
@discardableResult
|
|
public func downloadData(key: String,
|
|
options: StorageDownloadDataOperation.Request.Options? = nil) -> StorageDownloadDataTask {
|
|
let options = options ?? StorageDownloadDataRequest.Options()
|
|
let request = StorageDownloadDataRequest(key: key, options: options)
|
|
let operation = MockDispatchingStorageDownloadDataOperation(request: request)
|
|
let taskAdapter = AmplifyInProcessReportingOperationTaskAdapter(operation: operation)
|
|
return taskAdapter
|
|
}
|
|
|
|
@discardableResult
|
|
public func downloadFile(key: String,
|
|
local: URL,
|
|
options: StorageDownloadFileOperation.Request.Options?) -> StorageDownloadFileTask {
|
|
let options = options ?? StorageDownloadFileRequest.Options()
|
|
let request = StorageDownloadFileRequest(key: key, local: local, options: options)
|
|
let operation = MockDispatchingStorageDownloadFileOperation(request: request)
|
|
let taskAdapter = AmplifyInProcessReportingOperationTaskAdapter(operation: operation)
|
|
return taskAdapter
|
|
}
|
|
|
|
@discardableResult
|
|
public func uploadData(key: String,
|
|
data: Data,
|
|
options: StorageUploadDataOperation.Request.Options?) -> StorageUploadDataTask {
|
|
let options = options ?? StorageUploadDataRequest.Options()
|
|
let request = StorageUploadDataRequest(key: key, data: data, options: options)
|
|
let operation = MockDispatchingStorageUploadDataOperation(request: request)
|
|
let taskAdapter = AmplifyInProcessReportingOperationTaskAdapter(operation: operation)
|
|
return taskAdapter
|
|
}
|
|
|
|
@discardableResult
|
|
public func uploadFile(key: String,
|
|
local: URL,
|
|
options: StorageUploadFileOperation.Request.Options?) -> StorageUploadFileTask {
|
|
let options = options ?? StorageUploadFileRequest.Options()
|
|
let request = StorageUploadFileRequest(key: key, local: local, options: options)
|
|
let operation = MockDispatchingStorageUploadFileOperation(request: request)
|
|
let taskAdapter = AmplifyInProcessReportingOperationTaskAdapter(operation: operation)
|
|
return taskAdapter
|
|
}
|
|
|
|
@discardableResult
|
|
public func remove(key: String,
|
|
options: StorageRemoveRequest.Options? = nil) async throws -> String {
|
|
let options = options ?? StorageRemoveRequest.Options()
|
|
let request = StorageRemoveRequest(key: key, options: options)
|
|
let operation = MockDispatchingStorageRemoveOperation(request: request)
|
|
let taskAdapter = AmplifyOperationTaskAdapter(operation: operation)
|
|
return try await taskAdapter.value
|
|
}
|
|
|
|
@discardableResult
|
|
func list(options: StorageListOperation.Request.Options?) async throws -> StorageListResult {
|
|
let options = options ?? StorageListRequest.Options()
|
|
let request = StorageListRequest(options: options)
|
|
let operation = MockDispatchingStorageListOperation(request: request)
|
|
let taskAdapter = AmplifyOperationTaskAdapter(operation: operation)
|
|
return try await taskAdapter.value
|
|
}
|
|
|
|
}
|
|
|
|
// swiftlint:disable:next type_name
|
|
class MockDispatchingStorageDownloadFileOperation: AmplifyInProcessReportingOperation<
|
|
StorageDownloadFileRequest,
|
|
Progress,
|
|
Void,
|
|
StorageError
|
|
>, StorageDownloadFileOperation {
|
|
init(request: Request, progressListener: ProgressListener? = nil, resultListener: ResultListener? = nil) {
|
|
super.init(categoryType: .storage,
|
|
eventName: HubPayload.EventName.Storage.downloadFile,
|
|
request: request,
|
|
inProcessListener: progressListener,
|
|
resultListener: resultListener)
|
|
}
|
|
|
|
func doMockDispatch() {
|
|
super.dispatch(result: Result.successfulVoid)
|
|
}
|
|
|
|
func doMockProgress() {
|
|
super.dispatchInProcess(data: Progress(totalUnitCount: 1))
|
|
}
|
|
}
|
|
|
|
// swiftlint:disable:next type_name
|
|
class MockDispatchingStorageDownloadDataOperation: AmplifyInProcessReportingOperation<
|
|
StorageDownloadDataRequest,
|
|
Progress,
|
|
Data,
|
|
StorageError
|
|
>, StorageDownloadDataOperation {
|
|
init(request: Request, progressListener: ProgressListener? = nil, resultListener: ResultListener? = nil) {
|
|
super.init(categoryType: .storage,
|
|
eventName: HubPayload.EventName.Storage.downloadData,
|
|
request: request,
|
|
inProcessListener: progressListener,
|
|
resultListener: resultListener)
|
|
}
|
|
|
|
func doMockDispatch(result: StorageDownloadDataOperation.OperationResult = .success(Data())) {
|
|
super.dispatch(result: result)
|
|
}
|
|
|
|
func doMockProgress() {
|
|
super.dispatchInProcess(data: Progress(totalUnitCount: 1))
|
|
}
|
|
}
|
|
|
|
class MockDispatchingStorageGetURLOperation: AmplifyOperation<
|
|
StorageGetURLRequest,
|
|
URL,
|
|
StorageError
|
|
>, StorageGetURLOperation {
|
|
init(request: Request, resultListener: ResultListener? = nil) {
|
|
super.init(categoryType: .storage,
|
|
eventName: HubPayload.EventName.Storage.getURL,
|
|
request: request,
|
|
resultListener: resultListener)
|
|
}
|
|
|
|
func doMockDispatch(result: StorageGetURLOperation.OperationResult = .success(URL(fileURLWithPath: "/path"))) {
|
|
super.dispatch(result: result)
|
|
}
|
|
}
|
|
|
|
class MockDispatchingStorageListOperation: AmplifyOperation<
|
|
StorageListRequest,
|
|
StorageListResult,
|
|
StorageError
|
|
>, StorageListOperation {
|
|
init(request: Request, resultListener: ResultListener? = nil) {
|
|
super.init(categoryType: .storage,
|
|
eventName: HubPayload.EventName.Storage.list,
|
|
request: request,
|
|
resultListener: resultListener)
|
|
}
|
|
|
|
func doMockDispatch() {
|
|
super.dispatch(result: .success(StorageListResult(items: [])))
|
|
}
|
|
}
|
|
|
|
class MockDispatchingStorageRemoveOperation: AmplifyOperation<
|
|
StorageRemoveRequest,
|
|
String,
|
|
StorageError
|
|
>, StorageRemoveOperation {
|
|
init(request: Request, resultListener: ResultListener? = nil) {
|
|
super.init(categoryType: .storage,
|
|
eventName: HubPayload.EventName.Storage.remove,
|
|
request: request,
|
|
resultListener: resultListener)
|
|
}
|
|
|
|
func doMockDispatch() {
|
|
super.dispatch(result: .success("Done"))
|
|
}
|
|
}
|
|
|
|
// swiftlint:disable:next type_name
|
|
class MockDispatchingStorageUploadDataOperation: AmplifyInProcessReportingOperation<
|
|
StorageUploadDataRequest,
|
|
Progress,
|
|
String,
|
|
StorageError
|
|
>, StorageUploadDataOperation {
|
|
init(request: Request, progressListener: ProgressListener? = nil, resultListener: ResultListener? = nil) {
|
|
super.init(categoryType: .storage,
|
|
eventName: HubPayload.EventName.Storage.uploadData,
|
|
request: request,
|
|
inProcessListener: progressListener,
|
|
resultListener: resultListener)
|
|
}
|
|
|
|
func doMockDispatch() {
|
|
super.dispatch(result: .success("Done"))
|
|
}
|
|
|
|
func doMockProgress() {
|
|
super.dispatchInProcess(data: Progress(totalUnitCount: 1))
|
|
}
|
|
}
|
|
|
|
// swiftlint:disable:next type_name
|
|
class MockDispatchingStorageUploadFileOperation: AmplifyInProcessReportingOperation<
|
|
StorageUploadFileRequest,
|
|
Progress,
|
|
String,
|
|
StorageError
|
|
>, StorageUploadFileOperation {
|
|
init(request: Request, progressListener: ProgressListener? = nil, resultListener: ResultListener? = nil) {
|
|
super.init(categoryType: .storage,
|
|
eventName: HubPayload.EventName.Storage.uploadFile,
|
|
request: request,
|
|
inProcessListener: progressListener,
|
|
resultListener: resultListener)
|
|
}
|
|
|
|
func doMockDispatch() {
|
|
super.dispatch(result: .success("Done"))
|
|
}
|
|
|
|
func doMockProgress() {
|
|
super.dispatchInProcess(data: Progress(totalUnitCount: 1))
|
|
}
|
|
}
|
|
|
|
class NonListeningStorageListOperation: AmplifyOperation<
|
|
StorageListRequest,
|
|
StorageListResult,
|
|
StorageError
|
|
>, StorageListOperation {
|
|
init(request: Request) {
|
|
super.init(categoryType: .storage,
|
|
eventName: HubPayload.EventName.Storage.downloadFile,
|
|
request: request)
|
|
}
|
|
}
|