diff --git a/BankSDK/GiniBankSDKPinningExample/Tests/Resources/result_Gini_invoice_example.json b/BankSDK/GiniBankSDKPinningExample/Tests/Resources/result_Gini_invoice_example.json index 6f297124c..4fe4f8a2e 100644 --- a/BankSDK/GiniBankSDKPinningExample/Tests/Resources/result_Gini_invoice_example.json +++ b/BankSDK/GiniBankSDKPinningExample/Tests/Resources/result_Gini_invoice_example.json @@ -155,4 +155,4 @@ } ] } -} \ No newline at end of file +} diff --git a/HealthAPILibrary/GiniHealthAPILibrary/Sources/GiniHealthAPILibrary/Documents/Core/GiniHealthAPI.swift b/HealthAPILibrary/GiniHealthAPILibrary/Sources/GiniHealthAPILibrary/Documents/Core/GiniHealthAPI.swift index 130a1d478..aa4a2eee8 100644 --- a/HealthAPILibrary/GiniHealthAPILibrary/Sources/GiniHealthAPILibrary/Documents/Core/GiniHealthAPI.swift +++ b/HealthAPILibrary/GiniHealthAPILibrary/Sources/GiniHealthAPILibrary/Documents/Core/GiniHealthAPI.swift @@ -10,8 +10,8 @@ import Foundation /// The Gini Health API Library public final class GiniHealthAPI { - private let docService: DocumentService! - private let payService: PaymentService? + private var docService: DocumentService! + private var payService: PaymentService? static var logLevel: LogLevel = .none public var sessionDelegate: URLSessionDelegate? = nil diff --git a/HealthAPILibrary/GiniHealthAPILibrary/Sources/GiniHealthAPILibrary/Documents/Document.swift b/HealthAPILibrary/GiniHealthAPILibrary/Sources/GiniHealthAPILibrary/Documents/Document.swift index 1b6f6de5d..e347b5767 100644 --- a/HealthAPILibrary/GiniHealthAPILibrary/Sources/GiniHealthAPILibrary/Documents/Document.swift +++ b/HealthAPILibrary/GiniHealthAPILibrary/Sources/GiniHealthAPILibrary/Documents/Document.swift @@ -271,3 +271,9 @@ extension Document.Links: Decodable { extension Document.Layout: Decodable { } + +extension Document: Equatable { + public static func == (lhs: Document, rhs: Document) -> Bool { + lhs.id == rhs.id + } +} diff --git a/HealthAPILibrary/GiniHealthAPILibrary/Sources/GiniHealthAPILibrary/Documents/ExtractionsContainer.swift b/HealthAPILibrary/GiniHealthAPILibrary/Sources/GiniHealthAPILibrary/Documents/ExtractionsContainer.swift index 4acc857cc..3f9726ee1 100644 --- a/HealthAPILibrary/GiniHealthAPILibrary/Sources/GiniHealthAPILibrary/Documents/ExtractionsContainer.swift +++ b/HealthAPILibrary/GiniHealthAPILibrary/Sources/GiniHealthAPILibrary/Documents/ExtractionsContainer.swift @@ -7,7 +7,7 @@ import Foundation -struct ExtractionsContainer { +public struct ExtractionsContainer { let extractions: [Extraction] let compoundExtractions: [String : [[Extraction]]]? let candidates: [Extraction.Candidate] @@ -23,7 +23,7 @@ struct ExtractionsContainer { extension ExtractionsContainer: Decodable { - init(from decoder: Decoder) throws { + public init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) let decodedExtractions = try container.decode([String : Extraction].self, diff --git a/HealthAPILibrary/GiniHealthAPILibrary/Sources/GiniHealthAPILibrary/Documents/Payments/PaymentProvider.swift b/HealthAPILibrary/GiniHealthAPILibrary/Sources/GiniHealthAPILibrary/Documents/Payments/PaymentProvider.swift index 0bba0d629..810459f41 100644 --- a/HealthAPILibrary/GiniHealthAPILibrary/Sources/GiniHealthAPILibrary/Documents/Payments/PaymentProvider.swift +++ b/HealthAPILibrary/GiniHealthAPILibrary/Sources/GiniHealthAPILibrary/Documents/Payments/PaymentProvider.swift @@ -14,7 +14,7 @@ public struct PaymentProvider: Codable { public var name: String public var appSchemeIOS: String public var colors: ProviderColors - var minAppVersion: MinAppVersions? + public var minAppVersion: MinAppVersions? public var iconData: Data public var appStoreUrlIOS: String? public var universalLinkIOS: String @@ -31,3 +31,9 @@ public struct PaymentProvider: Codable { } } public typealias PaymentProviders = [PaymentProvider] + +extension PaymentProvider: Equatable { + public static func == (lhs: PaymentProvider, rhs: PaymentProvider) -> Bool { + lhs.id == rhs.id + } +} diff --git a/HealthAPILibrary/GiniHealthAPILibrary/Sources/GiniHealthAPILibrary/Documents/Payments/PaymentProviderResponse.swift b/HealthAPILibrary/GiniHealthAPILibrary/Sources/GiniHealthAPILibrary/Documents/Payments/PaymentProviderResponse.swift index e4794f3d3..44f8f9049 100644 --- a/HealthAPILibrary/GiniHealthAPILibrary/Sources/GiniHealthAPILibrary/Documents/Payments/PaymentProviderResponse.swift +++ b/HealthAPILibrary/GiniHealthAPILibrary/Sources/GiniHealthAPILibrary/Documents/Payments/PaymentProviderResponse.swift @@ -38,7 +38,7 @@ public struct PaymentProviderResponse: Codable { public var name: String public var appSchemeIOS: String public var colors: ProviderColors - var minAppVersion: MinAppVersions? + public var minAppVersion: MinAppVersions? public var iconLocation: String public var appStoreUrlIOS: String? public var universalLinkIOS: String diff --git a/HealthSDK/GiniHealthSDK/Package.swift b/HealthSDK/GiniHealthSDK/Package.swift index 4fbfd6c86..97dc45c13 100644 --- a/HealthSDK/GiniHealthSDK/Package.swift +++ b/HealthSDK/GiniHealthSDK/Package.swift @@ -27,6 +27,9 @@ let package = Package( dependencies: ["GiniHealthAPILibrary"]), .testTarget( name: "GiniHealthSDKTests", - dependencies: ["GiniHealthSDK"]), + dependencies: ["GiniHealthSDK"], + resources: [ + .process("Resources") + ]), ] ) diff --git a/HealthSDK/GiniHealthSDK/Sources/GiniHealthSDK/Core/GiniHealth.swift b/HealthSDK/GiniHealthSDK/Sources/GiniHealthSDK/Core/GiniHealth.swift index a9f814560..2f6bc3973 100644 --- a/HealthSDK/GiniHealthSDK/Sources/GiniHealthSDK/Core/GiniHealth.swift +++ b/HealthSDK/GiniHealthSDK/Sources/GiniHealthSDK/Core/GiniHealth.swift @@ -41,6 +41,8 @@ public enum GiniHealthError: Error { /// Error thrown when api didn't returns payment extractions. case noPaymentDataExtracted } + +extension GiniHealthError: Equatable {} /** Data structure for Payment Review Screen initialization. */ @@ -169,7 +171,9 @@ public struct DataForReview { switch result { case let .success(extractionResult): if let paymentExtractions = extractionResult.payment?.first, let iban = paymentExtractions.first(where: { $0.name == "iban" })?.value, !iban.isEmpty { - completion(.success(true)) + completion(.success(true)) + } else if let ibanExtraction = extractionResult.extractions.first(where: { $0.name == "iban"})?.value, !ibanExtraction.isEmpty { + completion(.success(true)) } else { completion(.success(false)) } @@ -220,32 +224,32 @@ public struct DataForReview { */ public func getExtractions(docId: String, completion: @escaping (Result<[Extraction], GiniHealthError>) -> Void){ - documentService.fetchDocument(with: docId) { result in - switch result { - case let .success(createdDocument): - self.documentService - .extractions(for: createdDocument, - cancellationToken: CancellationToken()) { result in - DispatchQueue.main.async { - switch result { - case let .success(extractionResult): - if let paymentExtractionsContainer = extractionResult.payment, let paymentExtractions = paymentExtractionsContainer.first { - completion(.success(paymentExtractions)) - } else { - completion(.failure(.noPaymentDataExtracted)) - } - case let .failure(error): - completion(.failure(.apiError(error))) + documentService.fetchDocument(with: docId) { result in + switch result { + case let .success(createdDocument): + self.documentService + .extractions(for: createdDocument, + cancellationToken: CancellationToken()) { result in + DispatchQueue.main.async { + switch result { + case let .success(extractionResult): + if let paymentExtractionsContainer = extractionResult.payment, let paymentExtractions = paymentExtractionsContainer.first { + completion(.success(paymentExtractions)) + } else { + completion(.failure(.noPaymentDataExtracted)) } + case let .failure(error): + completion(.failure(.apiError(error))) } } - case let .failure(error): - DispatchQueue.main.async { - completion(.failure(.apiError(error))) - } + } + case let .failure(error): + DispatchQueue.main.async { + completion(.failure(.apiError(error))) } } } + } /** Creates a payment request @@ -279,16 +283,15 @@ public struct DataForReview { - Parameters: - requestID: Id of the created payment request. - universalLink: Universal link for the selected payment provider - */ - public func openPaymentProviderApp(requestID: String, universalLink: String) { + public func openPaymentProviderApp(requestID: String, universalLink: String, urlOpener: URLOpener = URLOpener(UIApplication.shared), completion: ((Bool) -> Void)? = nil) { let queryItems = [URLQueryItem(name: "id", value: requestID)] let urlString = universalLink + "://payment" var urlComponents = URLComponents(string: urlString)! urlComponents.queryItems = queryItems let resultUrl = urlComponents.url! DispatchQueue.main.async { - UIApplication.shared.open(resultUrl, options: [:], completionHandler: nil) + urlOpener.openLink(url: resultUrl, completion: completion) } } @@ -365,3 +368,4 @@ public struct DataForReview { } } } + diff --git a/HealthSDK/GiniHealthSDK/Sources/GiniHealthSDK/Core/PaymentComponent/PaymentComponentsController.swift b/HealthSDK/GiniHealthSDK/Sources/GiniHealthSDK/Core/PaymentComponent/PaymentComponentsController.swift index 8867641aa..fb9c88040 100644 --- a/HealthSDK/GiniHealthSDK/Sources/GiniHealthSDK/Core/PaymentComponent/PaymentComponentsController.swift +++ b/HealthSDK/GiniHealthSDK/Sources/GiniHealthSDK/Core/PaymentComponent/PaymentComponentsController.swift @@ -16,10 +16,21 @@ public protocol PaymentComponentsControllerProtocol: AnyObject { func didFetchedPaymentProviders() } +protocol PaymentComponentsProtocol { + var isLoading: Bool { get set } + var selectedPaymentProvider: PaymentProvider? { get set } + func loadPaymentProviders() + func checkIfDocumentIsPayable(docId: String, completion: @escaping (Result) -> Void) + func paymentView(documentId: String) -> UIView + func bankSelectionBottomSheet() -> UIViewController + func loadPaymentReviewScreenFor(documentID: String, trackingDelegate: GiniHealthTrackingDelegate?, completion: @escaping (UIViewController?, GiniHealthError?) -> Void) + func paymentInfoViewController() -> UIViewController +} + /** The `PaymentComponentsController` class allows control over the payment components. */ -public final class PaymentComponentsController: NSObject { +public final class PaymentComponentsController: PaymentComponentsProtocol { /// handling the Payment Component Controller delegate public weak var delegate: PaymentComponentsControllerProtocol? /// handling the Payment Component view delegate @@ -53,7 +64,6 @@ public final class PaymentComponentsController: NSObject { */ public init(giniHealth: GiniHealth) { self.giniHealth = giniHealth - super.init() setupListeners() } diff --git a/HealthSDK/GiniHealthSDK/Sources/GiniHealthSDK/Core/URLOpener.swift b/HealthSDK/GiniHealthSDK/Sources/GiniHealthSDK/Core/URLOpener.swift new file mode 100644 index 000000000..3a0f1f8dd --- /dev/null +++ b/HealthSDK/GiniHealthSDK/Sources/GiniHealthSDK/Core/URLOpener.swift @@ -0,0 +1,39 @@ +// +// URLOpener.swift +// +// Copyright © 2024 Gini GmbH. All rights reserved. +// + +import UIKit + +// URLOpener helper structure for better testing of the open AppStore links functionality +public struct URLOpener { + private let application: URLOpenerProtocol + + public init(_ application: URLOpenerProtocol) { + self.application = application + } + + /// Opens AppStore with the provided URL + /// + /// - Parameters: + /// - url: link that will be opened + /// - completion: called after opening is completed + /// param is true if website was opened successfully + /// param is false if opening failed + + func openLink(url: URL, completion: ((Bool) -> Void)?) { + if application.canOpenURL(url) { + application.open(url, options: [:], completionHandler: completion) + } else { + completion?(false) + } + } +} + +public protocol URLOpenerProtocol { + func canOpenURL(_ url: URL) -> Bool + func open(_ url: URL, options: [UIApplication.OpenExternalURLOptionsKey : Any], completionHandler completion: ((Bool) -> Void)?) +} + +extension UIApplication: URLOpenerProtocol {} diff --git a/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/GiniHealthTests.swift b/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/GiniHealthTests.swift new file mode 100644 index 000000000..7469a0898 --- /dev/null +++ b/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/GiniHealthTests.swift @@ -0,0 +1,359 @@ +import XCTest +@testable import GiniHealthSDK +@testable import GiniHealthAPILibrary + +final class GiniHealthTests: XCTestCase { + + var giniHealthAPI: GiniHealthAPI! + var giniHealth: GiniHealth! + + override func setUp() { + let sessionManagerMock = MockSessionManager() + let documentService = DefaultDocumentService(sessionManager: sessionManagerMock) + let paymentService = PaymentService(sessionManager: sessionManagerMock) + giniHealthAPI = GiniHealthAPI(documentService: documentService, paymentService: paymentService) + giniHealth = GiniHealth(with: giniHealthAPI) + } + + override func tearDown() { + giniHealth = nil + super.tearDown() + } + + func testSetConfiguration() throws { + // Given + let configuration = GiniHealthConfiguration() + + // When + giniHealth.setConfiguration(configuration) + + // Then + XCTAssertEqual(GiniHealthConfiguration.shared, configuration) + } + + func testFetchBankingApps_Success() { + // Given + let expectedProviders: [PaymentProvider]? = loadProviders() + + // When + let expectation = self.expectation(description: "Fetching banking apps") + var receivedProviders: [PaymentProvider]? + giniHealth.fetchBankingApps { result in + switch result { + case .success(let providers): + receivedProviders = providers + case .failure(_): + receivedProviders = nil + } + expectation.fulfill() + } + waitForExpectations(timeout: 1, handler: nil) + + // Then + XCTAssertNotNil(receivedProviders) + XCTAssertEqual(receivedProviders?.count, expectedProviders?.count) + XCTAssertEqual(receivedProviders, expectedProviders) + } + + func testCheckIfDocumentIsPayable_Success() { + // Given + let fileName = "extractionResultWithIBAN" + let expectedExtractions: ExtractionsContainer? = GiniHealthSDKTests.load(fromFile: fileName) + guard let expectedExtractions else { + XCTFail("Error loading file: `\(fileName).json`") + return + } + let expectedExtractionsResult = ExtractionResult(extractionsContainer: expectedExtractions) + let expectedIsPayable = expectedExtractionsResult.extractions.first(where: { $0.name == "iban" })?.value.isNotEmpty + + // When + let expectation = self.expectation(description: "Checking if document is payable") + var isDocumentPayable: Bool? + giniHealth.checkIfDocumentIsPayable(docId: MockSessionManager.payableDocumentID) { result in + switch result { + case .success(let isPayable): + isDocumentPayable = isPayable + case .failure(_): + isDocumentPayable = nil + } + expectation.fulfill() + } + waitForExpectations(timeout: 1, handler: nil) + + // Then + XCTAssertEqual(expectedIsPayable, isDocumentPayable) + } + + func testCheckIfDocumentIsNotPayable_Success() { + // Given + let fileName = "extractionResultWithIBAN" + let expectedExtractions: ExtractionsContainer? = GiniHealthSDKTests.load(fromFile: fileName) + guard let expectedExtractions else { + XCTFail("Error loading file: `\(fileName).json`") + return + } + let expectedExtractionsResult = ExtractionResult(extractionsContainer: expectedExtractions) + let expectedIsPayable = expectedExtractionsResult.extractions.first(where: { $0.name == "iban" })?.value.isEmpty + + // When + let expectation = self.expectation(description: "Checking if document is not payable") + var isDocumentPayable: Bool? + giniHealth.checkIfDocumentIsPayable(docId: MockSessionManager.notPayableDocumentID) { result in + switch result { + case .success(let isPayable): + isDocumentPayable = isPayable + case .failure(_): + isDocumentPayable = nil + } + expectation.fulfill() + } + waitForExpectations(timeout: 1, handler: nil) + + // Then + XCTAssertEqual(expectedIsPayable, isDocumentPayable) + } + + func testCheckIfDocumentIsPayable_Failure() { + // When + let expectation = self.expectation(description: "Checking if request fails") + var isDocumentPayable: Bool? + giniHealth.checkIfDocumentIsPayable(docId: MockSessionManager.failurePayableDocumentID) { result in + switch result { + case .success(let isPayable): + isDocumentPayable = isPayable + case .failure(_): + isDocumentPayable = nil + } + expectation.fulfill() + } + waitForExpectations(timeout: 1, handler: nil) + + // Then + XCTAssertNil(isDocumentPayable) + } + + func testPollDocument_Success() { + // Given + let expectedDocument: Document? = GiniHealthSDKTests.load(fromFile: "document1") + + // When + let expectation = self.expectation(description: "Polling document") + var receivedDocument: Document? + giniHealth.pollDocument(docId: MockSessionManager.payableDocumentID) { result in + switch result { + case .success(let document): + receivedDocument = document + case .failure(_): + receivedDocument = nil + } + expectation.fulfill() + } + waitForExpectations(timeout: 1, handler: nil) + + // Then + XCTAssertNotNil(receivedDocument) + XCTAssertEqual(receivedDocument, expectedDocument) + } + + func testPollDocument_Failure() { + // When + let expectation = self.expectation(description: "Polling failure document") + var receivedDocument: Document? + giniHealth.pollDocument(docId: MockSessionManager.missingDocumentID) { result in + switch result { + case .success(let document): + receivedDocument = document + case .failure(_): + receivedDocument = nil + } + expectation.fulfill() + } + waitForExpectations(timeout: 1, handler: nil) + + // Then + XCTAssertNil(receivedDocument) + } + + func testGetExtractions_Success() { + // Given + let fileName = "extractionsWithPayment" + let expectedExtractionContainer: ExtractionsContainer? = GiniHealthSDKTests.load(fromFile: fileName) + guard let expectedExtractionContainer else { + XCTFail("Error loading file: `\(fileName).json`") + return + } + let expectedExtractions: [Extraction] = ExtractionResult(extractionsContainer: expectedExtractionContainer).payment?.first ?? [] + + // When + let expectation = self.expectation(description: "Getting extractions") + var receivedExtractions: [Extraction]? + giniHealth.getExtractions(docId: MockSessionManager.extractionsWithPaymentDocumentID) { result in + switch result { + case .success(let extractions): + receivedExtractions = extractions + case .failure(_): + receivedExtractions = nil + } + expectation.fulfill() + } + waitForExpectations(timeout: 1, handler: nil) + + // Then + XCTAssertNotNil(receivedExtractions) + XCTAssertEqual(receivedExtractions?.count, expectedExtractions.count) + } + + func testGetExtractions_Failure() { + // When + let expectation = self.expectation(description: "Extraction failure") + var receivedExtractions: [Extraction]? + giniHealth.getExtractions(docId: MockSessionManager.failurePayableDocumentID) { result in + switch result { + case .success(let extractions): + receivedExtractions = extractions + case .failure(_): + receivedExtractions = nil + } + expectation.fulfill() + } + waitForExpectations(timeout: 1, handler: nil) + + // Then + XCTAssertNil(receivedExtractions) + } + + func testCreatePaymentRequest_Success() { + // Given + let expectedPaymentRequestID = MockSessionManager.paymentRequestId + + // When + let expectation = self.expectation(description: "Creating payment request") + var receivedRequestId: String? + let paymentInfo = PaymentInfo(recipient: "Uno Flüchtlingshilfe", iban: "DE78370501980020008850", bic: "COLSDE33", amount: "1.00:EUR", purpose: "ReNr 12345", paymentUniversalLink: "ginipay-test://paymentRequester", paymentProviderId: "b09ef70a-490f-11eb-952e-9bc6f4646c57") + giniHealth.createPaymentRequest(paymentInfo: paymentInfo, completion: { result in + switch result { + case .success(let requestId): + receivedRequestId = requestId + case .failure(_): + receivedRequestId = nil + } + expectation.fulfill() + }) + waitForExpectations(timeout: 1, handler: nil) + + // Then + XCTAssertNotNil(receivedRequestId) + XCTAssertEqual(receivedRequestId, expectedPaymentRequestID) + } + + func testOpenLink_Success() { + let mockUIApplication = MockUIApplication(canOpen: true) + let urlOpener = URLOpener(mockUIApplication) + let waitForWebsiteOpen = expectation(description: "Link was opened") + + giniHealth.openPaymentProviderApp(requestID: "123", universalLink: "ginipay-bank://", urlOpener: urlOpener, completion: { open in + waitForWebsiteOpen.fulfill() + XCTAssert(open == true, "testOpenLink - FAILED to open link") + }) + + waitForExpectations(timeout: 0.1, handler: nil) + } + + func testOpenLink_Failure() { + let mockUIApplication = MockUIApplication(canOpen: false) + let urlOpener = URLOpener(mockUIApplication) + let waitForWebsiteOpen = expectation(description: "Link was not opened") + + giniHealth.openPaymentProviderApp(requestID: "123", universalLink: "ginipay-bank://", urlOpener: urlOpener, completion: { open in + waitForWebsiteOpen.fulfill() + XCTAssert(open == false, "testOpenLink - MANAGED to open link") + }) + + waitForExpectations(timeout: 0.1, handler: nil) + } + + func testSetDocumentForReview_Success() { + // Given + let fileName = "extractionsWithPayment" + let expectedExtractionContainer: ExtractionsContainer? = GiniHealthSDKTests.load(fromFile: fileName) + guard let expectedExtractionContainer else { + XCTFail("Error loading file: `\(fileName).json`") + return + } + let expectedExtractions: [Extraction] = ExtractionResult(extractionsContainer: expectedExtractionContainer).payment?.first ?? [] + + // When + let expectation = self.expectation(description: "Setting document for review") + var receivedExtractions: [Extraction]? + giniHealth.setDocumentForReview(documentId: MockSessionManager.extractionsWithPaymentDocumentID) { result in + switch result { + case .success(let extractions): + receivedExtractions = extractions + case .failure(_): + receivedExtractions = nil + } + expectation.fulfill() + } + waitForExpectations(timeout: 1, handler: nil) + + // Then + XCTAssertNotNil(receivedExtractions) + XCTAssertEqual(receivedExtractions?.count, expectedExtractions.count) + } + + func testFetchDataForReview_Success() { + // Given + let fileName = "extractionsWithPayment" + let expectedExtractionContainer: ExtractionsContainer? = GiniHealthSDKTests.load(fromFile: fileName) + guard let expectedExtractionContainer else { + XCTFail("Error loading file: `\(fileName).json`") + return + } + let expectedExtractions: [Extraction] = ExtractionResult(extractionsContainer: expectedExtractionContainer).payment?.first ?? [] + let documentFileName = "document4" + let expectedDocument: Document? = GiniHealthSDKTests.load(fromFile: documentFileName) + guard let expectedDocument else { + XCTFail("Error loading file: `\(documentFileName).json`") + return + } + let expectedDatForReview = DataForReview(document: expectedDocument, extractions: expectedExtractions) + + // When + let expectation = self.expectation(description: "Fetching data for review") + var receivedDataForReview: DataForReview? + giniHealth.fetchDataForReview(documentId: MockSessionManager.extractionsWithPaymentDocumentID) { result in + switch result { + case .success(let dataForReview): + receivedDataForReview = dataForReview + case .failure(_): + receivedDataForReview = nil + } + expectation.fulfill() + } + waitForExpectations(timeout: 1, handler: nil) + + // Then + XCTAssertNotNil(receivedDataForReview) + XCTAssertEqual(receivedDataForReview?.document, expectedDatForReview.document) + XCTAssertEqual(receivedDataForReview?.extractions.count, expectedDatForReview.extractions.count) + } + + func testFetchDataForReview_Failure() { + // When + let expectation = self.expectation(description: "Failure fetching data for review") + var receivedError: GiniHealthError? + giniHealth.fetchDataForReview(documentId: MockSessionManager.missingDocumentID) { result in + switch result { + case .success(_): + receivedError = nil + case .failure(let error): + receivedError = error + } + expectation.fulfill() + } + waitForExpectations(timeout: 1, handler: nil) + + // Then + XCTAssertNotNil(receivedError) + } +} diff --git a/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/HealthSDKTests.swift b/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/HealthSDKTests.swift deleted file mode 100644 index 2a33e28e4..000000000 --- a/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/HealthSDKTests.swift +++ /dev/null @@ -1,7 +0,0 @@ -import XCTest -@testable import GiniHealthSDK - -final class HealthSDKTests: XCTestCase { - func testExample() throws { - } -} diff --git a/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/MockHelpers/FileLoader.swift b/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/MockHelpers/FileLoader.swift new file mode 100644 index 000000000..12f798ee0 --- /dev/null +++ b/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/MockHelpers/FileLoader.swift @@ -0,0 +1,28 @@ +// +// FileLoader.swift +// +// Copyright © 2024 Gini GmbH. All rights reserved. +// + + +import Foundation + +import Foundation + +struct FileLoader { + static func loadFile(withName mockFileName: String, ofType fileType: String) -> Data? { + guard let filePath = Bundle.module.path(forResource: mockFileName, ofType: fileType) else { + print("File not found.") + return nil + } + + let fileURL = URL(fileURLWithPath: filePath) + do { + let data = try Data(contentsOf: fileURL) + return data + } catch { + print("Error loading file:", error) + return nil + } + } +} diff --git a/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/MockHelpers/MockPaymentComponents.swift b/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/MockHelpers/MockPaymentComponents.swift new file mode 100644 index 000000000..e299b6cff --- /dev/null +++ b/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/MockHelpers/MockPaymentComponents.swift @@ -0,0 +1,83 @@ +// +// MockPaymentComponentsController.swift +// +// Copyright © 2024 Gini GmbH. All rights reserved. +// + + +import UIKit +@testable import GiniHealthSDK +@testable import GiniHealthAPILibrary + +class MockPaymentComponents: PaymentComponentsProtocol { + + var isLoading: Bool = false + var selectedPaymentProvider: PaymentProvider? + + private var giniHealth: GiniHealth + private var paymentProviders: PaymentProviders = [] + private var installedPaymentProviders: PaymentProviders = [] + + init(giniHealthSDK: GiniHealth) { + self.giniHealth = giniHealthSDK + } + + func loadPaymentProviders() { + isLoading = false + guard let paymentProviderResponse: PaymentProviderResponse = load(fromFile: "provider") else { + return + } + if let iconData = Data(url: URL(string: paymentProviderResponse.iconLocation)) { + selectedPaymentProvider = PaymentProvider(id: paymentProviderResponse.id, name: paymentProviderResponse.name, appSchemeIOS: paymentProviderResponse.appSchemeIOS, minAppVersion: paymentProviderResponse.minAppVersion, colors: paymentProviderResponse.colors, iconData: iconData, appStoreUrlIOS: paymentProviderResponse.appStoreUrlIOS, universalLinkIOS: paymentProviderResponse.universalLinkIOS) + } + } + + func checkIfDocumentIsPayable(docId: String, completion: @escaping (Result) -> Void) { + switch docId { + case MockSessionManager.payableDocumentID: + completion(.success(true)) + case MockSessionManager.notPayableDocumentID: + completion(.success(false)) + case MockSessionManager.missingDocumentID: + completion(.failure(.apiError(.noResponse))) + default: + fatalError("Document id not handled in tests") + } + } + + func paymentView(documentId: String) -> UIView { + let viewModel = PaymentComponentViewModel(paymentProvider: selectedPaymentProvider) + viewModel.documentId = documentId + let view = PaymentComponentView() + view.viewModel = viewModel + return view + } + + func bankSelectionBottomSheet() -> UIViewController { + let paymentProvidersBottomView = BanksBottomView() + let paymentProvidersBottomViewModel = BanksBottomViewModel(paymentProviders: paymentProviders, + selectedPaymentProvider: selectedPaymentProvider) + paymentProvidersBottomView.viewModel = paymentProvidersBottomViewModel + let bankSelectionBottomSheet = BankSelectionBottomSheet() + bankSelectionBottomSheet.bottomSheet = paymentProvidersBottomView + return bankSelectionBottomSheet + } + + func loadPaymentReviewScreenFor(documentID: String, trackingDelegate: (any GiniHealthTrackingDelegate)?, completion: @escaping (UIViewController?, GiniHealthError?) -> Void) { + switch documentID { + case MockSessionManager.payableDocumentID: + completion(PaymentReviewViewController(), nil) + case MockSessionManager.missingDocumentID: + completion(nil, .apiError(.noResponse)) + default: + fatalError("Document id not handled in tests") + } + } + + func paymentInfoViewController() -> UIViewController { + let paymentInfoViewController = PaymentInfoViewController() + let paymentInfoViewModel = PaymentInfoViewModel(paymentProviders: paymentProviders) + paymentInfoViewController.viewModel = paymentInfoViewModel + return paymentInfoViewController + } +} diff --git a/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/MockHelpers/MockSessionManager.swift b/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/MockHelpers/MockSessionManager.swift new file mode 100644 index 000000000..0f7978c2c --- /dev/null +++ b/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/MockHelpers/MockSessionManager.swift @@ -0,0 +1,118 @@ +// +// MockSessionManage.swift +// +// Copyright © 2024 Gini GmbH. All rights reserved. +// + + +import UIKit +@testable import GiniHealthAPILibrary + +final class MockSessionManager: SessionManagerProtocol { + static let payableDocumentID = "626626a0-749f-11e2-bfd6-000000000001" + static let notPayableDocumentID = "626626a0-749f-11e2-bfd6-000000000002" + static let failurePayableDocumentID = "626626a0-749f-11e2-bfd6-000000000003" + static let missingDocumentID = "626626a0-749f-11e2-bfd6-000000000000" + static let extractionsWithPaymentDocumentID = "626626a0-749f-11e2-bfd6-000000000004" + static let paymentRequestId = "b09ef70a-490f-11eb-952e-9bc6f4646c57" + + func upload(resource: T, data: Data, cancellationToken: GiniHealthAPILibrary.CancellationToken?, completion: @escaping GiniHealthAPILibrary.CompletionResult) where T : GiniHealthAPILibrary.Resource { + // + } + + func download(resource: T, cancellationToken: GiniHealthAPILibrary.CancellationToken?, completion: @escaping GiniHealthAPILibrary.CompletionResult) where T : GiniHealthAPILibrary.Resource { + if let apiMethod = resource.method as? APIMethod { + switch apiMethod { + case .file(_): + let imageData = UIImage(named: "Gini-Test-Payment-Provider", in: Bundle.module, compatibleWith: nil)?.pngData() + if let imageData = imageData as? T.ResponseType { + completion(.success(imageData)) + } + default: + break + } + } + } + + func logIn(completion: @escaping (Result) -> Void) { + // + } + + func logOut() { + // + } + + func data(resource: T, cancellationToken: GiniHealthAPILibrary.CancellationToken?, completion: @escaping GiniHealthAPILibrary.CompletionResult) where T : GiniHealthAPILibrary.Resource { + if let apiMethod = resource.method as? APIMethod { + switch apiMethod { + case .document(let id): + switch (id, resource.params.method) { + case (MockSessionManager.payableDocumentID, .get): + let document: Document? = load(fromFile: "document1", type: "json") + if let document = document as? T.ResponseType { + completion(.success(document)) + } + case (MockSessionManager.notPayableDocumentID, .get): + let document: Document? = load(fromFile: "document2", type: "json") + if let document = document as? T.ResponseType { + completion(.success(document)) + } + case (MockSessionManager.failurePayableDocumentID, .get): + let document: Document? = load(fromFile: "document3", type: "json") + if let document = document as? T.ResponseType { + completion(.success(document)) + } + case (MockSessionManager.missingDocumentID, .get): + completion(.failure(.notFound(response: nil, data: nil))) + case (MockSessionManager.extractionsWithPaymentDocumentID, .get): + let document: Document? = load(fromFile: "document4", type: "json") + if let document = document as? T.ResponseType { + completion(.success(document)) + } + default: + fatalError("Document id not found in tests") + } + case .createPaymentRequest: + if let paymentRequestId = MockSessionManager.paymentRequestId as? T.ResponseType { + completion(.success(paymentRequestId)) + } + case .paymentProvider(_): + let providerResponse: PaymentProviderResponse? = load(fromFile: "provider") + if let providerResponse = providerResponse as? T.ResponseType { + completion(.success(providerResponse)) + } + case .paymentProviders: + let paymentProvidersResponse: [PaymentProviderResponse]? = load(fromFile: "providers") + if let paymentProvidersResponse = paymentProvidersResponse as? T.ResponseType { + completion(.success(paymentProvidersResponse)) + } + case .extractions(let documentId): + switch (documentId, resource.params.method) { + case (MockSessionManager.payableDocumentID, .get): + let extractionResults: ExtractionsContainer? = load(fromFile: "extractionResultWithIBAN") + if let extractionResults = extractionResults as? T.ResponseType { + completion(.success(extractionResults)) + } + case (MockSessionManager.notPayableDocumentID, .get): + let extractionResults: ExtractionsContainer? = load(fromFile: "extractionResultWithoutIBAN") + if let extractionResults = extractionResults as? T.ResponseType { + completion(.success(extractionResults)) + } + case (MockSessionManager.failurePayableDocumentID, .get): + completion(.failure(.noResponse)) + case (MockSessionManager.extractionsWithPaymentDocumentID, .get): + let extractionResults: ExtractionsContainer? = load(fromFile: "extractionsWithPayment") + if let extractionResults = extractionResults as? T.ResponseType { + completion(.success(extractionResults)) + } + default: + fatalError("Document id not found in tests") + } + default: + let error = GiniError.unknown(response: nil, data: nil) + completion(.failure(error)) + } + } + } +} + diff --git a/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/MockHelpers/MockUIApplication.swift b/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/MockHelpers/MockUIApplication.swift new file mode 100644 index 000000000..9bea4e08b --- /dev/null +++ b/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/MockHelpers/MockUIApplication.swift @@ -0,0 +1,23 @@ +// +// MockUIApplication.swift +// +// Copyright © 2024 Gini GmbH. All rights reserved. +// + + +import UIKit +@testable import GiniHealthSDK + +struct MockUIApplication: URLOpenerProtocol { + var canOpen: Bool + + func canOpenURL(_ url: URL) -> Bool { + return canOpen + } + + func open(_ url: URL, options: [UIApplication.OpenExternalURLOptionsKey : Any], completionHandler completion: ((Bool) -> Void)?) { + if canOpen { + completion?(true) + } + } +} diff --git a/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/MockHelpers/Utils.swift b/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/MockHelpers/Utils.swift new file mode 100644 index 000000000..1f11a5b2f --- /dev/null +++ b/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/MockHelpers/Utils.swift @@ -0,0 +1,29 @@ +// +// Utils.swift +// +// Copyright © 2024 Gini GmbH. All rights reserved. +// + + +import UIKit +import GiniHealthAPILibrary + +func loadProviders() -> PaymentProviders? { + var providers: PaymentProviders = [] + let providersResponse: [PaymentProviderResponse]? = load(fromFile: "providers") + guard let providersResponse else { return nil } + for providerResponse in providersResponse { + let imageData = UIImage(named: "Gini-Test-Payment-Provider", in: Bundle.module, compatibleWith: nil)?.pngData() + let provider = PaymentProvider(id: providerResponse.id, name: providerResponse.name, appSchemeIOS: providerResponse.appSchemeIOS, minAppVersion: providerResponse.minAppVersion, colors: providerResponse.colors, iconData: imageData ?? Data(), appStoreUrlIOS: providerResponse.appStoreUrlIOS, universalLinkIOS: providerResponse.universalLinkIOS) + providers.append(provider) + } + return providers +} + +func load(fromFile named: String, type: String = "json") -> T? { + guard let jsonData = FileLoader.loadFile(withName: named, ofType: type) else { + return nil + } + + return try? JSONDecoder().decode(T.self, from: jsonData) +} diff --git a/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/PaymentComponentsControllerTests.swift b/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/PaymentComponentsControllerTests.swift new file mode 100644 index 000000000..a9bfa5bec --- /dev/null +++ b/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/PaymentComponentsControllerTests.swift @@ -0,0 +1,162 @@ +// +// PaymentComponentsControllerTests.swift +// +// Copyright © 2024 Gini GmbH. All rights reserved. +// + + +import XCTest +@testable import GiniHealthSDK +@testable import GiniHealthAPILibrary + +final class PaymentComponentsControllerTests: XCTestCase { + var giniHealthAPI: GiniHealthAPI! + var mockPaymentComponentsController: PaymentComponentsProtocol! + + override func setUp() { + super.setUp() + let sessionManagerMock = MockSessionManager() + let documentService = DefaultDocumentService(sessionManager: sessionManagerMock) + let paymentService = PaymentService(sessionManager: sessionManagerMock) + giniHealthAPI = GiniHealthAPI(documentService: documentService, paymentService: paymentService) + let giniHealth = GiniHealth(with: giniHealthAPI) + mockPaymentComponentsController = MockPaymentComponents(giniHealthSDK: giniHealth) + } + + override func tearDown() { + giniHealthAPI = nil + mockPaymentComponentsController = nil + super.tearDown() + } + + func testLoadPaymentProviders_Success() { + // When + mockPaymentComponentsController.loadPaymentProviders() + + // Then + XCTAssertFalse(mockPaymentComponentsController.isLoading) + XCTAssertNotNil(mockPaymentComponentsController.selectedPaymentProvider) + } + + func testCheckIfDocumentIsPayable_Success() { + let expectedResult: Result = .success(true) + // When + var receivedResult: Result? + mockPaymentComponentsController.checkIfDocumentIsPayable(docId: MockSessionManager.payableDocumentID) { result in + receivedResult = result + } + + // Then + XCTAssertEqual(receivedResult, expectedResult) + } + + func testCheckIfDocumentIsPayable_NotPayable() { + let expectedResult: Result = .success(false) + // When + var receivedResult: Result? + mockPaymentComponentsController.checkIfDocumentIsPayable(docId: MockSessionManager.notPayableDocumentID) { result in + receivedResult = result + } + + // Then + XCTAssertEqual(receivedResult, expectedResult) + } + + func testCheckIfDocumentIsPayable_Failure() { + let expectedResult: Result = .failure(.apiError(.noResponse)) + // When + var receivedResult: Result? + mockPaymentComponentsController.checkIfDocumentIsPayable(docId: MockSessionManager.missingDocumentID) { result in + receivedResult = result + } + + // Then + XCTAssertEqual(receivedResult, expectedResult) + } + + func testPaymentView_ReturnsView() { + // Given + let documentId = "123456" + let expectedViewModel = PaymentComponentViewModel(paymentProvider: nil) + let expectedView = PaymentComponentView() + expectedView.viewModel = expectedViewModel + + // When + let view = mockPaymentComponentsController.paymentView(documentId: documentId) + + // Then + XCTAssertTrue(view is PaymentComponentView) + guard let view = view as? PaymentComponentView else { + XCTFail("Error finding correct view.") + return + } + XCTAssertEqual(view.viewModel?.documentId, documentId) + } + + func testBankSelectionBottomSheet_ReturnsViewController() { + // When + let viewController = mockPaymentComponentsController.bankSelectionBottomSheet() + + // Then + XCTAssertTrue(viewController is BankSelectionBottomSheet) + guard let bottomSheet = viewController as? BankSelectionBottomSheet else { + XCTFail("Error finding correct viewController.") + return + } + XCTAssertNotNil(bottomSheet.bottomSheet) + } + + func testLoadPaymentReviewScreenFor_Success() { + // Given + let documentID = MockSessionManager.payableDocumentID + + // When + var receivedViewController: UIViewController? + var receivedError: GiniHealthError? + mockPaymentComponentsController.loadPaymentReviewScreenFor(documentID: documentID, trackingDelegate: nil) { viewController, error in + receivedViewController = viewController + receivedError = error + } + + // Then + XCTAssertNil(receivedError) + XCTAssertNotNil(receivedViewController) + XCTAssertTrue(receivedViewController is PaymentReviewViewController) + } + + func testLoadPaymentReviewScreenFor_Failure() { + // Given + let documentID = MockSessionManager.missingDocumentID + + // When + var receivedViewController: UIViewController? + var receivedError: GiniHealthError? + mockPaymentComponentsController.loadPaymentReviewScreenFor(documentID: documentID, trackingDelegate: nil) { viewController, error in + receivedViewController = viewController + receivedError = error + } + + // Then + XCTAssertNotNil(receivedError) + XCTAssertNil(receivedViewController) + XCTAssertEqual(receivedError, .apiError(.noResponse)) + } + + func testPaymentInfoViewController_ReturnsCorrectViewController() { + // When + let viewController = mockPaymentComponentsController.paymentInfoViewController() + + // Then + XCTAssertTrue(viewController is PaymentInfoViewController) + guard let paymentInfoVC = viewController as? PaymentInfoViewController else { + XCTFail("Error finding correct viewController.") + return + } + XCTAssertNotNil(paymentInfoVC.viewModel) + guard let paymentInfoViewModel = paymentInfoVC.viewModel else { + XCTFail("Error finding payment info viewModel.") + return + } + XCTAssertEqual(paymentInfoViewModel.paymentProviders, []) + } +} diff --git a/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/Resources/Gini-Test-Payment-Provider.png b/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/Resources/Gini-Test-Payment-Provider.png new file mode 100644 index 000000000..12766c524 Binary files /dev/null and b/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/Resources/Gini-Test-Payment-Provider.png differ diff --git a/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/Resources/document1.json b/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/Resources/document1.json new file mode 100644 index 000000000..5375bb3d5 --- /dev/null +++ b/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/Resources/document1.json @@ -0,0 +1,25 @@ +{ + "id": "626626a0-749f-11e2-bfd6-000000000001", + "creationDate": 1515932941.2839971, + "name": "scanned.jpg", + "progress": "COMPLETED", + "origin": "UPLOAD", + "sourceClassification": "SCANNED", + "pageCount": 1, + "pages" : [ + { + "images" : { + "750x900" : "http://api.gini.net/documents/626626a0-749f-11e2-bfd6-000000000001/pages/1/750x900", + "1280x1810" : "http://api.gini.net/documents/626626a0-749f-11e2-bfd6-000000000001/pages/1/1280x1810" + }, + "pageNumber" : 1 + } + ], + "_links": { + "extractions": "https://api.gini.net/documents/626626a0-749f-11e2-bfd6-000000000001/extractions", + "layout": "https://api.gini.net/documents/626626a0-749f-11e2-bfd6-000000000001/layout", + "document": "https://api.gini.net/documents/626626a0-749f-11e2-bfd6-000000000001", + "processed": "https://api.gini.net/documents/626626a0-749f-11e2-bfd6-000000000001/processed", + "pages": "https://api.gini.net/documents/626626a0-749f-11e2-bfd6-000000000001/pages" + } +} diff --git a/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/Resources/document2.json b/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/Resources/document2.json new file mode 100644 index 000000000..e4ed5ec7b --- /dev/null +++ b/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/Resources/document2.json @@ -0,0 +1,25 @@ +{ + "id": "626626a0-749f-11e2-bfd6-000000000002", + "creationDate": 1515932941.2839971, + "name": "scanned.jpg", + "progress": "COMPLETED", + "origin": "UPLOAD", + "sourceClassification": "SCANNED", + "pageCount": 1, + "pages" : [ + { + "images" : { + "750x900" : "http://api.gini.net/documents/626626a0-749f-11e2-bfd6-000000000002/pages/1/750x900", + "1280x1810" : "http://api.gini.net/documents/626626a0-749f-11e2-bfd6-000000000002/pages/1/1280x1810" + }, + "pageNumber" : 1 + } + ], + "_links": { + "extractions": "https://api.gini.net/documents/626626a0-749f-11e2-bfd6-000000000002/extractions", + "layout": "https://api.gini.net/documents/626626a0-749f-11e2-bfd6-000000000002/layout", + "document": "https://api.gini.net/documents/626626a0-749f-11e2-bfd6-000000000002", + "processed": "https://api.gini.net/documents/626626a0-749f-11e2-bfd6-000000000002/processed", + "pages": "https://api.gini.net/documents/626626a0-749f-11e2-bfd6-000000000002/pages" + } +} diff --git a/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/Resources/document3.json b/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/Resources/document3.json new file mode 100644 index 000000000..4fae5ee0b --- /dev/null +++ b/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/Resources/document3.json @@ -0,0 +1,25 @@ +{ + "id": "626626a0-749f-11e2-bfd6-000000000003", + "creationDate": 1515932941.2839971, + "name": "scanned.jpg", + "progress": "COMPLETED", + "origin": "UPLOAD", + "sourceClassification": "SCANNED", + "pageCount": 1, + "pages" : [ + { + "images" : { + "750x900" : "http://api.gini.net/documents/626626a0-749f-11e2-bfd6-000000000003/pages/1/750x900", + "1280x1810" : "http://api.gini.net/documents/626626a0-749f-11e2-bfd6-000000000003/pages/1/1280x1810" + }, + "pageNumber" : 1 + } + ], + "_links": { + "extractions": "https://api.gini.net/documents/626626a0-749f-11e2-bfd6-000000000003/extractions", + "layout": "https://api.gini.net/documents/626626a0-749f-11e2-bfd6-000000000003/layout", + "document": "https://api.gini.net/documents/626626a0-749f-11e2-bfd6-000000000003", + "processed": "https://api.gini.net/documents/626626a0-749f-11e2-bfd6-000000000003/processed", + "pages": "https://api.gini.net/documents/626626a0-749f-11e2-bfd6-000000000003/pages" + } +} diff --git a/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/Resources/document4.json b/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/Resources/document4.json new file mode 100644 index 000000000..acb439990 --- /dev/null +++ b/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/Resources/document4.json @@ -0,0 +1,25 @@ +{ + "id": "626626a0-749f-11e2-bfd6-000000000004", + "creationDate": 1515932941.2839971, + "name": "scanned.jpg", + "progress": "COMPLETED", + "origin": "UPLOAD", + "sourceClassification": "SCANNED", + "pageCount": 1, + "pages" : [ + { + "images" : { + "750x900" : "http://api.gini.net/documents/626626a0-749f-11e2-bfd6-000000000004/pages/1/750x900", + "1280x1810" : "http://api.gini.net/documents/626626a0-749f-11e2-bfd6-000000000004/pages/1/1280x1810" + }, + "pageNumber" : 1 + } + ], + "_links": { + "extractions": "https://api.gini.net/documents/626626a0-749f-11e2-bfd6-000000000004/extractions", + "layout": "https://api.gini.net/documents/626626a0-749f-11e2-bfd6-000000000004/layout", + "document": "https://api.gini.net/documents/626626a0-749f-11e2-bfd6-000000000004", + "processed": "https://api.gini.net/documents/626626a0-749f-11e2-bfd6-000000000004/processed", + "pages": "https://api.gini.net/documents/626626a0-749f-11e2-bfd6-000000000004/pages" + } +} diff --git a/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/Resources/extractionResultWithIBAN.json b/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/Resources/extractionResultWithIBAN.json new file mode 100644 index 000000000..4fe4f8a2e --- /dev/null +++ b/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/Resources/extractionResultWithIBAN.json @@ -0,0 +1,158 @@ +{ + "extractions": { + "paymentRecipient": { + "entity": "companyname", + "value": "Fahrrad Rückenwind", + "box": { + "top": 617.53, + "left": 66.25, + "width": 192.95999999999998, + "height": 11.040000000000077, + "page": 1 + }, + "candidates": "paymentRecipients" + }, + "paymentPurpose": { + "entity": "reference", + "value": "RE-20210512-02" + }, + "bic": { + "entity": "bic", + "value": "BYLADEM1001", + "box": { + "top": 642.49, + "left": 66.25, + "width": 86.03, + "height": 11.039999999999964, + "page": 1 + }, + "candidates": "bics" + }, + "amountToPay": { + "entity": "amount", + "value": "995.00:EUR", + "box": { + "top": 464.89, + "left": 496.45, + "width": 29.439999999999998, + "height": 10.080000000000041, + "page": 1 + }, + "candidates": "amounts" + }, + "iban": { + "entity": "iban", + "value": "DE02120300000000202051", + "box": { + "top": 666.49, + "left": 93.65, + "width": 121.82999999999998, + "height": 11.039999999999964, + "page": 1 + }, + "candidates": "ibans" + }, + "docType": { + "entity": "doctype", + "value": "Invoice" + } + }, + "candidates": { + "paymentRecipients": [ + { + "entity": "companyname", + "value": "Fahrrad Rückenwind", + "box": { + "top": 103.69, + "left": 66.25, + "width": 107.0, + "height": 12.0, + "page": 1 + } + }, + { + "entity": "companyname", + "value": "Fahrrad Rückenwind", + "box": { + "top": 617.53, + "left": 66.25, + "width": 192.95999999999998, + "height": 11.040000000000077, + "page": 1 + } + } + ], + "bics": [ + { + "entity": "bic", + "value": "BYLADEM1001", + "box": { + "top": 794.41, + "left": 282.25, + "width": 62.420000000000016, + "height": 7.920000000000073, + "page": 1 + } + }, + { + "entity": "bic", + "value": "BYLADEM1001", + "box": { + "top": 642.49, + "left": 66.25, + "width": 86.03, + "height": 11.039999999999964, + "page": 1 + } + } + ], + "amounts": [ + { + "entity": "amount", + "value": "995.00:EUR", + "box": { + "top": 464.89, + "left": 496.45, + "width": 29.439999999999998, + "height": 10.080000000000041, + "page": 1 + } + }, + { + "entity": "amount", + "value": "995.00:EUR", + "box": { + "top": 464.89, + "left": 496.45, + "width": 29.439999999999998, + "height": 10.080000000000041, + "page": 1 + } + } + ], + "ibans": [ + { + "entity": "iban", + "value": "DE02120300000000202051", + "box": { + "top": 804.49, + "left": 302.17, + "width": 88.56, + "height": 7.919999999999959, + "page": 1 + } + }, + { + "entity": "iban", + "value": "DE02120300000000202051", + "box": { + "top": 666.49, + "left": 93.65, + "width": 121.82999999999998, + "height": 11.039999999999964, + "page": 1 + } + } + ] + } +} diff --git a/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/Resources/extractionResultWithoutIBAN.json b/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/Resources/extractionResultWithoutIBAN.json new file mode 100644 index 000000000..896c10ded --- /dev/null +++ b/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/Resources/extractionResultWithoutIBAN.json @@ -0,0 +1,158 @@ +{ + "extractions": { + "paymentRecipient": { + "entity": "companyname", + "value": "Fahrrad Rückenwind", + "box": { + "top": 617.53, + "left": 66.25, + "width": 192.95999999999998, + "height": 11.040000000000077, + "page": 1 + }, + "candidates": "paymentRecipients" + }, + "paymentPurpose": { + "entity": "reference", + "value": "RE-20210512-02" + }, + "bic": { + "entity": "bic", + "value": "BYLADEM1001", + "box": { + "top": 642.49, + "left": 66.25, + "width": 86.03, + "height": 11.039999999999964, + "page": 1 + }, + "candidates": "bics" + }, + "amountToPay": { + "entity": "amount", + "value": "995.00:EUR", + "box": { + "top": 464.89, + "left": 496.45, + "width": 29.439999999999998, + "height": 10.080000000000041, + "page": 1 + }, + "candidates": "amounts" + }, + "iban": { + "entity": "iban", + "value": "", + "box": { + "top": 666.49, + "left": 93.65, + "width": 121.82999999999998, + "height": 11.039999999999964, + "page": 1 + }, + "candidates": "ibans" + }, + "docType": { + "entity": "doctype", + "value": "Invoice" + } + }, + "candidates": { + "paymentRecipients": [ + { + "entity": "companyname", + "value": "Fahrrad Rückenwind", + "box": { + "top": 103.69, + "left": 66.25, + "width": 107.0, + "height": 12.0, + "page": 1 + } + }, + { + "entity": "companyname", + "value": "Fahrrad Rückenwind", + "box": { + "top": 617.53, + "left": 66.25, + "width": 192.95999999999998, + "height": 11.040000000000077, + "page": 1 + } + } + ], + "bics": [ + { + "entity": "bic", + "value": "BYLADEM1001", + "box": { + "top": 794.41, + "left": 282.25, + "width": 62.420000000000016, + "height": 7.920000000000073, + "page": 1 + } + }, + { + "entity": "bic", + "value": "BYLADEM1001", + "box": { + "top": 642.49, + "left": 66.25, + "width": 86.03, + "height": 11.039999999999964, + "page": 1 + } + } + ], + "amounts": [ + { + "entity": "amount", + "value": "995.00:EUR", + "box": { + "top": 464.89, + "left": 496.45, + "width": 29.439999999999998, + "height": 10.080000000000041, + "page": 1 + } + }, + { + "entity": "amount", + "value": "995.00:EUR", + "box": { + "top": 464.89, + "left": 496.45, + "width": 29.439999999999998, + "height": 10.080000000000041, + "page": 1 + } + } + ], + "ibans": [ + { + "entity": "iban", + "value": "DE02120300000000202051", + "box": { + "top": 804.49, + "left": 302.17, + "width": 88.56, + "height": 7.919999999999959, + "page": 1 + } + }, + { + "entity": "iban", + "value": "DE02120300000000202051", + "box": { + "top": 666.49, + "left": 93.65, + "width": 121.82999999999998, + "height": 11.039999999999964, + "page": 1 + } + } + ] + } +} diff --git a/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/Resources/extractionsWithPayment.json b/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/Resources/extractionsWithPayment.json new file mode 100644 index 000000000..e97049889 --- /dev/null +++ b/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/Resources/extractionsWithPayment.json @@ -0,0 +1,546 @@ +{ + "extractions": { + "amount_to_pay": { + "entity": "amount", + "value": "30.27:EUR", + "box": { + "top": 860.6, + "left": 1106.6, + "width": 48.799999999999955, + "height": 16.0, + "page": 1 + }, + "candidates": "amounts" + }, + "document_date": { + "entity": "date", + "value": "2020-09-23", + "box": { + "top": 135.85, + "left": 418.85, + "width": 82.30000000000001, + "height": 13.0, + "page": 1 + }, + "candidates": "dates" + }, + "gross_amount": { + "entity": "amount", + "value": "30.27:EUR", + "box": { + "top": 860.6, + "left": 1106.6, + "width": 48.799999999999955, + "height": 16.0, + "page": 1 + }, + "candidates": "gross_amounts" + }, + "doc_type": { + "entity": "doctype", + "value": "Invoice" + }, + "language": { + "entity": "language", + "value": "de" + }, + "payment_state": { + "entity": "paymentstate", + "value": "ToBePaid" + }, + "invoice_id": { + "entity": "invoiceid", + "value": "3963757910434", + "box": { + "top": 116.7, + "left": 368.7, + "width": 132.0, + "height": 11.999999999999986, + "page": 1 + }, + "candidates": "invoice_ids" + } + }, + "compoundExtractions": { + "line_items": [ + { + "quantity": { + "entity": "numeric", + "value": "1", + "box": { + "top": 595.15, + "left": 721.15, + "width": 11.700000000000045, + "height": 14.0, + "page": 1 + } + }, + "description": { + "entity": "text", + "value": "Damen Yoga Leggings Fitness Hose Gym Fit- ness Sport bequeme Hose mit Tasche", + "box": { + "top": 593.45, + "left": 283.15, + "width": 333.30000000000007, + "height": 31.699999999999932, + "page": 1 + } + }, + "amount": { + "entity": "amount", + "value": "4.73:EUR", + "box": { + "top": 597.3, + "left": 1120.3, + "width": 36.40000000000009, + "height": 15.0, + "page": 1 + } + }, + "fee_schedule_number": { + "entity": "text", + "value": "4341", + "box": { + "top": 609.3, + "left": 82.3, + "width": 38.39999999999999, + "height": 15.0, + "page": 1 + } + } + }, + { + "quantity": { + "entity": "numeric", + "value": "1", + "box": { + "top": 635.15, + "left": 721.15, + "width": 11.700000000000045, + "height": 14.0, + "page": 1 + } + }, + "description": { + "entity": "text", + "value": "Lässige Leggings mit Totenkopf- und Blu-", + "box": { + "top": 634.0, + "left": 283.0, + "width": 303.0, + "height": 14.0, + "page": 1 + } + }, + "amount": { + "entity": "amount", + "value": "5.00:EUR", + "box": { + "top": 635.75, + "left": 1119.75, + "width": 35.5, + "height": 17.0, + "page": 1 + } + } + }, + { + "quantity": { + "entity": "numeric", + "value": "1", + "box": { + "top": 674.7, + "left": 721.7, + "width": 9.600000000000023, + "height": 12.0, + "page": 1 + } + }, + "description": { + "entity": "text", + "value": "Eng anliegende Anti-Cellulite Kompression Slim Yogahose für Damen Sport schneil trocknende Hose mit hohem Bund", + "box": { + "top": 672.3, + "left": 282.15, + "width": 347.15, + "height": 47.85000000000002, + "page": 1 + } + }, + "amount": { + "entity": "amount", + "value": "5.54:EUR", + "box": { + "top": 673.6, + "left": 808.6, + "width": 33.799999999999955, + "height": 16.0, + "page": 1 + } + } + }, + { + "amount": { + "entity": "amount", + "value": "5.00:EUR", + "box": { + "top": 775.45, + "left": 1120.45, + "width": 34.09999999999991, + "height": 16.0, + "page": 1 + } + } + } + ], + "invoice_sender": [ + { + "website": { + "entity": "url", + "value": "www.klana.de", + "box": { + "top": 880.5, + "left": 818.5, + "width": 79.0, + "height": 21.0, + "page": 1 + } + }, + "name": { + "entity": "text", + "value": "Kundenservice Klana", + "box": { + "top": 1027.0, + "left": 69.0, + "width": 407.0, + "height": 24.0, + "page": 1 + } + }, + "bic": { + "entity": "bic", + "value": "DEUTDEMM760", + "box": { + "top": 363.6, + "left": 656.6, + "width": 494.94999999999993, + "height": 16.849999999999966, + "page": 1 + } + }, + "vat_reg_number": { + "entity": "vat", + "value": "SE556737043101", + "box": { + "top": 1067.85, + "left": 713.85, + "width": 99.29999999999995, + "height": 13.0, + "page": 1 + } + }, + "iban": { + "entity": "iban", + "value": "DE13760700120500154000", + "box": { + "top": 344.0, + "left": 946.0, + "width": 206.0, + "height": 14.0, + "page": 1 + } + } + } + ], + "payment": [ + { + "amount_to_pay": { + "entity": "amount", + "value": "30.27:EUR", + "box": { + "top": 860.6, + "left": 1106.6, + "width": 48.799999999999955, + "height": 16.0, + "page": 1 + } + }, + "bic": { + "entity": "bic", + "value": "DEUTDEMM760", + "box": { + "top": 1331.5, + "left": 403.5, + "width": 306.0, + "height": 21.0, + "page": 1 + } + }, + "payment_reference": { + "entity": "text", + "value": "3963757910434", + "box": { + "top": 1473.2, + "left": 404.2, + "width": 364.00000000000006, + "height": 19.0, + "page": 1 + } + }, + "payment_recipient": { + "entity": "text", + "value": "KLARNA" + }, + "payment_purpose": { + "entity": "text", + "value": "39 63 75 79 10 43 4", + "box": { + "top": 1473.2, + "left": 404.2, + "width": 364.00000000000006, + "height": 19.0, + "page": 1 + } + }, + "iban": { + "entity": "iban", + "value": "DE13760700120500154000", + "box": { + "top": 1282.2, + "left": 403.2, + "width": 499.00000000000006, + "height": 19.0, + "page": 1 + } + } + } + ] + }, + "candidates": { + "ibans": [ + { + "entity": "iban", + "value": "DE13760700120500154000", + "box": { + "top": 344.0, + "left": 946.0, + "width": 206.0, + "height": 14.0, + "page": 1 + } + }, + { + "entity": "iban", + "value": "DE13760700120500154000", + "box": { + "top": 1056.85, + "left": 954.85, + "width": 192.9999999999999, + "height": 13.0, + "page": 1 + } + } + ], + "gross_amounts": [ + { + "entity": "amount", + "value": "30.27:EUR", + "box": { + "top": 388.15, + "left": 1070.15, + "width": 84.0, + "height": 14.0, + "page": 1 + } + }, + { + "entity": "amount", + "value": "5.00:EUR", + "box": { + "top": 798.6, + "left": 1120.6, + "width": 33.799999999999955, + "height": 16.0, + "page": 1 + } + }, + { + "entity": "amount", + "value": "30.27:EUR", + "box": { + "top": 860.6, + "left": 1106.6, + "width": 48.799999999999955, + "height": 16.0, + "page": 1 + } + }, + { + "entity": "amount", + "value": "30.27:EUR", + "box": { + "top": 860.6, + "left": 1106.6, + "width": 48.799999999999955, + "height": 16.0, + "page": 1 + } + }, + { + "entity": "amount", + "value": "30.27:EUR", + "box": { + "top": 860.6, + "left": 1106.6, + "width": 48.799999999999955, + "height": 16.0, + "page": 1 + } + } + ], + "bics": [ + { + "entity": "bic", + "value": "DEUTDEMM760", + "box": { + "top": 1070.4, + "left": 955.4, + "width": 121.00000000000011, + "height": 11.0, + "page": 1 + } + }, + { + "entity": "bic", + "value": "DEUTDEMM760", + "box": { + "top": 363.6, + "left": 656.6, + "width": 494.94999999999993, + "height": 16.849999999999966, + "page": 1 + } + } + ], + "websites": [ + { + "entity": "url", + "value": "www.klana.de", + "box": { + "top": 880.5, + "left": 818.5, + "width": 79.0, + "height": 21.0, + "page": 1 + } + }, + { + "entity": "url", + "value": "www.klarna.de", + "box": { + "top": 1040.0, + "left": 438.0, + "width": 163.0, + "height": 14.0, + "page": 1 + } + } + ], + "dates": [ + { + "entity": "date", + "value": "2020-09-23", + "box": { + "top": 135.85, + "left": 418.85, + "width": 82.30000000000001, + "height": 13.0, + "page": 1 + } + }, + { + "entity": "date", + "value": "2020-07-24", + "box": { + "top": 173.85, + "left": 417.85, + "width": 83.30000000000001, + "height": 13.0, + "page": 1 + } + }, + { + "entity": "date", + "value": "2020-10-07", + "box": { + "top": 298.3, + "left": 1069.3, + "width": 83.40000000000009, + "height": 15.0, + "page": 1 + } + } + ], + "vat_reg_numbers": [ + { + "entity": "vat", + "value": "SE556737043101", + "box": { + "top": 1067.85, + "left": 713.85, + "width": 99.29999999999995, + "height": 13.0, + "page": 1 + } + } + ], + "invoice_ids": [ + { + "entity": "invoiceid", + "value": "3963757910434", + "box": { + "top": 116.7, + "left": 368.7, + "width": 132.0, + "height": 11.999999999999986, + "page": 1 + } + } + ], + "amounts": [ + { + "entity": "amount", + "value": "30.27:EUR", + "box": { + "top": 860.6, + "left": 1106.6, + "width": 48.799999999999955, + "height": 16.0, + "page": 1 + } + }, + { + "entity": "amount", + "value": "30.27:EUR", + "box": { + "top": 860.6, + "left": 1106.6, + "width": 48.799999999999955, + "height": 16.0, + "page": 1 + } + }, + { + "entity": "amount", + "value": "30.27:EUR", + "box": { + "top": 388.15, + "left": 1070.15, + "width": 84.0, + "height": 14.0, + "page": 1 + } + } + ] + } +} diff --git a/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/Resources/paymentRequest.json b/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/Resources/paymentRequest.json new file mode 100644 index 000000000..1fd4c6ce7 --- /dev/null +++ b/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/Resources/paymentRequest.json @@ -0,0 +1,15 @@ +{ + "paymentProvider": "b09ef70a-490f-11eb-952e-9bc6f4646c57", + "requesterUri": "ginipay-test://paymentRequester", + "iban": "DE78370501980020008850", + "bic": "COLSDE33", + "amount": "1.00:EUR", + "purpose": "ReNr 12345", + "recipient": "Uno Flüchtlingshilfe", + "createdAt": "2021-03-23T08:40:01.830403", + "status": "open", + "_links": { + "self": "https://pay-api.gini.net/paymentRequests/118edf41-102a-4b40-8753-df2f0634cb86", + "paymentProvider": "https://pay-api.gini.net/paymentProviders/b09ef70a-490f-11eb-952e-9bc6f4646c57" + } +} diff --git a/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/Resources/provider.json b/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/Resources/provider.json new file mode 100644 index 000000000..1e9c34416 --- /dev/null +++ b/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/Resources/provider.json @@ -0,0 +1,16 @@ +{ + "id": "b09ef70a-490f-11eb-952e-9bc6f4646c57", + "name": "Gini-Test-Payment-Provider", + "appSchemeIOS": "ginipay-bank://", + "packageNameAndroid": "net.gini.android.bank.sdk.screenapiexample", + "minAppVersion": { + "ios": "??.?", + "android": "??.?" + }, + "colors": { + "background": "009EDC", + "text": "FFFFFF" + }, + "iconLocation": "https://pay-api.gini.net/paymentProviders/b09ef70a-490f-11eb-952e-9bc6f4646c57/icon", + "universalLinkIOS": "ginipay-bank://" +} diff --git a/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/Resources/providers.json b/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/Resources/providers.json new file mode 100644 index 000000000..889e47d00 --- /dev/null +++ b/HealthSDK/GiniHealthSDK/Tests/GiniHealthSDKTests/Resources/providers.json @@ -0,0 +1,186 @@ +[ + { + "id": "b09ef70a-490f-11eb-952e-9bc6f4646c57", + "name": "Gini-Test-Payment-Provider", + "appSchemeIOS": "ginipay-bank://", + "packageNameAndroid": "net.gini.android.bank.sdk.exampleapp", + "minAppVersion": { + "ios": "??.?", + "android": "??.?" + }, + "colors": { + "background": "009EDC", + "text": "FFFFFF" + }, + "iconLocation": "https://health-api.gini.net/paymentProviders/b09ef70a-490f-11eb-952e-9bc6f4646c57/icon", + "appStoreUrlIOS": "https://apps.apple.com/de/app/bank/id1234567890", + "playStoreUrlAndroid": "https://play.google.com/store/apps/details?id=net.gini.android.bank.insurance.mock", + "universalLinkIOS": "ginipay-bank://" + }, + { + "id": "f7d06ee0-51fd-11ec-8216-97f0937beb16", + "name": "GiniBank", + "appSchemeIOS": "ginipay-ginibank://", + "packageNameAndroid": "net.gini.android.bank.sdk.ginibank", + "minAppVersion": { + "ios": "1.2.3", + "android": "4.5.6" + }, + "colors": { + "background": "FFFFFF", + "text": "009EDC" + }, + "iconLocation": "https://health-api.gini.net/paymentProviders/f7d06ee0-51fd-11ec-8216-97f0937beb16/icon", + "universalLinkIOS": "ginipay-ginibank://" + }, + { + "id": "0bd58eae-7ea2-11ec-8a88-8fbe75353d94", + "name": "ConsorsbankMock", + "appSchemeIOS": "ginipay-consorsbank-mock://", + "packageNameAndroid": "de.consorsbank.bankingapp", + "minAppVersion": { + "ios": "1.2.3", + "android": "4.5.6" + }, + "colors": { + "background": "4DBED3", + "text": "FFFFFF" + }, + "iconLocation": "https://health-api.gini.net/paymentProviders/0bd58eae-7ea2-11ec-8a88-8fbe75353d94/icon", + "universalLinkIOS": "ginipay-consorsbank-mock://" + }, + { + "id": "f2d2f9a6-8e4a-11ec-97e4-e372f4cd98db", + "name": "Consorsbank Test", + "appSchemeIOS": "ginipay-consorsbanktest://", + "packageNameAndroid": "de.consorsbank.test", + "minAppVersion": { + "ios": "1.0.0", + "android": "1.0.0" + }, + "colors": { + "background": "0080A6", + "text": "FFFFFF" + }, + "iconLocation": "https://health-api.gini.net/paymentProviders/f2d2f9a6-8e4a-11ec-97e4-e372f4cd98db/icon", + "universalLinkIOS": "ginipay-consorsbanktest://" + }, + { + "id": "d5a56d26-8e4c-11ec-9c27-5b350ade3856", + "name": "Consorsbank Dev", + "appSchemeIOS": "ginipay-consorsbankdebug://", + "packageNameAndroid": "de.consorsbank.debug", + "minAppVersion": { + "ios": "1.0.0", + "android": "1.0.0" + }, + "colors": { + "background": "0080A6", + "text": "FFFFFF" + }, + "iconLocation": "https://health-api.gini.net/paymentProviders/d5a56d26-8e4c-11ec-9c27-5b350ade3856/icon", + "universalLinkIOS": "ginipay-consorsbankdebug://" + }, + { + "id": "f2e66ede-57be-43d9-b483-5c746220c594", + "name": "Bank", + "appSchemeIOS": "ginipay-insurance-bank-mock://", + "packageNameAndroid": "net.gini.android.bank.insurance.mock", + "minAppVersion": { + "ios": "1.0.0", + "android": "1.0.0" + }, + "colors": { + "background": "003FE2", + "text": "FFFFFF" + }, + "iconLocation": "https://health-api.gini.net/paymentProviders/f2e66ede-57be-43d9-b483-5c746220c594/icon", + "appStoreUrlIOS": "https://testflight.apple.com/join/BTe3AH8w", + "playStoreUrlAndroid": "https://install.appcenter.ms/orgs/gini-team-organization/apps/bank-1/distribution_groups/internal", + "universalLinkIOS": "ginipay-insurance-bank-mock://" + }, + { + "id": "dbe3a2ca-c9df-11eb-a1d8-a7efff6e88b7", + "name": "ING-DiBa", + "appSchemeIOS": "ginipay-ingdiba://", + "packageNameAndroid": "de.ingdiba.bankingapp", + "minAppVersion": { + "ios": "??.?", + "android": "??.?" + }, + "colors": { + "background": "daa520", + "text": "54f1db" + }, + "iconLocation": "https://health-api.gini.net/paymentProviders/dbe3a2ca-c9df-11eb-a1d8-a7efff6e88b7/icon", + "universalLinkIOS": "ginipay-ingdiba://" + }, + { + "id": "a65b0646-51fe-11ec-8736-c338396b2f09", + "name": "Consorsbank", + "appSchemeIOS": "ginipay-consorsbank://", + "packageNameAndroid": "de.consorsbank", + "minAppVersion": { + "ios": "1.0.0", + "android": "1.0.0" + }, + "colors": { + "background": "0080A6", + "text": "FFFFFF" + }, + "iconLocation": "https://health-api.gini.net/paymentProviders/a65b0646-51fe-11ec-8736-c338396b2f09/icon", + "appStoreUrlIOS": "https://apps.apple.com/de/app/consorsbank/id930883278", + "playStoreUrlAndroid": "https://play.google.com/store/apps/details?id=de.consorsbank", + "universalLinkIOS": "ginipay-consorsbank://" + }, + { + "id": "03e8f20c-8e4d-11ec-a97f-5f81b1fbfee4", + "name": "BNP Paribas myPrivateBank", + "appSchemeIOS": "ginipay-cbwm://", + "packageNameAndroid": "de.bnp.wm", + "minAppVersion": { + "ios": "1.0.0", + "android": "1.0.0" + }, + "colors": { + "background": "01975E", + "text": "FFFFFF" + }, + "iconLocation": "https://health-api.gini.net/paymentProviders/03e8f20c-8e4d-11ec-a97f-5f81b1fbfee4/icon", + "appStoreUrlIOS": "https://apps.apple.com/de/app/myprivatebank/id1115169520", + "playStoreUrlAndroid": "https://play.google.com/store/apps/details?id=de.bnp.wm", + "universalLinkIOS": "ginipay-cbwm://" + }, + { + "id": "43119f92-8e4d-11ec-861f-c75b8eeceadc", + "name": "BNP Paribas myPrivateBank Dev", + "appSchemeIOS": "ginipay-cbwmdebug://", + "packageNameAndroid": "de.bnp.wm.debug", + "minAppVersion": { + "ios": "1.0.0", + "android": "1.0.0" + }, + "colors": { + "background": "01975E", + "text": "FFFFFF" + }, + "iconLocation": "https://health-api.gini.net/paymentProviders/43119f92-8e4d-11ec-861f-c75b8eeceadc/icon", + "universalLinkIOS": "ginipay-cbwmdebug://" + }, + { + "id": "72e3b804-8e4d-11ec-be15-9bfa6d461196", + "name": "BNP Paribas myPrivateBank Test", + "appSchemeIOS": "ginipay-cbwmtest://", + "packageNameAndroid": "de.bnp.wm.test", + "minAppVersion": { + "ios": "1.0.0", + "android": "1.0.0" + }, + "colors": { + "background": "01975E", + "text": "FFFFFF" + }, + "iconLocation": "https://health-api.gini.net/paymentProviders/72e3b804-8e4d-11ec-be15-9bfa6d461196/icon", + "universalLinkIOS": "ginipay-cbwmtest://" + } +]