Skip to content

Commit

Permalink
[in_app_purchase_storekit] fix finish() not completing (#8324)
Browse files Browse the repository at this point in the history
Fixes `finishTransaction()` not properly completed. Also driveby test backfill + small adjustment to example app. 
fixes flutter/flutter#160148
  • Loading branch information
LouiseHsu authored Jan 6, 2025
1 parent 07ae98c commit 6294ec1
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 14 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## NEXT
## 0.3.20+3

* Fixes `finishTransaction` not completing.
* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4.

## 0.3.20+2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ extension InAppPurchasePlugin: InAppPurchase2API {
let transaction = try await fetchTransaction(by: UInt64(id))
if let transaction = transaction {
await transaction.finish()
completion(.success(Void()))
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,11 @@ import 'consumable_store.dart';
import 'example_payment_queue_delegate.dart';

void main() {
InAppPurchaseStoreKitPlatform.enableStoreKit2();
WidgetsFlutterBinding.ensureInitialized();

// When using the Android plugin directly it is mandatory to register
// the plugin as default instance as part of initializing the app.
InAppPurchaseStoreKitPlatform.registerPlatform();
InAppPurchaseStoreKitPlatform.enableStoreKit2();

runApp(_MyApp());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,35 @@ final class InAppPurchase2PluginTests: XCTestCase {
XCTAssertEqual(testProductMsg, fetchedProductMsg)
}

func testGetTransactions() async throws {
let purchaseExpectation = self.expectation(description: "Purchase should succeed")
let transactionExpectation = self.expectation(
description: "Getting transactions should succeed")

plugin.purchase(id: "consumable", options: nil) { result in
switch result {
case .success:
purchaseExpectation.fulfill()
case .failure(let error):
XCTFail("Purchase should NOT fail. Failed with \(error)")
}
}

await fulfillment(of: [purchaseExpectation], timeout: 5)

plugin.transactions {
result in
switch result {
case .success(let transactions):
XCTAssert(transactions.count == 1)
transactionExpectation.fulfill()
case .failure(let error):
XCTFail("Getting transactions should NOT fail. Failed with \(error)")
}
}
await fulfillment(of: [transactionExpectation], timeout: 5)
}

func testGetDiscountedProducts() async throws {
let expectation = self.expectation(description: "products successfully fetched")

Expand Down Expand Up @@ -91,7 +120,7 @@ final class InAppPurchase2PluginTests: XCTestCase {
case .success(let productMessages):
fetchedProductMsg = productMessages
expectation.fulfill()
case .failure(_):
case .failure:
XCTFail("Products should be successfully fetched")
}
}
Expand All @@ -110,7 +139,7 @@ final class InAppPurchase2PluginTests: XCTestCase {

plugin.products(identifiers: ["subscription_silver"]) { result in
switch result {
case .success(_):
case .success:
XCTFail("This `products` call should not succeed")
case .failure(let error):
expectation.fulfill()
Expand All @@ -127,7 +156,7 @@ final class InAppPurchase2PluginTests: XCTestCase {
let expectation = self.expectation(description: "Purchase request should succeed")
plugin.purchase(id: "consumable", options: nil) { result in
switch result {
case .success(let purchaseResult):
case .success:
expectation.fulfill()
case .failure(let error):
XCTFail("Purchase should NOT fail. Failed with \(error)")
Expand All @@ -143,7 +172,7 @@ final class InAppPurchase2PluginTests: XCTestCase {
let expectation = self.expectation(description: "products request should fail")
plugin.purchase(id: "consumable", options: nil) { result in
switch result {
case .success(_):
case .success:
XCTFail("Purchase should NOT suceed.")
case .failure(let error):
XCTAssertEqual(
Expand All @@ -162,7 +191,7 @@ final class InAppPurchase2PluginTests: XCTestCase {
let expectation = self.expectation(description: "Purchase request should succeed")
plugin.purchase(id: "consumable", options: nil) { result in
switch result {
case .success(_):
case .success:
XCTFail("Purchase should NOT suceed.")
case .failure(let error):
XCTAssertEqual(error.localizedDescription, "Item Unavailable")
Expand All @@ -176,7 +205,7 @@ final class InAppPurchase2PluginTests: XCTestCase {
let expectation = self.expectation(description: "products request should fail")
plugin.purchase(id: "invalid_product", options: nil) { result in
switch result {
case .success(_):
case .success:
XCTFail("Purchase should NOT suceed.")
case .failure(let error):
let pigeonError = error as! PigeonError
Expand All @@ -192,7 +221,7 @@ final class InAppPurchase2PluginTests: XCTestCase {
let expectation = self.expectation(description: "Purchase request should succeed")
plugin.purchase(id: "subscription_discounted", options: nil) { result in
switch result {
case .success(let purchaseResult):
case .success:
expectation.fulfill()
case .failure(let error):
XCTFail("Purchase should NOT fail. Failed with \(error)")
Expand All @@ -205,7 +234,7 @@ final class InAppPurchase2PluginTests: XCTestCase {
let expectation = self.expectation(description: "Purchase request should succeed")
plugin.purchase(id: "subscription_discounted", options: nil) { result in
switch result {
case .success(let purchaseResult):
case .success:
expectation.fulfill()
case .failure(let error):
XCTFail("Purchase should NOT fail. Failed with \(error)")
Expand All @@ -218,7 +247,7 @@ final class InAppPurchase2PluginTests: XCTestCase {
let expectation = self.expectation(description: "Purchase request should succeed")
plugin.purchase(id: "consumable_discounted", options: nil) { result in
switch result {
case .success(let purchaseResult):
case .success:
expectation.fulfill()
case .failure(let error):
XCTFail("Purchase should NOT fail. Failed with \(error)")
Expand All @@ -233,7 +262,7 @@ final class InAppPurchase2PluginTests: XCTestCase {

plugin.purchase(id: "subscription_silver", options: nil) { result in
switch result {
case .success(_):
case .success:
purchaseExpectation.fulfill()
case .failure(let error):
XCTFail("Purchase should NOT fail. Failed with \(error)")
Expand All @@ -250,4 +279,32 @@ final class InAppPurchase2PluginTests: XCTestCase {

await fulfillment(of: [restoreExpectation, purchaseExpectation], timeout: 5)
}

func testFinishTransaction() async throws {
let purchaseExpectation = self.expectation(description: "Purchase should succeed")
let finishExpectation = self.expectation(description: "Finishing purchase should succeed")

plugin.purchase(id: "consumable", options: nil) { result in
switch result {
case .success(let purchase):
purchaseExpectation.fulfill()
case .failure(let error):
XCTFail("Purchase should NOT fail. Failed with \(error)")
}
}

await fulfillment(of: [purchaseExpectation], timeout: 5)

// id should always be 0 as it is the first purchase
plugin.finish(id: 0) { result in
switch result {
case .success():
finishExpectation.fulfill()
case .failure(let error):
XCTFail("Finish purchases should NOT fail. Failed with \(error)")
}
}

await fulfillment(of: [finishExpectation], timeout: 5)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: in_app_purchase_storekit
description: An implementation for the iOS and macOS platforms of the Flutter `in_app_purchase` plugin. This uses the StoreKit Framework.
repository: https://github.com/flutter/packages/tree/main/packages/in_app_purchase/in_app_purchase_storekit
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+in_app_purchase%22
version: 0.3.20+2
version: 0.3.20+3

environment:
sdk: ^3.4.0
Expand Down

0 comments on commit 6294ec1

Please sign in to comment.