diff --git a/WultraMobileTokenSDKTests/IntegrationTests.swift b/WultraMobileTokenSDKTests/IntegrationTests.swift index 1302390..be55130 100644 --- a/WultraMobileTokenSDKTests/IntegrationTests.swift +++ b/WultraMobileTokenSDKTests/IntegrationTests.swift @@ -91,6 +91,27 @@ class IntegrationTests: XCTestCase { waitForExpectations(timeout: 20, handler: nil) } + + /// Test of the getOperations WMTCancellable + func testCancelList() { + let exp = expectation(description: "Cancel list of operations") + + let list = ops.getOperations { result in + XCTFail("Operation should be already canceled") + exp.fulfill() + } + + list.cancel() + + // Allowing most of the timeout duration for potential completion of the getOperations call. + DispatchQueue.main.asyncAfter(deadline: .now() + 4) { + XCTAssertTrue(list.isCanceled, "WMTCancellable should be cancelled") + exp.fulfill() + } + + waitForExpectations(timeout: 5, handler: nil) + } + /// Operation IDs should be equal func testDetail() { let exp = expectation(description: "Operation detail") @@ -117,6 +138,37 @@ class IntegrationTests: XCTestCase { waitForExpectations(timeout: 20, handler: nil) } + /// Test of the Operation cancel + func testDetailCancel() { + let exp = expectation(description: "Cancel operation detail") + + proxy.createNonPersonalisedPACOperation { op in + if let op { + DispatchQueue.main.async { + guard let operation = self.ops.getDetail(operationId: op.operationId, completion: { _ in + XCTFail("Operation should be already canceled") + exp.fulfill() + }) else { + XCTFail("Failed to create operation") + exp.fulfill() + return + } + + operation.cancel() + + // Allowing most of the timeout duration for potential completion of the getDetail call. + DispatchQueue.main.asyncAfter(deadline: .now() + 4) { + XCTAssertTrue(operation.isCancelled, "Operation should be cancelled") + exp.fulfill() + } + } + } + } + + // Wait for expectation to be fulfilled + waitForExpectations(timeout: 5, handler: nil) + } + /// Operation IDs should be equal func testClaim() { let exp = expectation(description: "Operation Claim should return UserOperation with operation.id") diff --git a/docs/Using-Operations-Service.md b/docs/Using-Operations-Service.md index 12bc4d2..cf448ae 100644 --- a/docs/Using-Operations-Service.md +++ b/docs/Using-Operations-Service.md @@ -9,6 +9,8 @@ - [Reject an Operation](#reject-an-operation) - [Operation detail](#operation-detail) - [Claim the Operation](#claim-the-operation) +- [Operation History](#operation-history) +- [Cancelling Operations](#cancelling-operations) - [Off-line Authorization](#off-line-authorization) - [Operations API Reference](#operations-api-reference) - [WMTUserOperation](#wmtuseroperation) @@ -300,6 +302,21 @@ func history(password: String) { Note that the operation history availability depends on the backend implementation and might not be available. Please consult this with your backend developers. +## Cancelling Operations + +Additionally, please note that WMTCancellable or Operation objects retrieved from the Operations Service methods (getOperations, getHistory, getDetail, claim, authorize and reject) can be canceled using the cancel() method. This allows you to interrupt ongoing operations as needed. + +You can do so as shown below: + +```swift + let list = operationsService.getOperations { _ in } + list.cancel() + +``` + +For more examples refer to `IntegrationTests` in this repository. + + ## Off-line Authorization In case the user is not online, you can use off-line authorizations. In this operation mode, the user needs to scan a QR code, enter a PIN code, or use biometry, and rewrite the resulting code. Wultra provides a special format for [the operation QR codes](https://github.com/wultra/powerauth-webflow/blob/develop/docs/Off-line-Signatures-QR-Code.md), that is automatically processed with the SDK.