Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Apple Pay - Donate form API calls #4619

Merged
merged 33 commits into from
Sep 27, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
76916e0
Add feature flag
tonisevener Sep 8, 2023
85a3a07
Add json resources
tonisevener Sep 22, 2023
0f37f7f
Add WKServiceEnvironment, add methods for creating donate API URLs
tonisevener Sep 22, 2023
7fbb310
Move WKData protocols into Protocol subfolder, tweak service protocol…
tonisevener Sep 22, 2023
e23e324
Move feature-specific models into subfolders
tonisevener Sep 22, 2023
63e3073
Add WKURLSession wrapper for assistance in unit testing
tonisevener Sep 22, 2023
3b33078
Add extensions needed for basic service
tonisevener Sep 22, 2023
421971c
Add WKBasicService and WKBasicServiceRequest
tonisevener Sep 22, 2023
20295db
Add WKMockURLSession and unit tests for WKBasicService
tonisevener Sep 22, 2023
deec94c
Add basicService and serviceEnvironment properties to WKDataEnvironment
tonisevener Sep 22, 2023
bbb5b71
Add models for donateConfig, paymentMethods, and submitPayment API calls
tonisevener Sep 22, 2023
c315364
Add WKDonateDataController for making donation-related API calls
tonisevener Sep 22, 2023
7ebe664
Add WKMockDonateBasicService and unit tests for WKDonateDataController
tonisevener Sep 22, 2023
b49f212
Set the correct WKDataEnvironment service environment upon launch
tonisevener Sep 22, 2023
b6b436b
Fetch donate configs when announcements are fetched
tonisevener Sep 22, 2023
cdf54df
Add missed posting protocol conformance
tonisevener Sep 22, 2023
fdf2151
Merge branch 'main' into apple-pay-1
tonisevener Sep 22, 2023
312faba
Remove double header setting
tonisevener Sep 22, 2023
a1c1e3f
Fix compile failure - add fetchDonateConfig helper method to WMFAnnou…
tonisevener Sep 22, 2023
a82a1f8
Better brand name handling
tonisevener Sep 22, 2023
f4fe16e
Remove extra extension file
tonisevener Sep 22, 2023
b3aea1b
Temporary changes for testing
tonisevener Sep 22, 2023
d4bdfde
Merge branch 'main' into apple-pay-1
staykids Sep 25, 2023
cc2e9cd
PR Feedback - http response extension for status code success flag
tonisevener Sep 26, 2023
880b5b9
PR Feedback - base api path components
tonisevener Sep 26, 2023
d5b60e9
PR feedback - unnecessary comments
tonisevener Sep 26, 2023
7da6760
PR Feedback - rename feature flag
tonisevener Sep 26, 2023
96a531a
PR Feedback - improve donate config key names
tonisevener Sep 26, 2023
105b610
Merge branch 'main' into apple-pay-1
tonisevener Sep 26, 2023
c023c78
PR Feedback - rename feature flag again
tonisevener Sep 26, 2023
729ff24
PR Feedback - missing completion handler
tonisevener Sep 27, 2023
664e9f2
PR Feedback - add assertion failure for failure to encode dictionary …
tonisevener Sep 27, 2023
c7453a2
Merge branch 'main' into apple-pay-1
tonisevener Sep 27, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add WKMockDonateBasicService and unit tests for WKDonateDataController
  • Loading branch information
tonisevener committed Sep 22, 2023
commit 7ebe664bb7b5c5bda71dc32a9a89b1ee91bc3c89
145 changes: 145 additions & 0 deletions WKData/Sources/WKDataMocks/WKMockDonateBasicService.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
import Foundation
import WKData

fileprivate enum WKMockError: Error {
case unableToPullData
case unableToDeserialize
}

fileprivate extension WKData.WKServiceRequest {
var isDonateConfigGet: Bool {
switch WKDataEnvironment.current.serviceEnvironment {
case .production:
return false
case .staging:
guard let url,
url.host == "test.wikipedia.org",
url.path == "/wiki/MediaWiki:AppsDonationConfig.json",
let action = parameters?["action"] as? String else {
return false
}

return method == .GET && action == "raw"
}
}

var isPaymentMethodsGet: Bool {

switch WKDataEnvironment.current.serviceEnvironment {
case .production:
return false
case .staging:
guard let url,
url.host == "paymentstest4.wmcloud.org",
let action = parameters?["action"] as? String else {
return false
}

return method == .GET && action == "getPaymentMethods"
}
}

var isSubmitPaymentPost: Bool {
switch WKDataEnvironment.current.serviceEnvironment {
case .production:
return false
case .staging:
guard let url,
url.host == "paymentstest4.wmcloud.org",
let action = parameters?["action"] as? String else {
return false
}

return method == .POST && action == "submitPayment"
}
}
}

public class WKMockDonateBasicService: WKService {

public init() {

}

public func perform<R: WKServiceRequest>(request: R, completion: @escaping (Result<[String: Any]?, Error>) -> Void) {

guard let jsonData = jsonData(for: request) else {
completion(.failure(WKMockError.unableToPullData))
return
}

guard let jsonDict = try? JSONSerialization.jsonObject(with: jsonData) as? [String: Any] else {
completion(.failure(WKMockError.unableToDeserialize))
return
}

completion(.success(jsonDict))
}

public func performDecodableGET<R: WKServiceRequest, T: Decodable>(request: R, completion: @escaping (Result<T, Error>) -> Void) {

guard let jsonData = jsonData(for: request) else {
completion(.failure(WKMockError.unableToPullData))
return
}

let decoder = JSONDecoder()

guard let response = try? decoder.decode(T.self, from: jsonData) else {
completion(.failure(WKMockError.unableToDeserialize))
return
}

completion(.success(response))
}

public func performDecodablePOST<R, T>(request: R, completion: @escaping (Result<T, Error>) -> Void) where R : WKData.WKServiceRequest, T : Decodable {

guard let jsonData = jsonData(for: request) else {
completion(.failure(WKMockError.unableToPullData))
return
}

let decoder = JSONDecoder()

guard let response = try? decoder.decode(T.self, from: jsonData) else {
completion(.failure(WKMockError.unableToDeserialize))
return
}

completion(.success(response))
}

private func jsonData(for request: WKData.WKServiceRequest) -> Data? {
if request.isDonateConfigGet {
let resourceName = "donate-get-config"

guard let url = Bundle.module.url(forResource: resourceName, withExtension: "json"),
let jsonData = try? Data(contentsOf: url) else {
return nil
}

return jsonData
} else if request.isPaymentMethodsGet {
let resourceName = "donate-get-payment-methods"

guard let url = Bundle.module.url(forResource: resourceName, withExtension: "json"),
let jsonData = try? Data(contentsOf: url) else {
return nil
}

return jsonData
} else if request.isSubmitPaymentPost {
let resourceName = "donate-post-submit-payment-success"

guard let url = Bundle.module.url(forResource: resourceName, withExtension: "json"),
let jsonData = try? Data(contentsOf: url) else {
return nil
}

return jsonData
}

return nil
}
}
70 changes: 70 additions & 0 deletions WKData/Tests/WKDataTests/WKDonateDataControllerTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import XCTest
@testable import WKData
@testable import WKDataMocks

final class WKDonateDataControllerTests: XCTestCase {

override func setUp() async throws {
WKDataEnvironment.current.basicService = WKMockDonateBasicService()
WKDataEnvironment.current.serviceEnvironment = .staging
}

func testFetchDonateConfig() {
let controller = WKDonateDataController()

let expectation = XCTestExpectation(description: "Fetch Donate Configs")

controller.fetchConfigs(for: "US") { result in
switch result {
case .success:
break
case .failure(let error):
XCTFail("Failure fetching configs: \(error)")
}

expectation.fulfill()
}

wait(for: [expectation], timeout: 10.0)

let paymentMethods = WKDonateDataController.paymentMethods
let donateConfig = WKDonateDataController.donateConfig

XCTAssertNotNil(paymentMethods, "Expected Payment Methods")
XCTAssertNotNil(donateConfig, "Expected Donate Config")

guard let paymentMethods,
let donateConfig else {
return
}

XCTAssertEqual(donateConfig.version, 1, "Unexpected version")
XCTAssertEqual(donateConfig.currencyMinimums["USD"], 1, "Unexpected USD minimum")
XCTAssertEqual(donateConfig.currencyMaximums["USD"], 25000, "Unexpected USD maximum")
XCTAssertEqual(donateConfig.currencyAmounts7["USD"]?.count, 7, "Unexpected USD default options count")
XCTAssertEqual(donateConfig.currencyAmounts7["USD"]?[0], 3, "Unexpected USD default option first value")
XCTAssertEqual(donateConfig.currencyTransactionFees["default"], 0.35, "Unexpected default transaction fee")
XCTAssertTrue(donateConfig.countryCodeEmailOptInRequired.contains("AR"), "Missing AR from email opt in required list")
XCTAssertEqual(paymentMethods.applePayPaymentNetworks, ["AmEx", "Discover", "Maestro", "MasterCard", "Visa"], "Unexpected Apple Pay payment networks")
}

func testDonateSubmitPayment() {
let controller = WKDonateDataController()

let expectation = XCTestExpectation(description: "Fetch Donate Configs")

controller.submitPayment(amount: 3, currencyCode: "USD", paymentToken: "fake-token", donorName: "iOS Tester", donorEmail: "[email protected]", donorAddress: "123 Fake Street\nFaketown AA 12345\nUnited States", emailOptIn: nil) { result in
switch result {
case .success:
break
case .failure(let error):
XCTFail("Failure fetching configs: \(error)")
}

expectation.fulfill()
}

wait(for: [expectation], timeout: 10.0)
}

}