[in_app_purchase] Update Android to new analysis options (#4937)
diff --git a/packages/in_app_purchase/in_app_purchase_android/CHANGELOG.md b/packages/in_app_purchase/in_app_purchase_android/CHANGELOG.md index ff0ce6e..a871cfa 100644 --- a/packages/in_app_purchase/in_app_purchase_android/CHANGELOG.md +++ b/packages/in_app_purchase/in_app_purchase_android/CHANGELOG.md
@@ -1,3 +1,7 @@ +## 0.2.2+2 + +* Internal code cleanup for stricter analysis options. + ## 0.2.2+1 * Removes the dependency on `meta`.
diff --git a/packages/in_app_purchase/in_app_purchase_android/analysis_options.yaml b/packages/in_app_purchase/in_app_purchase_android/analysis_options.yaml deleted file mode 100644 index 5aeb4e7..0000000 --- a/packages/in_app_purchase/in_app_purchase_android/analysis_options.yaml +++ /dev/null
@@ -1 +0,0 @@ -include: ../../../analysis_options_legacy.yaml
diff --git a/packages/in_app_purchase/in_app_purchase_android/example/lib/consumable_store.dart b/packages/in_app_purchase/in_app_purchase_android/example/lib/consumable_store.dart index 4d10a50..448efcf 100644 --- a/packages/in_app_purchase/in_app_purchase_android/example/lib/consumable_store.dart +++ b/packages/in_app_purchase/in_app_purchase_android/example/lib/consumable_store.dart
@@ -5,13 +5,14 @@ import 'dart:async'; import 'package:shared_preferences/shared_preferences.dart'; +// ignore: avoid_classes_with_only_static_members /// A store of consumable items. /// /// This is a development prototype tha stores consumables in the shared /// preferences. Do not use this in real world apps. class ConsumableStore { static const String _kPrefKey = 'consumables'; - static Future<void> _writes = Future.value(); + static Future<void> _writes = Future<void>.value(); /// Adds a consumable with ID `id` to the store. /// @@ -32,19 +33,19 @@ /// Returns the list of consumables from the store. static Future<List<String>> load() async { return (await SharedPreferences.getInstance()).getStringList(_kPrefKey) ?? - []; + <String>[]; } static Future<void> _doSave(String id) async { - List<String> cached = await load(); - SharedPreferences prefs = await SharedPreferences.getInstance(); + final List<String> cached = await load(); + final SharedPreferences prefs = await SharedPreferences.getInstance(); cached.add(id); await prefs.setStringList(_kPrefKey, cached); } static Future<void> _doConsume(String id) async { - List<String> cached = await load(); - SharedPreferences prefs = await SharedPreferences.getInstance(); + final List<String> cached = await load(); + final SharedPreferences prefs = await SharedPreferences.getInstance(); cached.remove(id); await prefs.setStringList(_kPrefKey, cached); }
diff --git a/packages/in_app_purchase/in_app_purchase_android/example/lib/main.dart b/packages/in_app_purchase/in_app_purchase_android/example/lib/main.dart index a53e9b3..939bc43 100644 --- a/packages/in_app_purchase/in_app_purchase_android/example/lib/main.dart +++ b/packages/in_app_purchase/in_app_purchase_android/example/lib/main.dart
@@ -44,10 +44,10 @@ final InAppPurchasePlatform _inAppPurchasePlatform = InAppPurchasePlatform.instance; late StreamSubscription<List<PurchaseDetails>> _subscription; - List<String> _notFoundIds = []; - List<ProductDetails> _products = []; - List<PurchaseDetails> _purchases = []; - List<String> _consumables = []; + List<String> _notFoundIds = <String>[]; + List<ProductDetails> _products = <ProductDetails>[]; + List<PurchaseDetails> _purchases = <PurchaseDetails>[]; + List<String> _consumables = <String>[]; bool _isAvailable = false; bool _purchasePending = false; bool _loading = true; @@ -57,11 +57,12 @@ void initState() { final Stream<List<PurchaseDetails>> purchaseUpdated = _inAppPurchasePlatform.purchaseStream; - _subscription = purchaseUpdated.listen((purchaseDetailsList) { + _subscription = + purchaseUpdated.listen((List<PurchaseDetails> purchaseDetailsList) { _listenToPurchaseUpdated(purchaseDetailsList); }, onDone: () { _subscription.cancel(); - }, onError: (error) { + }, onError: (Object error) { // handle error here. }); initStoreInfo(); @@ -73,26 +74,26 @@ if (!isAvailable) { setState(() { _isAvailable = isAvailable; - _products = []; - _purchases = []; - _notFoundIds = []; - _consumables = []; + _products = <ProductDetails>[]; + _purchases = <PurchaseDetails>[]; + _notFoundIds = <String>[]; + _consumables = <String>[]; _purchasePending = false; _loading = false; }); return; } - ProductDetailsResponse productDetailResponse = + final ProductDetailsResponse productDetailResponse = await _inAppPurchasePlatform.queryProductDetails(_kProductIds.toSet()); if (productDetailResponse.error != null) { setState(() { _queryProductError = productDetailResponse.error!.message; _isAvailable = isAvailable; _products = productDetailResponse.productDetails; - _purchases = []; + _purchases = <PurchaseDetails>[]; _notFoundIds = productDetailResponse.notFoundIDs; - _consumables = []; + _consumables = <String>[]; _purchasePending = false; _loading = false; }); @@ -104,9 +105,9 @@ _queryProductError = null; _isAvailable = isAvailable; _products = productDetailResponse.productDetails; - _purchases = []; + _purchases = <PurchaseDetails>[]; _notFoundIds = productDetailResponse.notFoundIDs; - _consumables = []; + _consumables = <String>[]; _purchasePending = false; _loading = false; }); @@ -115,7 +116,7 @@ await _inAppPurchasePlatform.restorePurchases(); - List<String> consumables = await ConsumableStore.load(); + final List<String> consumables = await ConsumableStore.load(); setState(() { _isAvailable = isAvailable; _products = productDetailResponse.productDetails; @@ -134,11 +135,11 @@ @override Widget build(BuildContext context) { - List<Widget> stack = []; + final List<Widget> stack = <Widget>[]; if (_queryProductError == null) { stack.add( ListView( - children: [ + children: <Widget>[ _buildConnectionCheckTile(), _buildProductList(), _buildConsumableBox(), @@ -154,10 +155,10 @@ if (_purchasePending) { stack.add( Stack( - children: [ + children: const <Widget>[ Opacity( opacity: 0.3, - child: const ModalBarrier(dismissible: false, color: Colors.grey), + child: ModalBarrier(dismissible: false, color: Colors.grey), ), Center( child: CircularProgressIndicator(), @@ -181,7 +182,7 @@ Card _buildConnectionCheckTile() { if (_loading) { - return Card(child: ListTile(title: const Text('Trying to connect...'))); + return const Card(child: ListTile(title: Text('Trying to connect...'))); } final Widget storeHeader = ListTile( leading: Icon(_isAvailable ? Icons.check : Icons.block, @@ -192,8 +193,8 @@ final List<Widget> children = <Widget>[storeHeader]; if (!_isAvailable) { - children.addAll([ - Divider(), + children.addAll(<Widget>[ + const Divider(), ListTile( title: Text('Not connected', style: TextStyle(color: ThemeData.light().errorColor)), @@ -207,29 +208,30 @@ Card _buildProductList() { if (_loading) { - return Card( - child: (ListTile( + return const Card( + child: ListTile( leading: CircularProgressIndicator(), - title: Text('Fetching products...')))); + title: Text('Fetching products...'))); } if (!_isAvailable) { - return Card(); + return const Card(); } - final ListTile productHeader = ListTile(title: Text('Products for Sale')); - List<ListTile> productList = <ListTile>[]; + const ListTile productHeader = ListTile(title: Text('Products for Sale')); + final List<ListTile> productList = <ListTile>[]; if (_notFoundIds.isNotEmpty) { productList.add(ListTile( title: Text('[${_notFoundIds.join(", ")}] not found', style: TextStyle(color: ThemeData.light().errorColor)), - subtitle: Text( + subtitle: const Text( 'This app needs special configuration to run. Please see example/README.md for instructions.'))); } // This loading previous purchases code is just a demo. Please do not use this as it is. // In your app you should always verify the purchase data using the `verificationData` inside the [PurchaseDetails] object before trusting it. // We recommend that you use your own server to verify the purchase data. - Map<String, PurchaseDetails> purchases = - Map.fromEntries(_purchases.map((PurchaseDetails purchase) { + final Map<String, PurchaseDetails> purchases = + Map<String, PurchaseDetails>.fromEntries( + _purchases.map((PurchaseDetails purchase) { if (purchase.pendingCompletePurchase) { _inAppPurchasePlatform.completePurchase(purchase); } @@ -237,7 +239,7 @@ })); productList.addAll(_products.map( (ProductDetails productDetails) { - PurchaseDetails? previousPurchase = purchases[productDetails.id]; + final PurchaseDetails? previousPurchase = purchases[productDetails.id]; return ListTile( title: Text( productDetails.title, @@ -249,18 +251,18 @@ ? IconButton( onPressed: () { final InAppPurchaseAndroidPlatformAddition addition = - InAppPurchasePlatformAddition.instance + InAppPurchasePlatformAddition.instance! as InAppPurchaseAndroidPlatformAddition; - var skuDetails = + final SkuDetailsWrapper skuDetails = (productDetails as GooglePlayProductDetails) .skuDetails; addition .launchPriceChangeConfirmationFlow( sku: skuDetails.sku) - .then((value) => print( - "confirmationResponse: ${value.responseCode}")); + .then((BillingResultWrapper value) => print( + 'confirmationResponse: ${value.responseCode}')); }, - icon: Icon(Icons.upgrade)) + icon: const Icon(Icons.upgrade)) : TextButton( child: Text(productDetails.price), style: TextButton.styleFrom( @@ -272,10 +274,11 @@ // verify the latest status of you your subscription by using server side receipt validation // and update the UI accordingly. The subscription purchase status shown // inside the app may not be accurate. - final oldSubscription = _getOldSubscription( - productDetails as GooglePlayProductDetails, - purchases); - GooglePlayPurchaseParam purchaseParam = + final GooglePlayPurchaseDetails? oldSubscription = + _getOldSubscription( + productDetails as GooglePlayProductDetails, + purchases); + final GooglePlayPurchaseParam purchaseParam = GooglePlayPurchaseParam( productDetails: productDetails, applicationUserName: null, @@ -299,26 +302,26 @@ )); return Card( - child: - Column(children: <Widget>[productHeader, Divider()] + productList)); + child: Column( + children: <Widget>[productHeader, const Divider()] + productList)); } Card _buildConsumableBox() { if (_loading) { - return Card( - child: (ListTile( + return const Card( + child: ListTile( leading: CircularProgressIndicator(), - title: Text('Fetching consumables...')))); + title: Text('Fetching consumables...'))); } if (!_isAvailable || _notFoundIds.contains(_kConsumableId)) { - return Card(); + return const Card(); } - final ListTile consumableHeader = + const ListTile consumableHeader = ListTile(title: Text('Purchased consumables')); final List<Widget> tokens = _consumables.map((String id) { return GridTile( child: IconButton( - icon: Icon( + icon: const Icon( Icons.stars, size: 42.0, color: Colors.orange, @@ -331,12 +334,12 @@ return Card( child: Column(children: <Widget>[ consumableHeader, - Divider(), + const Divider(), GridView.count( crossAxisCount: 5, children: tokens, shrinkWrap: true, - padding: EdgeInsets.all(16.0), + padding: const EdgeInsets.all(16.0), ) ])); } @@ -355,11 +358,11 @@ }); } - void deliverProduct(PurchaseDetails purchaseDetails) async { + Future<void> deliverProduct(PurchaseDetails purchaseDetails) async { // IMPORTANT!! Always verify purchase details before delivering the product. if (purchaseDetails.productID == _kConsumableId) { await ConsumableStore.save(purchaseDetails.purchaseID!); - List<String> consumables = await ConsumableStore.load(); + final List<String> consumables = await ConsumableStore.load(); setState(() { _purchasePending = false; _consumables = consumables; @@ -388,8 +391,9 @@ // handle invalid purchase here if _verifyPurchase` failed. } - void _listenToPurchaseUpdated(List<PurchaseDetails> purchaseDetailsList) { - purchaseDetailsList.forEach((PurchaseDetails purchaseDetails) async { + Future<void> _listenToPurchaseUpdated( + List<PurchaseDetails> purchaseDetailsList) async { + for (final PurchaseDetails purchaseDetails in purchaseDetailsList) { if (purchaseDetails.status == PurchaseStatus.pending) { showPendingUI(); } else { @@ -397,7 +401,7 @@ handleError(purchaseDetails.error!); } else if (purchaseDetails.status == PurchaseStatus.purchased || purchaseDetails.status == PurchaseStatus.restored) { - bool valid = await _verifyPurchase(purchaseDetails); + final bool valid = await _verifyPurchase(purchaseDetails); if (valid) { deliverProduct(purchaseDetails); } else { @@ -408,7 +412,7 @@ if (!_kAutoConsume && purchaseDetails.productID == _kConsumableId) { final InAppPurchaseAndroidPlatformAddition addition = - InAppPurchasePlatformAddition.instance + InAppPurchasePlatformAddition.instance! as InAppPurchaseAndroidPlatformAddition; await addition.consumePurchase(purchaseDetails); @@ -418,7 +422,7 @@ await _inAppPurchasePlatform.completePurchase(purchaseDetails); } } - }); + } } GooglePlayPurchaseDetails? _getOldSubscription( @@ -435,31 +439,31 @@ if (productDetails.id == _kSilverSubscriptionId && purchases[_kGoldSubscriptionId] != null) { oldSubscription = - purchases[_kGoldSubscriptionId] as GooglePlayPurchaseDetails; + purchases[_kGoldSubscriptionId]! as GooglePlayPurchaseDetails; } else if (productDetails.id == _kGoldSubscriptionId && purchases[_kSilverSubscriptionId] != null) { oldSubscription = - purchases[_kSilverSubscriptionId] as GooglePlayPurchaseDetails; + purchases[_kSilverSubscriptionId]! as GooglePlayPurchaseDetails; } return oldSubscription; } } class _FeatureCard extends StatelessWidget { - final InAppPurchaseAndroidPlatformAddition addition = - InAppPurchasePlatformAddition.instance - as InAppPurchaseAndroidPlatformAddition; - _FeatureCard({Key? key}) : super(key: key); + final InAppPurchaseAndroidPlatformAddition addition = + InAppPurchasePlatformAddition.instance! + as InAppPurchaseAndroidPlatformAddition; + @override Widget build(BuildContext context) { return Card( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ - ListTile(title: Text('Available features')), - Divider(), + const ListTile(title: Text('Available features')), + const Divider(), for (BillingClientFeature feature in BillingClientFeature.values) _buildFeatureWidget(feature), ])); @@ -468,9 +472,9 @@ Widget _buildFeatureWidget(BillingClientFeature feature) { return FutureBuilder<bool>( future: addition.isFeatureSupported(feature), - builder: (context, snapshot) { + builder: (BuildContext context, AsyncSnapshot<bool> snapshot) { Color color = Colors.grey; - bool? data = snapshot.data; + final bool? data = snapshot.data; if (data != null) { color = data ? Colors.green : Colors.red; }
diff --git a/packages/in_app_purchase/in_app_purchase_android/example/pubspec.yaml b/packages/in_app_purchase/in_app_purchase_android/example/pubspec.yaml index f272616..9c16efc 100644 --- a/packages/in_app_purchase/in_app_purchase_android/example/pubspec.yaml +++ b/packages/in_app_purchase/in_app_purchase_android/example/pubspec.yaml
@@ -9,7 +9,6 @@ dependencies: flutter: sdk: flutter - shared_preferences: ^2.0.0 in_app_purchase_android: # When depending on this package from a real application you should use: # in_app_purchase_android: ^x.y.z @@ -17,15 +16,14 @@ # The example app is bundled with the plugin so we use a path dependency on # the parent directory to use the current plugin's version. path: ../ - in_app_purchase_platform_interface: ^1.0.0 + shared_preferences: ^2.0.0 dev_dependencies: flutter_driver: sdk: flutter integration_test: sdk: flutter - pedantic: ^1.10.0 flutter: uses-material-design: true
diff --git a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/billing_client_wrapper.dart b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/billing_client_wrapper.dart index 29441fb..416eb56 100644 --- a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/billing_client_wrapper.dart +++ b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/billing_client_wrapper.dart
@@ -38,7 +38,8 @@ /// /// Wraps a /// [`PurchasesUpdatedListener`](https://developer.android.com/reference/com/android/billingclient/api/PurchasesUpdatedListener.html). -typedef void PurchasesUpdatedListener(PurchasesResultWrapper purchasesResult); +typedef PurchasesUpdatedListener = void Function( + PurchasesResultWrapper purchasesResult); /// This class can be used directly instead of [InAppPurchaseConnection] to call /// Play-specific billing APIs. @@ -56,7 +57,9 @@ /// Creates a billing client. BillingClient(PurchasesUpdatedListener onPurchasesUpdated) { channel.setMethodCallHandler(callHandler); - _callbacks[kOnPurchasesUpdated] = [onPurchasesUpdated]; + _callbacks[kOnPurchasesUpdated] = <PurchasesUpdatedListener>[ + onPurchasesUpdated + ]; } // Occasionally methods in the native layer require a Dart callback to be @@ -67,7 +70,7 @@ // matching callback here to remember, and then once its twin is triggered it // sends the handle back over the platform channel. We then access that handle // in this array and call it in Dart code. See also [_callHandler]. - Map<String, List<Function>> _callbacks = <String, List<Function>>{}; + final Map<String, List<Function>> _callbacks = <String, List<Function>>{}; /// Calls /// [`BillingClient#isReady()`](https://developer.android.com/reference/com/android/billingclient/api/BillingClient.html#isReady()) @@ -101,12 +104,12 @@ Future<BillingResultWrapper> startConnection( {required OnBillingServiceDisconnected onBillingServiceDisconnected}) async { - List<Function> disconnectCallbacks = - _callbacks[_kOnBillingServiceDisconnected] ??= []; + final List<Function> disconnectCallbacks = + _callbacks[_kOnBillingServiceDisconnected] ??= <Function>[]; disconnectCallbacks.add(onBillingServiceDisconnected); return BillingResultWrapper.fromJson((await channel .invokeMapMethod<String, dynamic>( - "BillingClient#startConnection(BillingClientStateListener)", + 'BillingClient#startConnection(BillingClientStateListener)', <String, dynamic>{ 'handle': disconnectCallbacks.length - 1, })) ?? @@ -121,7 +124,7 @@ /// /// This triggers the destruction of the `BillingClient` instance in Java. Future<void> endConnection() async { - return channel.invokeMethod<void>("BillingClient#endConnection()", null); + return channel.invokeMethod<void>('BillingClient#endConnection()', null); } /// Returns a list of [SkuDetailsWrapper]s that have [SkuDetailsWrapper.sku] @@ -136,7 +139,7 @@ Future<SkuDetailsResponseWrapper> querySkuDetails( {required SkuType skuType, required List<String> skusList}) async { final Map<String, dynamic> arguments = <String, dynamic>{ - 'skuType': SkuTypeConverter().toJson(skuType), + 'skuType': const SkuTypeConverter().toJson(skuType), 'skusList': skusList }; return SkuDetailsResponseWrapper.fromJson((await channel.invokeMapMethod< @@ -197,7 +200,7 @@ 'obfuscatedProfileId': obfuscatedProfileId, 'oldSku': oldSku, 'purchaseToken': purchaseToken, - 'prorationMode': ProrationModeConverter().toJson(prorationMode ?? + 'prorationMode': const ProrationModeConverter().toJson(prorationMode ?? ProrationMode.unknownSubscriptionUpgradeDowngradePolicy) }; return BillingResultWrapper.fromJson( @@ -223,7 +226,7 @@ return PurchasesResultWrapper.fromJson((await channel .invokeMapMethod<String, dynamic>( 'BillingClient#queryPurchases(String)', <String, dynamic>{ - 'skuType': SkuTypeConverter().toJson(skuType) + 'skuType': const SkuTypeConverter().toJson(skuType) })) ?? <String, dynamic>{}); } @@ -247,7 +250,7 @@ String, dynamic>( 'BillingClient#queryPurchaseHistoryAsync(String, PurchaseHistoryResponseListener)', <String, dynamic>{ - 'skuType': SkuTypeConverter().toJson(skuType) + 'skuType': const SkuTypeConverter().toJson(skuType) })) ?? <String, dynamic>{}); } @@ -300,9 +303,9 @@ /// Checks if the specified feature or capability is supported by the Play Store. /// Call this to check if a [BillingClientFeature] is supported by the device. Future<bool> isFeatureSupported(BillingClientFeature feature) async { - var result = await channel.invokeMethod<bool>( + final bool? result = await channel.invokeMethod<bool>( 'BillingClient#isFeatureSupported(String)', <String, dynamic>{ - 'feature': BillingClientFeatureConverter().toJson(feature), + 'feature': const BillingClientFeatureConverter().toJson(feature), }); return result ?? false; } @@ -337,10 +340,10 @@ final PurchasesUpdatedListener listener = _callbacks[kOnPurchasesUpdated]!.first as PurchasesUpdatedListener; listener(PurchasesResultWrapper.fromJson( - call.arguments.cast<String, dynamic>())); + (call.arguments as Map<dynamic, dynamic>).cast<String, dynamic>())); break; case _kOnBillingServiceDisconnected: - final int handle = call.arguments['handle']; + final int handle = call.arguments['handle'] as int; await _callbacks[_kOnBillingServiceDisconnected]![handle](); break; } @@ -352,7 +355,7 @@ /// Wraps /// [`com.android.billingclient.api.BillingClientStateListener.onServiceDisconnected()`](https://developer.android.com/reference/com/android/billingclient/api/BillingClientStateListener.html#onBillingServiceDisconnected()) /// to call back on `BillingClient` disconnect. -typedef void OnBillingServiceDisconnected(); +typedef OnBillingServiceDisconnected = void Function(); /// Possible `BillingClient` response statuses. ///
diff --git a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/purchase_wrapper.dart b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/purchase_wrapper.dart index 742288e..653e514 100644 --- a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/purchase_wrapper.dart +++ b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/purchase_wrapper.dart
@@ -25,10 +25,11 @@ /// This wraps [`com.android.billlingclient.api.Purchase`](https://developer.android.com/reference/com/android/billingclient/api/Purchase) @JsonSerializable() @PurchaseStateConverter() +@immutable class PurchaseWrapper { /// Creates a purchase wrapper with the given purchase details. @visibleForTesting - PurchaseWrapper({ + const PurchaseWrapper({ required this.orderId, required this.packageName, required this.purchaseTime, @@ -50,19 +51,23 @@ @override bool operator ==(Object other) { - if (identical(other, this)) return true; - if (other.runtimeType != runtimeType) return false; - final PurchaseWrapper typedOther = other as PurchaseWrapper; - return typedOther.orderId == orderId && - typedOther.packageName == packageName && - typedOther.purchaseTime == purchaseTime && - typedOther.purchaseToken == purchaseToken && - typedOther.signature == signature && - typedOther.sku == sku && - typedOther.isAutoRenewing == isAutoRenewing && - typedOther.originalJson == originalJson && - typedOther.isAcknowledged == isAcknowledged && - typedOther.purchaseState == purchaseState; + if (identical(other, this)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + return other is PurchaseWrapper && + other.orderId == orderId && + other.packageName == packageName && + other.purchaseTime == purchaseTime && + other.purchaseToken == purchaseToken && + other.signature == signature && + other.sku == sku && + other.isAutoRenewing == isAutoRenewing && + other.originalJson == originalJson && + other.isAcknowledged == isAcknowledged && + other.purchaseState == purchaseState; } @override @@ -167,10 +172,11 @@ // We can optionally make [PurchaseWrapper] extend or implement [PurchaseHistoryRecordWrapper]. // For now, we keep them separated classes to be consistent with Android's BillingClient implementation. @JsonSerializable() +@immutable class PurchaseHistoryRecordWrapper { /// Creates a [PurchaseHistoryRecordWrapper] with the given record details. @visibleForTesting - PurchaseHistoryRecordWrapper({ + const PurchaseHistoryRecordWrapper({ required this.purchaseTime, required this.purchaseToken, required this.signature, @@ -216,16 +222,19 @@ @override bool operator ==(Object other) { - if (identical(other, this)) return true; - if (other.runtimeType != runtimeType) return false; - final PurchaseHistoryRecordWrapper typedOther = - other as PurchaseHistoryRecordWrapper; - return typedOther.purchaseTime == purchaseTime && - typedOther.purchaseToken == purchaseToken && - typedOther.signature == signature && - typedOther.sku == sku && - typedOther.originalJson == originalJson && - typedOther.developerPayload == developerPayload; + if (identical(other, this)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + return other is PurchaseHistoryRecordWrapper && + other.purchaseTime == purchaseTime && + other.purchaseToken == purchaseToken && + other.signature == signature && + other.sku == sku && + other.originalJson == originalJson && + other.developerPayload == developerPayload; } @override @@ -242,9 +251,10 @@ /// Wraps [`com.android.billingclient.api.Purchase.PurchasesResult`](https://developer.android.com/reference/com/android/billingclient/api/Purchase.PurchasesResult). @JsonSerializable() @BillingResponseConverter() +@immutable class PurchasesResultWrapper { /// Creates a [PurchasesResultWrapper] with the given purchase result details. - PurchasesResultWrapper( + const PurchasesResultWrapper( {required this.responseCode, required this.billingResult, required this.purchasesList}); @@ -255,12 +265,16 @@ @override bool operator ==(Object other) { - if (identical(other, this)) return true; - if (other.runtimeType != runtimeType) return false; - final PurchasesResultWrapper typedOther = other as PurchasesResultWrapper; - return typedOther.responseCode == responseCode && - typedOther.purchasesList == purchasesList && - typedOther.billingResult == billingResult; + if (identical(other, this)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + return other is PurchasesResultWrapper && + other.responseCode == responseCode && + other.purchasesList == purchasesList && + other.billingResult == billingResult; } @override @@ -288,9 +302,10 @@ /// that contains a detailed description of the status. @JsonSerializable() @BillingResponseConverter() +@immutable class PurchasesHistoryResult { /// Creates a [PurchasesHistoryResult] with the provided history. - PurchasesHistoryResult( + const PurchasesHistoryResult( {required this.billingResult, required this.purchaseHistoryRecordList}); /// Factory for creating a [PurchasesHistoryResult] from a [Map] with the history result details. @@ -299,11 +314,15 @@ @override bool operator ==(Object other) { - if (identical(other, this)) return true; - if (other.runtimeType != runtimeType) return false; - final PurchasesHistoryResult typedOther = other as PurchasesHistoryResult; - return typedOther.purchaseHistoryRecordList == purchaseHistoryRecordList && - typedOther.billingResult == billingResult; + if (identical(other, this)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + return other is PurchasesHistoryResult && + other.purchaseHistoryRecordList == purchaseHistoryRecordList && + other.billingResult == billingResult; } @override
diff --git a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/sku_details_wrapper.dart b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/sku_details_wrapper.dart index 8069a1f..53595c5 100644 --- a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/sku_details_wrapper.dart +++ b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/sku_details_wrapper.dart
@@ -18,7 +18,7 @@ /// /// This usually indicates a series underlining code issue in the plugin. @visibleForTesting -const kInvalidBillingResultErrorMessage = +const String kInvalidBillingResultErrorMessage = 'Invalid billing result map from method channel.'; /// Dart wrapper around [`com.android.billingclient.api.SkuDetails`](https://developer.android.com/reference/com/android/billingclient/api/SkuDetails). @@ -26,10 +26,11 @@ /// Contains the details of an available product in Google Play Billing. @JsonSerializable() @SkuTypeConverter() +@immutable class SkuDetailsWrapper { /// Creates a [SkuDetailsWrapper] with the given purchase details. @visibleForTesting - SkuDetailsWrapper({ + const SkuDetailsWrapper({ required this.description, required this.freeTrialPeriod, required this.introductoryPrice, @@ -50,8 +51,6 @@ required this.originalPriceAmountMicros, }) : _introductoryPriceMicros = introductoryPriceMicros; - final String _introductoryPriceMicros; - /// Constructs an instance of this from a key value map of data. /// /// The map needs to have named string keys with values matching the names and @@ -60,6 +59,8 @@ factory SkuDetailsWrapper.fromJson(Map<String, dynamic> map) => _$SkuDetailsWrapperFromJson(map); + final String _introductoryPriceMicros; + /// Textual description of the product. @JsonKey(defaultValue: '') final String description; @@ -182,10 +183,11 @@ /// /// Returned by [BillingClient.querySkuDetails]. @JsonSerializable() +@immutable class SkuDetailsResponseWrapper { /// Creates a [SkuDetailsResponseWrapper] with the given purchase details. @visibleForTesting - SkuDetailsResponseWrapper( + const SkuDetailsResponseWrapper( {required this.billingResult, required this.skuDetailsList}); /// Constructs an instance of this from a key value map of data. @@ -220,9 +222,10 @@ /// Params containing the response code and the debug message from the Play Billing API response. @JsonSerializable() @BillingResponseConverter() +@immutable class BillingResultWrapper { /// Constructs the object with [responseCode] and [debugMessage]. - BillingResultWrapper({required this.responseCode, this.debugMessage}); + const BillingResultWrapper({required this.responseCode, this.debugMessage}); /// Constructs an instance of this from a key value map of data. /// @@ -230,7 +233,7 @@ /// types of all of the members on this class. factory BillingResultWrapper.fromJson(Map<String, dynamic>? map) { if (map == null || map.isEmpty) { - return BillingResultWrapper( + return const BillingResultWrapper( responseCode: BillingResponse.error, debugMessage: kInvalidBillingResultErrorMessage); }
diff --git a/packages/in_app_purchase/in_app_purchase_android/lib/src/in_app_purchase_android_platform.dart b/packages/in_app_purchase/in_app_purchase_android/lib/src/in_app_purchase_android_platform.dart index 7c8ca52..61af756 100644 --- a/packages/in_app_purchase/in_app_purchase_android/lib/src/in_app_purchase_android_platform.dart +++ b/packages/in_app_purchase/in_app_purchase_android/lib/src/in_app_purchase_android_platform.dart
@@ -40,7 +40,8 @@ InAppPurchaseAndroidPlatformAddition(billingClient); _readyFuture = _connect(); - _purchaseUpdatedController = StreamController.broadcast(); + _purchaseUpdatedController = + StreamController<List<PurchaseDetails>>.broadcast(); } /// Registers this class as the default instance of [InAppPurchasePlatform]. @@ -64,7 +65,7 @@ late final BillingClient billingClient; late Future<void> _readyFuture; - static Set<String> _productIdsToConsume = Set<String>(); + static final Set<String> _productIdsToConsume = <String>{}; @override Future<bool> isAvailable() async { @@ -78,7 +79,7 @@ List<SkuDetailsResponseWrapper> responses; PlatformException? exception; try { - responses = await Future.wait([ + responses = await Future.wait(<Future<SkuDetailsResponseWrapper>>[ billingClient.querySkuDetails( skuType: SkuType.inapp, skusList: identifiers.toList()), billingClient.querySkuDetails( @@ -86,30 +87,31 @@ ]); } on PlatformException catch (e) { exception = e; - responses = [ + responses = <SkuDetailsResponseWrapper>[ // ignore: invalid_use_of_visible_for_testing_member SkuDetailsResponseWrapper( billingResult: BillingResultWrapper( responseCode: BillingResponse.error, debugMessage: e.code), - skuDetailsList: []), + skuDetailsList: const <SkuDetailsWrapper>[]), // ignore: invalid_use_of_visible_for_testing_member SkuDetailsResponseWrapper( billingResult: BillingResultWrapper( responseCode: BillingResponse.error, debugMessage: e.code), - skuDetailsList: []) + skuDetailsList: const <SkuDetailsWrapper>[]) ]; } - List<ProductDetails> productDetailsList = + final List<ProductDetails> productDetailsList = responses.expand((SkuDetailsResponseWrapper response) { return response.skuDetailsList; }).map((SkuDetailsWrapper skuDetailWrapper) { return GooglePlayProductDetails.fromSkuDetails(skuDetailWrapper); }).toList(); - Set<String> successIDS = productDetailsList + final Set<String> successIDS = productDetailsList .map((ProductDetails productDetails) => productDetails.id) .toSet(); - List<String> notFoundIDS = identifiers.difference(successIDS).toList(); + final List<String> notFoundIDS = + identifiers.difference(successIDS).toList(); return ProductDetailsResponse( productDetails: productDetailsList, notFoundIDs: notFoundIDS, @@ -130,7 +132,7 @@ changeSubscriptionParam = purchaseParam.changeSubscriptionParam; } - BillingResultWrapper billingResultWrapper = + final BillingResultWrapper billingResultWrapper = await billingClient.launchBillingFlow( sku: purchaseParam.productDetails.id, accountId: purchaseParam.applicationUserName, @@ -158,11 +160,11 @@ 'On Android, the `purchase` should always be of type `GooglePlayPurchaseDetails`.', ); - GooglePlayPurchaseDetails googlePurchase = + final GooglePlayPurchaseDetails googlePurchase = purchase as GooglePlayPurchaseDetails; if (googlePurchase.billingClientPurchase.isAcknowledged) { - return BillingResultWrapper(responseCode: BillingResponse.ok); + return const BillingResultWrapper(responseCode: BillingResponse.ok); } if (googlePurchase.verificationData == null) { @@ -180,22 +182,22 @@ }) async { List<PurchasesResultWrapper> responses; - responses = await Future.wait([ + responses = await Future.wait(<Future<PurchasesResultWrapper>>[ billingClient.queryPurchases(SkuType.inapp), billingClient.queryPurchases(SkuType.subs) ]); - Set errorCodeSet = responses + final Set<String> errorCodeSet = responses .where((PurchasesResultWrapper response) => response.responseCode != BillingResponse.ok) .map((PurchasesResultWrapper response) => response.responseCode.toString()) .toSet(); - String errorMessage = + final String errorMessage = errorCodeSet.isNotEmpty ? errorCodeSet.join(', ') : ''; - List<PurchaseDetails> pastPurchases = + final List<PurchaseDetails> pastPurchases = responses.expand((PurchasesResultWrapper response) { return response.purchasesList; }).map((PurchaseWrapper purchaseWrapper) { @@ -229,7 +231,7 @@ } final BillingResultWrapper billingResult = - await (InAppPurchasePlatformAddition.instance + await (InAppPurchasePlatformAddition.instance! as InAppPurchaseAndroidPlatformAddition) .consumePurchase(purchaseDetails); final BillingResponse consumedResponse = billingResult.responseCode; @@ -276,7 +278,7 @@ } else if (resultWrapper.responseCode == BillingResponse.ok) { status = PurchaseStatus.purchased; } - return [ + return <PurchaseDetails>[ PurchaseDetails( purchaseID: '', productID: '',
diff --git a/packages/in_app_purchase/in_app_purchase_android/lib/src/in_app_purchase_android_platform_addition.dart b/packages/in_app_purchase/in_app_purchase_android/lib/src/in_app_purchase_android_platform_addition.dart index dd6fe37..9bcfc3d 100644 --- a/packages/in_app_purchase/in_app_purchase_android/lib/src/in_app_purchase_android_platform_addition.dart +++ b/packages/in_app_purchase/in_app_purchase_android/lib/src/in_app_purchase_android_platform_addition.dart
@@ -74,16 +74,16 @@ List<PurchasesResultWrapper> responses; PlatformException? exception; try { - responses = await Future.wait([ + responses = await Future.wait(<Future<PurchasesResultWrapper>>[ _billingClient.queryPurchases(SkuType.inapp), _billingClient.queryPurchases(SkuType.subs) ]); } on PlatformException catch (e) { exception = e; - responses = [ + responses = <PurchasesResultWrapper>[ PurchasesResultWrapper( responseCode: BillingResponse.error, - purchasesList: [], + purchasesList: const <PurchaseWrapper>[], billingResult: BillingResultWrapper( responseCode: BillingResponse.error, debugMessage: e.details.toString(), @@ -91,7 +91,7 @@ ), PurchasesResultWrapper( responseCode: BillingResponse.error, - purchasesList: [], + purchasesList: const <PurchaseWrapper>[], billingResult: BillingResultWrapper( responseCode: BillingResponse.error, debugMessage: e.details.toString(), @@ -100,17 +100,17 @@ ]; } - Set errorCodeSet = responses + final Set<String> errorCodeSet = responses .where((PurchasesResultWrapper response) => response.responseCode != BillingResponse.ok) .map((PurchasesResultWrapper response) => response.responseCode.toString()) .toSet(); - String errorMessage = + final String errorMessage = errorCodeSet.isNotEmpty ? errorCodeSet.join(', ') : ''; - List<GooglePlayPurchaseDetails> pastPurchases = + final List<GooglePlayPurchaseDetails> pastPurchases = responses.expand((PurchasesResultWrapper response) { return response.purchasesList; }).map((PurchaseWrapper purchaseWrapper) {
diff --git a/packages/in_app_purchase/in_app_purchase_android/lib/src/types/google_play_product_details.dart b/packages/in_app_purchase/in_app_purchase_android/lib/src/types/google_play_product_details.dart index 59d33fe..58fd34e 100644 --- a/packages/in_app_purchase/in_app_purchase_android/lib/src/types/google_play_product_details.dart +++ b/packages/in_app_purchase/in_app_purchase_android/lib/src/types/google_play_product_details.dart
@@ -29,10 +29,6 @@ currencySymbol: currencySymbol, ); - /// Points back to the [SkuDetailsWrapper] object that was used to generate - /// this [GooglePlayProductDetails] object. - final SkuDetailsWrapper skuDetails; - /// Generate a [GooglePlayProductDetails] object based on an Android /// [SkuDetailsWrapper] object. factory GooglePlayProductDetails.fromSkuDetails( @@ -49,4 +45,8 @@ skuDetails: skuDetails, ); } + + /// Points back to the [SkuDetailsWrapper] object that was used to generate + /// this [GooglePlayProductDetails] object. + final SkuDetailsWrapper skuDetails; }
diff --git a/packages/in_app_purchase/in_app_purchase_android/lib/src/types/google_play_purchase_details.dart b/packages/in_app_purchase/in_app_purchase_android/lib/src/types/google_play_purchase_details.dart index e607164..42c61a3 100644 --- a/packages/in_app_purchase/in_app_purchase_android/lib/src/types/google_play_purchase_details.dart +++ b/packages/in_app_purchase/in_app_purchase_android/lib/src/types/google_play_purchase_details.dart
@@ -25,13 +25,9 @@ verificationData: verificationData, status: status, ) { - this.pendingCompletePurchase = !billingClientPurchase.isAcknowledged; + pendingCompletePurchase = !billingClientPurchase.isAcknowledged; } - /// Points back to the [PurchaseWrapper] which was used to generate this - /// [GooglePlayPurchaseDetails] object. - final PurchaseWrapper billingClientPurchase; - /// Generate a [PurchaseDetails] object based on an Android [Purchase] object. factory GooglePlayPurchaseDetails.fromPurchase(PurchaseWrapper purchase) { final GooglePlayPurchaseDetails purchaseDetails = GooglePlayPurchaseDetails( @@ -43,7 +39,8 @@ source: kIAPSource), transactionDate: purchase.purchaseTime.toString(), billingClientPurchase: purchase, - status: PurchaseStateConverter().toPurchaseStatus(purchase.purchaseState), + status: const PurchaseStateConverter() + .toPurchaseStatus(purchase.purchaseState), ); if (purchaseDetails.status == PurchaseStatus.error) { @@ -56,4 +53,8 @@ return purchaseDetails; } + + /// Points back to the [PurchaseWrapper] which was used to generate this + /// [GooglePlayPurchaseDetails] object. + final PurchaseWrapper billingClientPurchase; }
diff --git a/packages/in_app_purchase/in_app_purchase_android/pubspec.yaml b/packages/in_app_purchase/in_app_purchase_android/pubspec.yaml index 08e971a..0a667c6 100644 --- a/packages/in_app_purchase/in_app_purchase_android/pubspec.yaml +++ b/packages/in_app_purchase/in_app_purchase_android/pubspec.yaml
@@ -2,7 +2,7 @@ description: An implementation for the Android platform of the Flutter `in_app_purchase` plugin. This uses the Android BillingClient APIs. repository: https://github.com/flutter/plugins/tree/main/packages/in_app_purchase/in_app_purchase_android issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+in_app_purchase%22 -version: 0.2.2+1 +version: 0.2.2+2 environment: sdk: ">=2.14.0 <3.0.0" @@ -28,5 +28,4 @@ flutter_test: sdk: flutter json_serializable: ^6.0.0 - pedantic: ^1.10.0 test: ^1.16.0
diff --git a/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/billing_client_wrapper_test.dart b/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/billing_client_wrapper_test.dart index ba6e755..1e30ce4 100644 --- a/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/billing_client_wrapper_test.dart +++ b/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/billing_client_wrapper_test.dart
@@ -40,7 +40,7 @@ // Make sure that the enum values are supported and that the converter call // does not fail test('response states', () async { - BillingResponseConverter converter = BillingResponseConverter(); + const BillingResponseConverter converter = BillingResponseConverter(); converter.fromJson(-3); converter.fromJson(-2); converter.fromJson(-1); @@ -56,20 +56,20 @@ }); group('startConnection', () { - final String methodName = + const String methodName = 'BillingClient#startConnection(BillingClientStateListener)'; test('returns BillingResultWrapper', () async { const String debugMessage = 'dummy message'; - final BillingResponse responseCode = BillingResponse.developerError; + const BillingResponse responseCode = BillingResponse.developerError; stubPlatform.addResponse( name: methodName, value: <String, dynamic>{ - 'responseCode': BillingResponseConverter().toJson(responseCode), + 'responseCode': const BillingResponseConverter().toJson(responseCode), 'debugMessage': debugMessage, }, ); - BillingResultWrapper billingResult = BillingResultWrapper( + const BillingResultWrapper billingResult = BillingResultWrapper( responseCode: responseCode, debugMessage: debugMessage); expect( await billingClient.startConnection( @@ -79,11 +79,11 @@ test('passes handle to onBillingServiceDisconnected', () async { const String debugMessage = 'dummy message'; - final BillingResponse responseCode = BillingResponse.developerError; + const BillingResponse responseCode = BillingResponse.developerError; stubPlatform.addResponse( name: methodName, value: <String, dynamic>{ - 'responseCode': BillingResponseConverter().toJson(responseCode), + 'responseCode': const BillingResponseConverter().toJson(responseCode), 'debugMessage': debugMessage, }, ); @@ -101,14 +101,14 @@ expect( await billingClient.startConnection( onBillingServiceDisconnected: () {}), - equals(BillingResultWrapper( + equals(const BillingResultWrapper( responseCode: BillingResponse.error, debugMessage: kInvalidBillingResultErrorMessage))); }); }); test('endConnection', () async { - final String endConnectionName = 'BillingClient#endConnection()'; + const String endConnectionName = 'BillingClient#endConnection()'; expect(stubPlatform.countPreviousCalls(endConnectionName), equals(0)); stubPlatform.addResponse(name: endConnectionName, value: null); await billingClient.endConnection(); @@ -116,15 +116,15 @@ }); group('querySkuDetails', () { - final String queryMethodName = + const String queryMethodName = 'BillingClient#querySkuDetailsAsync(SkuDetailsParams, SkuDetailsResponseListener)'; test('handles empty skuDetails', () async { const String debugMessage = 'dummy message'; - final BillingResponse responseCode = BillingResponse.developerError; + const BillingResponse responseCode = BillingResponse.developerError; stubPlatform.addResponse(name: queryMethodName, value: <dynamic, dynamic>{ 'billingResult': <String, dynamic>{ - 'responseCode': BillingResponseConverter().toJson(responseCode), + 'responseCode': const BillingResponseConverter().toJson(responseCode), 'debugMessage': debugMessage, }, 'skuDetailsList': <Map<String, dynamic>>[] @@ -134,7 +134,7 @@ .querySkuDetails( skuType: SkuType.inapp, skusList: <String>['invalid']); - BillingResultWrapper billingResult = BillingResultWrapper( + const BillingResultWrapper billingResult = BillingResultWrapper( responseCode: responseCode, debugMessage: debugMessage); expect(response.billingResult, equals(billingResult)); expect(response.skuDetailsList, isEmpty); @@ -142,10 +142,10 @@ test('returns SkuDetailsResponseWrapper', () async { const String debugMessage = 'dummy message'; - final BillingResponse responseCode = BillingResponse.ok; + const BillingResponse responseCode = BillingResponse.ok; stubPlatform.addResponse(name: queryMethodName, value: <String, dynamic>{ 'billingResult': <String, dynamic>{ - 'responseCode': BillingResponseConverter().toJson(responseCode), + 'responseCode': const BillingResponseConverter().toJson(responseCode), 'debugMessage': debugMessage, }, 'skuDetailsList': <Map<String, dynamic>>[buildSkuMap(dummySkuDetails)] @@ -155,7 +155,7 @@ .querySkuDetails( skuType: SkuType.inapp, skusList: <String>['invalid']); - BillingResultWrapper billingResult = BillingResultWrapper( + const BillingResultWrapper billingResult = BillingResultWrapper( responseCode: responseCode, debugMessage: debugMessage); expect(response.billingResult, equals(billingResult)); expect(response.skuDetailsList, contains(dummySkuDetails)); @@ -168,7 +168,7 @@ .querySkuDetails( skuType: SkuType.inapp, skusList: <String>['invalid']); - BillingResultWrapper billingResult = BillingResultWrapper( + const BillingResultWrapper billingResult = BillingResultWrapper( responseCode: BillingResponse.error, debugMessage: kInvalidBillingResultErrorMessage); expect(response.billingResult, equals(billingResult)); @@ -177,21 +177,21 @@ }); group('launchBillingFlow', () { - final String launchMethodName = + const String launchMethodName = 'BillingClient#launchBillingFlow(Activity, BillingFlowParams)'; test('serializes and deserializes data', () async { const String debugMessage = 'dummy message'; - final BillingResponse responseCode = BillingResponse.ok; - final BillingResultWrapper expectedBillingResult = BillingResultWrapper( + const BillingResponse responseCode = BillingResponse.ok; + const BillingResultWrapper expectedBillingResult = BillingResultWrapper( responseCode: responseCode, debugMessage: debugMessage); stubPlatform.addResponse( name: launchMethodName, value: buildBillingResultMap(expectedBillingResult), ); - final SkuDetailsWrapper skuDetails = dummySkuDetails; - final String accountId = "hashedAccountId"; - final String profileId = "hashedProfileId"; + const SkuDetailsWrapper skuDetails = dummySkuDetails; + const String accountId = 'hashedAccountId'; + const String profileId = 'hashedProfileId'; expect( await billingClient.launchBillingFlow( @@ -199,8 +199,9 @@ accountId: accountId, obfuscatedProfileId: profileId), equals(expectedBillingResult)); - Map<dynamic, dynamic> arguments = - stubPlatform.previousCallMatching(launchMethodName).arguments; + final Map<dynamic, dynamic> arguments = stubPlatform + .previousCallMatching(launchMethodName) + .arguments as Map<dynamic, dynamic>; expect(arguments['sku'], equals(skuDetails.sku)); expect(arguments['accountId'], equals(accountId)); expect(arguments['obfuscatedProfileId'], equals(profileId)); @@ -210,16 +211,16 @@ 'Change subscription throws assertion error `oldSku` and `purchaseToken` has different nullability', () async { const String debugMessage = 'dummy message'; - final BillingResponse responseCode = BillingResponse.ok; - final BillingResultWrapper expectedBillingResult = BillingResultWrapper( + const BillingResponse responseCode = BillingResponse.ok; + const BillingResultWrapper expectedBillingResult = BillingResultWrapper( responseCode: responseCode, debugMessage: debugMessage); stubPlatform.addResponse( name: launchMethodName, value: buildBillingResultMap(expectedBillingResult), ); - final SkuDetailsWrapper skuDetails = dummySkuDetails; - final String accountId = 'hashedAccountId'; - final String profileId = 'hashedProfileId'; + const SkuDetailsWrapper skuDetails = dummySkuDetails; + const String accountId = 'hashedAccountId'; + const String profileId = 'hashedProfileId'; expect( billingClient.launchBillingFlow( @@ -244,16 +245,16 @@ 'serializes and deserializes data on change subscription without proration', () async { const String debugMessage = 'dummy message'; - final BillingResponse responseCode = BillingResponse.ok; - final BillingResultWrapper expectedBillingResult = BillingResultWrapper( + const BillingResponse responseCode = BillingResponse.ok; + const BillingResultWrapper expectedBillingResult = BillingResultWrapper( responseCode: responseCode, debugMessage: debugMessage); stubPlatform.addResponse( name: launchMethodName, value: buildBillingResultMap(expectedBillingResult), ); - final SkuDetailsWrapper skuDetails = dummySkuDetails; - final String accountId = 'hashedAccountId'; - final String profileId = 'hashedProfileId'; + const SkuDetailsWrapper skuDetails = dummySkuDetails; + const String accountId = 'hashedAccountId'; + const String profileId = 'hashedProfileId'; expect( await billingClient.launchBillingFlow( @@ -263,8 +264,9 @@ oldSku: dummyOldPurchase.sku, purchaseToken: dummyOldPurchase.purchaseToken), equals(expectedBillingResult)); - Map<dynamic, dynamic> arguments = - stubPlatform.previousCallMatching(launchMethodName).arguments; + final Map<dynamic, dynamic> arguments = stubPlatform + .previousCallMatching(launchMethodName) + .arguments as Map<dynamic, dynamic>; expect(arguments['sku'], equals(skuDetails.sku)); expect(arguments['accountId'], equals(accountId)); expect(arguments['oldSku'], equals(dummyOldPurchase.sku)); @@ -277,17 +279,18 @@ 'serializes and deserializes data on change subscription with proration', () async { const String debugMessage = 'dummy message'; - final BillingResponse responseCode = BillingResponse.ok; - final BillingResultWrapper expectedBillingResult = BillingResultWrapper( + const BillingResponse responseCode = BillingResponse.ok; + const BillingResultWrapper expectedBillingResult = BillingResultWrapper( responseCode: responseCode, debugMessage: debugMessage); stubPlatform.addResponse( name: launchMethodName, value: buildBillingResultMap(expectedBillingResult), ); - final SkuDetailsWrapper skuDetails = dummySkuDetails; - final String accountId = 'hashedAccountId'; - final String profileId = 'hashedProfileId'; - final prorationMode = ProrationMode.immediateAndChargeProratedPrice; + const SkuDetailsWrapper skuDetails = dummySkuDetails; + const String accountId = 'hashedAccountId'; + const String profileId = 'hashedProfileId'; + const ProrationMode prorationMode = + ProrationMode.immediateAndChargeProratedPrice; expect( await billingClient.launchBillingFlow( @@ -298,8 +301,9 @@ prorationMode: prorationMode, purchaseToken: dummyOldPurchase.purchaseToken), equals(expectedBillingResult)); - Map<dynamic, dynamic> arguments = - stubPlatform.previousCallMatching(launchMethodName).arguments; + final Map<dynamic, dynamic> arguments = stubPlatform + .previousCallMatching(launchMethodName) + .arguments as Map<dynamic, dynamic>; expect(arguments['sku'], equals(skuDetails.sku)); expect(arguments['accountId'], equals(accountId)); expect(arguments['oldSku'], equals(dummyOldPurchase.sku)); @@ -307,24 +311,25 @@ expect( arguments['purchaseToken'], equals(dummyOldPurchase.purchaseToken)); expect(arguments['prorationMode'], - ProrationModeConverter().toJson(prorationMode)); + const ProrationModeConverter().toJson(prorationMode)); }); test('handles null accountId', () async { const String debugMessage = 'dummy message'; - final BillingResponse responseCode = BillingResponse.ok; - final BillingResultWrapper expectedBillingResult = BillingResultWrapper( + const BillingResponse responseCode = BillingResponse.ok; + const BillingResultWrapper expectedBillingResult = BillingResultWrapper( responseCode: responseCode, debugMessage: debugMessage); stubPlatform.addResponse( name: launchMethodName, value: buildBillingResultMap(expectedBillingResult), ); - final SkuDetailsWrapper skuDetails = dummySkuDetails; + const SkuDetailsWrapper skuDetails = dummySkuDetails; expect(await billingClient.launchBillingFlow(sku: skuDetails.sku), equals(expectedBillingResult)); - Map<dynamic, dynamic> arguments = - stubPlatform.previousCallMatching(launchMethodName).arguments; + final Map<dynamic, dynamic> arguments = stubPlatform + .previousCallMatching(launchMethodName) + .arguments as Map<dynamic, dynamic>; expect(arguments['sku'], equals(skuDetails.sku)); expect(arguments['accountId'], isNull); }); @@ -334,10 +339,10 @@ name: launchMethodName, value: null, ); - final SkuDetailsWrapper skuDetails = dummySkuDetails; + const SkuDetailsWrapper skuDetails = dummySkuDetails; expect( await billingClient.launchBillingFlow(sku: skuDetails.sku), - equals(BillingResultWrapper( + equals(const BillingResultWrapper( responseCode: BillingResponse.error, debugMessage: kInvalidBillingResultErrorMessage))); }); @@ -348,17 +353,17 @@ 'BillingClient#queryPurchases(String)'; test('serializes and deserializes data', () async { - final BillingResponse expectedCode = BillingResponse.ok; + const BillingResponse expectedCode = BillingResponse.ok; final List<PurchaseWrapper> expectedList = <PurchaseWrapper>[ dummyPurchase ]; const String debugMessage = 'dummy message'; - final BillingResultWrapper expectedBillingResult = BillingResultWrapper( + const BillingResultWrapper expectedBillingResult = BillingResultWrapper( responseCode: expectedCode, debugMessage: debugMessage); stubPlatform .addResponse(name: queryPurchasesMethodName, value: <String, dynamic>{ 'billingResult': buildBillingResultMap(expectedBillingResult), - 'responseCode': BillingResponseConverter().toJson(expectedCode), + 'responseCode': const BillingResponseConverter().toJson(expectedCode), 'purchasesList': expectedList .map((PurchaseWrapper purchase) => buildPurchaseMap(purchase)) .toList(), @@ -373,15 +378,15 @@ }); test('handles empty purchases', () async { - final BillingResponse expectedCode = BillingResponse.userCanceled; + const BillingResponse expectedCode = BillingResponse.userCanceled; const String debugMessage = 'dummy message'; - final BillingResultWrapper expectedBillingResult = BillingResultWrapper( + const BillingResultWrapper expectedBillingResult = BillingResultWrapper( responseCode: expectedCode, debugMessage: debugMessage); stubPlatform .addResponse(name: queryPurchasesMethodName, value: <String, dynamic>{ 'billingResult': buildBillingResultMap(expectedBillingResult), - 'responseCode': BillingResponseConverter().toJson(expectedCode), - 'purchasesList': [], + 'responseCode': const BillingResponseConverter().toJson(expectedCode), + 'purchasesList': <dynamic>[], }); final PurchasesResultWrapper response = @@ -402,7 +407,7 @@ expect( response.billingResult, - equals(BillingResultWrapper( + equals(const BillingResultWrapper( responseCode: BillingResponse.error, debugMessage: kInvalidBillingResultErrorMessage))); expect(response.responseCode, BillingResponse.error); @@ -415,13 +420,13 @@ 'BillingClient#queryPurchaseHistoryAsync(String, PurchaseHistoryResponseListener)'; test('serializes and deserializes data', () async { - final BillingResponse expectedCode = BillingResponse.ok; + const BillingResponse expectedCode = BillingResponse.ok; final List<PurchaseHistoryRecordWrapper> expectedList = <PurchaseHistoryRecordWrapper>[ dummyPurchaseHistoryRecord, ]; const String debugMessage = 'dummy message'; - final BillingResultWrapper expectedBillingResult = BillingResultWrapper( + const BillingResultWrapper expectedBillingResult = BillingResultWrapper( responseCode: expectedCode, debugMessage: debugMessage); stubPlatform.addResponse( name: queryPurchaseHistoryMethodName, @@ -440,14 +445,16 @@ }); test('handles empty purchases', () async { - final BillingResponse expectedCode = BillingResponse.userCanceled; + const BillingResponse expectedCode = BillingResponse.userCanceled; const String debugMessage = 'dummy message'; - final BillingResultWrapper expectedBillingResult = BillingResultWrapper( + const BillingResultWrapper expectedBillingResult = BillingResultWrapper( responseCode: expectedCode, debugMessage: debugMessage); - stubPlatform.addResponse(name: queryPurchaseHistoryMethodName, value: { - 'billingResult': buildBillingResultMap(expectedBillingResult), - 'purchaseHistoryRecordList': [], - }); + stubPlatform.addResponse( + name: queryPurchaseHistoryMethodName, + value: <dynamic, dynamic>{ + 'billingResult': buildBillingResultMap(expectedBillingResult), + 'purchaseHistoryRecordList': <dynamic>[], + }); final PurchasesHistoryResult response = await billingClient.queryPurchaseHistory(SkuType.inapp); @@ -466,7 +473,7 @@ expect( response.billingResult, - equals(BillingResultWrapper( + equals(const BillingResultWrapper( responseCode: BillingResponse.error, debugMessage: kInvalidBillingResultErrorMessage))); expect(response.purchaseHistoryRecordList, isEmpty); @@ -477,9 +484,9 @@ const String consumeMethodName = 'BillingClient#consumeAsync(String, ConsumeResponseListener)'; test('consume purchase async success', () async { - final BillingResponse expectedCode = BillingResponse.ok; + const BillingResponse expectedCode = BillingResponse.ok; const String debugMessage = 'dummy message'; - final BillingResultWrapper expectedBillingResult = BillingResultWrapper( + const BillingResultWrapper expectedBillingResult = BillingResultWrapper( responseCode: expectedCode, debugMessage: debugMessage); stubPlatform.addResponse( name: consumeMethodName, @@ -501,7 +508,7 @@ expect( billingResult, - equals(BillingResultWrapper( + equals(const BillingResultWrapper( responseCode: BillingResponse.error, debugMessage: kInvalidBillingResultErrorMessage))); }); @@ -511,9 +518,9 @@ const String acknowledgeMethodName = 'BillingClient#(AcknowledgePurchaseParams params, (AcknowledgePurchaseParams, AcknowledgePurchaseResponseListener)'; test('acknowledge purchase success', () async { - final BillingResponse expectedCode = BillingResponse.ok; + const BillingResponse expectedCode = BillingResponse.ok; const String debugMessage = 'dummy message'; - final BillingResultWrapper expectedBillingResult = BillingResultWrapper( + const BillingResultWrapper expectedBillingResult = BillingResultWrapper( responseCode: expectedCode, debugMessage: debugMessage); stubPlatform.addResponse( name: acknowledgeMethodName, @@ -534,7 +541,7 @@ expect( billingResult, - equals(BillingResultWrapper( + equals(const BillingResultWrapper( responseCode: BillingResponse.error, debugMessage: kInvalidBillingResultErrorMessage))); }); @@ -548,7 +555,8 @@ stubPlatform.addResponse( name: isFeatureSupportedMethodName, value: false, - additionalStepBeforeReturn: (value) => arguments = value, + additionalStepBeforeReturn: (dynamic value) => + arguments = value as Map<dynamic, dynamic>, ); final bool isSupported = await billingClient .isFeatureSupported(BillingClientFeature.subscriptions); @@ -561,7 +569,8 @@ stubPlatform.addResponse( name: isFeatureSupportedMethodName, value: true, - additionalStepBeforeReturn: (value) => arguments = value, + additionalStepBeforeReturn: (dynamic value) => + arguments = value as Map<dynamic, dynamic>, ); final bool isSupported = await billingClient .isFeatureSupported(BillingClientFeature.subscriptions); @@ -574,7 +583,8 @@ const String launchPriceChangeConfirmationFlowMethodName = 'BillingClient#launchPriceChangeConfirmationFlow (Activity, PriceChangeFlowParams, PriceChangeConfirmationListener)'; - final expectedBillingResultPriceChangeConfirmation = BillingResultWrapper( + const BillingResultWrapper expectedBillingResultPriceChangeConfirmation = + BillingResultWrapper( responseCode: BillingResponse.ok, debugMessage: 'dummy message', );
diff --git a/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/purchase_wrapper_test.dart b/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/purchase_wrapper_test.dart index f513420..65c8bb2 100644 --- a/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/purchase_wrapper_test.dart +++ b/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/purchase_wrapper_test.dart
@@ -6,7 +6,7 @@ import 'package:in_app_purchase_android/in_app_purchase_android.dart'; import 'package:test/test.dart'; -final PurchaseWrapper dummyPurchase = PurchaseWrapper( +const PurchaseWrapper dummyPurchase = PurchaseWrapper( orderId: 'orderId', packageName: 'packageName', purchaseTime: 0, @@ -22,7 +22,7 @@ obfuscatedProfileId: 'Profile103', ); -final PurchaseWrapper dummyUnacknowledgedPurchase = PurchaseWrapper( +const PurchaseWrapper dummyUnacknowledgedPurchase = PurchaseWrapper( orderId: 'orderId', packageName: 'packageName', purchaseTime: 0, @@ -36,7 +36,7 @@ purchaseState: PurchaseStateWrapper.purchased, ); -final PurchaseHistoryRecordWrapper dummyPurchaseHistoryRecord = +const PurchaseHistoryRecordWrapper dummyPurchaseHistoryRecord = PurchaseHistoryRecordWrapper( purchaseTime: 0, signature: 'signature', @@ -46,7 +46,7 @@ developerPayload: 'dummy payload', ); -final PurchaseWrapper dummyOldPurchase = PurchaseWrapper( +const PurchaseWrapper dummyOldPurchase = PurchaseWrapper( orderId: 'oldOrderId', packageName: 'oldPackageName', purchaseTime: 0, @@ -63,7 +63,7 @@ void main() { group('PurchaseWrapper', () { test('converts from map', () { - final PurchaseWrapper expected = dummyPurchase; + const PurchaseWrapper expected = dummyPurchase; final PurchaseWrapper parsed = PurchaseWrapper.fromJson(buildPurchaseMap(expected)); @@ -109,7 +109,7 @@ group('PurchaseHistoryRecordWrapper', () { test('converts from map', () { - final PurchaseHistoryRecordWrapper expected = dummyPurchaseHistoryRecord; + const PurchaseHistoryRecordWrapper expected = dummyPurchaseHistoryRecord; final PurchaseHistoryRecordWrapper parsed = PurchaseHistoryRecordWrapper.fromJson( buildPurchaseHistoryRecordMap(expected)); @@ -120,13 +120,13 @@ group('PurchasesResultWrapper', () { test('parsed from map', () { - final BillingResponse responseCode = BillingResponse.ok; + const BillingResponse responseCode = BillingResponse.ok; final List<PurchaseWrapper> purchases = <PurchaseWrapper>[ dummyPurchase, dummyPurchase ]; const String debugMessage = 'dummy Message'; - final BillingResultWrapper billingResult = BillingResultWrapper( + const BillingResultWrapper billingResult = BillingResultWrapper( responseCode: responseCode, debugMessage: debugMessage); final PurchasesResultWrapper expected = PurchasesResultWrapper( billingResult: billingResult, @@ -135,7 +135,7 @@ final PurchasesResultWrapper parsed = PurchasesResultWrapper.fromJson(<String, dynamic>{ 'billingResult': buildBillingResultMap(billingResult), - 'responseCode': BillingResponseConverter().toJson(responseCode), + 'responseCode': const BillingResponseConverter().toJson(responseCode), 'purchasesList': <Map<String, dynamic>>[ buildPurchaseMap(dummyPurchase), buildPurchaseMap(dummyPurchase) @@ -148,10 +148,10 @@ test('parsed from empty map', () { final PurchasesResultWrapper parsed = - PurchasesResultWrapper.fromJson(<String, dynamic>{}); + PurchasesResultWrapper.fromJson(const <String, dynamic>{}); expect( parsed.billingResult, - equals(BillingResultWrapper( + equals(const BillingResultWrapper( responseCode: BillingResponse.error, debugMessage: kInvalidBillingResultErrorMessage))); expect(parsed.responseCode, BillingResponse.error); @@ -161,14 +161,14 @@ group('PurchasesHistoryResult', () { test('parsed from map', () { - final BillingResponse responseCode = BillingResponse.ok; + const BillingResponse responseCode = BillingResponse.ok; final List<PurchaseHistoryRecordWrapper> purchaseHistoryRecordList = <PurchaseHistoryRecordWrapper>[ dummyPurchaseHistoryRecord, dummyPurchaseHistoryRecord ]; const String debugMessage = 'dummy Message'; - final BillingResultWrapper billingResult = BillingResultWrapper( + const BillingResultWrapper billingResult = BillingResultWrapper( responseCode: responseCode, debugMessage: debugMessage); final PurchasesHistoryResult expected = PurchasesHistoryResult( billingResult: billingResult, @@ -188,10 +188,10 @@ test('parsed from empty map', () { final PurchasesHistoryResult parsed = - PurchasesHistoryResult.fromJson(<String, dynamic>{}); + PurchasesHistoryResult.fromJson(const <String, dynamic>{}); expect( parsed.billingResult, - equals(BillingResultWrapper( + equals(const BillingResultWrapper( responseCode: BillingResponse.error, debugMessage: kInvalidBillingResultErrorMessage))); expect(parsed.purchaseHistoryRecordList, isEmpty); @@ -210,7 +210,8 @@ 'isAutoRenewing': original.isAutoRenewing, 'originalJson': original.originalJson, 'developerPayload': original.developerPayload, - 'purchaseState': PurchaseStateConverter().toJson(original.purchaseState), + 'purchaseState': + const PurchaseStateConverter().toJson(original.purchaseState), 'isAcknowledged': original.isAcknowledged, 'obfuscatedAccountId': original.obfuscatedAccountId, 'obfuscatedProfileId': original.obfuscatedProfileId, @@ -231,7 +232,8 @@ Map<String, dynamic> buildBillingResultMap(BillingResultWrapper original) { return <String, dynamic>{ - 'responseCode': BillingResponseConverter().toJson(original.responseCode), + 'responseCode': + const BillingResponseConverter().toJson(original.responseCode), 'debugMessage': original.debugMessage, }; }
diff --git a/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/sku_details_wrapper_deprecated_test.dart b/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/sku_details_wrapper_deprecated_test.dart index 3e29d92..f27ea02 100644 --- a/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/sku_details_wrapper_deprecated_test.dart +++ b/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/sku_details_wrapper_deprecated_test.dart
@@ -13,7 +13,7 @@ test( 'Deprecated `introductoryPriceMicros` field reflects parameter from constructor', () { - final SkuDetailsWrapper skuDetails = SkuDetailsWrapper( + const SkuDetailsWrapper skuDetails = SkuDetailsWrapper( description: 'description', freeTrialPeriod: 'freeTrialPeriod', introductoryPrice: 'introductoryPrice', @@ -42,7 +42,7 @@ test( '`introductoryPriceAmoutMicros` constructor parameter is reflected by deprecated `introductoryPriceMicros` and `introductoryPriceAmountMicros` fields', () { - final SkuDetailsWrapper skuDetails = SkuDetailsWrapper( + const SkuDetailsWrapper skuDetails = SkuDetailsWrapper( description: 'description', freeTrialPeriod: 'freeTrialPeriod', introductoryPrice: 'introductoryPrice',
diff --git a/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/sku_details_wrapper_test.dart b/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/sku_details_wrapper_test.dart index 08cde07..ecc399b 100644 --- a/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/sku_details_wrapper_test.dart +++ b/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/sku_details_wrapper_test.dart
@@ -6,7 +6,7 @@ import 'package:in_app_purchase_android/src/types/google_play_product_details.dart'; import 'package:test/test.dart'; -final SkuDetailsWrapper dummySkuDetails = SkuDetailsWrapper( +const SkuDetailsWrapper dummySkuDetails = SkuDetailsWrapper( description: 'description', freeTrialPeriod: 'freeTrialPeriod', introductoryPrice: 'introductoryPrice', @@ -28,7 +28,7 @@ void main() { group('SkuDetailsWrapper', () { test('converts from map', () { - final SkuDetailsWrapper expected = dummySkuDetails; + const SkuDetailsWrapper expected = dummySkuDetails; final SkuDetailsWrapper parsed = SkuDetailsWrapper.fromJson(buildSkuMap(expected)); @@ -38,13 +38,13 @@ group('SkuDetailsResponseWrapper', () { test('parsed from map', () { - final BillingResponse responseCode = BillingResponse.ok; + const BillingResponse responseCode = BillingResponse.ok; const String debugMessage = 'dummy message'; final List<SkuDetailsWrapper> skusDetails = <SkuDetailsWrapper>[ dummySkuDetails, dummySkuDetails ]; - BillingResultWrapper result = BillingResultWrapper( + const BillingResultWrapper result = BillingResultWrapper( responseCode: responseCode, debugMessage: debugMessage); final SkuDetailsResponseWrapper expected = SkuDetailsResponseWrapper( billingResult: result, skuDetailsList: skusDetails); @@ -52,7 +52,7 @@ final SkuDetailsResponseWrapper parsed = SkuDetailsResponseWrapper.fromJson(<String, dynamic>{ 'billingResult': <String, dynamic>{ - 'responseCode': BillingResponseConverter().toJson(responseCode), + 'responseCode': const BillingResponseConverter().toJson(responseCode), 'debugMessage': debugMessage, }, 'skuDetailsList': <Map<String, dynamic>>[ @@ -78,10 +78,10 @@ }); test('handles empty list of skuDetails', () { - final BillingResponse responseCode = BillingResponse.error; + const BillingResponse responseCode = BillingResponse.error; const String debugMessage = 'dummy message'; final List<SkuDetailsWrapper> skusDetails = <SkuDetailsWrapper>[]; - BillingResultWrapper billingResult = BillingResultWrapper( + const BillingResultWrapper billingResult = BillingResultWrapper( responseCode: responseCode, debugMessage: debugMessage); final SkuDetailsResponseWrapper expected = SkuDetailsResponseWrapper( billingResult: billingResult, skuDetailsList: skusDetails); @@ -89,10 +89,10 @@ final SkuDetailsResponseWrapper parsed = SkuDetailsResponseWrapper.fromJson(<String, dynamic>{ 'billingResult': <String, dynamic>{ - 'responseCode': BillingResponseConverter().toJson(responseCode), + 'responseCode': const BillingResponseConverter().toJson(responseCode), 'debugMessage': debugMessage, }, - 'skuDetailsList': <Map<String, dynamic>>[] + 'skuDetailsList': const <Map<String, dynamic>>[] }); expect(parsed.billingResult, equals(expected.billingResult)); @@ -101,10 +101,10 @@ test('fromJson creates an object with default values', () { final SkuDetailsResponseWrapper skuDetails = - SkuDetailsResponseWrapper.fromJson(<String, dynamic>{}); + SkuDetailsResponseWrapper.fromJson(const <String, dynamic>{}); expect( skuDetails.billingResult, - equals(BillingResultWrapper( + equals(const BillingResultWrapper( responseCode: BillingResponse.error, debugMessage: kInvalidBillingResultErrorMessage))); expect(skuDetails.skuDetailsList, isEmpty); @@ -114,7 +114,7 @@ group('BillingResultWrapper', () { test('fromJson on empty map creates an object with default values', () { final BillingResultWrapper billingResult = - BillingResultWrapper.fromJson(<String, dynamic>{}); + BillingResultWrapper.fromJson(const <String, dynamic>{}); expect(billingResult.debugMessage, kInvalidBillingResultErrorMessage); expect(billingResult.responseCode, BillingResponse.error); });
diff --git a/packages/in_app_purchase/in_app_purchase_android/test/in_app_purchase_android_platform_addition_test.dart b/packages/in_app_purchase/in_app_purchase_android/test/in_app_purchase_android_platform_addition_test.dart index 112300d..9d2045b 100644 --- a/packages/in_app_purchase/in_app_purchase_android/test/in_app_purchase_android_platform_addition_test.dart +++ b/packages/in_app_purchase/in_app_purchase_android/test/in_app_purchase_android_platform_addition_test.dart
@@ -30,8 +30,8 @@ widgets.WidgetsFlutterBinding.ensureInitialized(); const String debugMessage = 'dummy message'; - final BillingResponse responseCode = BillingResponse.ok; - final BillingResultWrapper expectedBillingResult = BillingResultWrapper( + const BillingResponse responseCode = BillingResponse.ok; + const BillingResultWrapper expectedBillingResult = BillingResultWrapper( responseCode: responseCode, debugMessage: debugMessage); stubPlatform.addResponse( name: startConnectionCall, @@ -45,9 +45,9 @@ const String consumeMethodName = 'BillingClient#consumeAsync(String, ConsumeResponseListener)'; test('consume purchase async success', () async { - final BillingResponse expectedCode = BillingResponse.ok; + const BillingResponse expectedCode = BillingResponse.ok; const String debugMessage = 'dummy message'; - final BillingResultWrapper expectedBillingResult = BillingResultWrapper( + const BillingResultWrapper expectedBillingResult = BillingResultWrapper( responseCode: expectedCode, debugMessage: debugMessage); stubPlatform.addResponse( name: consumeMethodName, @@ -66,14 +66,14 @@ const String queryMethodName = 'BillingClient#queryPurchases(String)'; test('handles error', () async { const String debugMessage = 'dummy message'; - final BillingResponse responseCode = BillingResponse.developerError; - final BillingResultWrapper expectedBillingResult = BillingResultWrapper( + const BillingResponse responseCode = BillingResponse.developerError; + const BillingResultWrapper expectedBillingResult = BillingResultWrapper( responseCode: responseCode, debugMessage: debugMessage); stubPlatform .addResponse(name: queryMethodName, value: <dynamic, dynamic>{ 'billingResult': buildBillingResultMap(expectedBillingResult), - 'responseCode': BillingResponseConverter().toJson(responseCode), + 'responseCode': const BillingResponseConverter().toJson(responseCode), 'purchasesList': <Map<String, dynamic>>[] }); final QueryPurchaseDetailsResponse response = @@ -87,14 +87,14 @@ test('returns SkuDetailsResponseWrapper', () async { const String debugMessage = 'dummy message'; - final BillingResponse responseCode = BillingResponse.ok; - final BillingResultWrapper expectedBillingResult = BillingResultWrapper( + const BillingResponse responseCode = BillingResponse.ok; + const BillingResultWrapper expectedBillingResult = BillingResultWrapper( responseCode: responseCode, debugMessage: debugMessage); stubPlatform .addResponse(name: queryMethodName, value: <String, dynamic>{ 'billingResult': buildBillingResultMap(expectedBillingResult), - 'responseCode': BillingResponseConverter().toJson(responseCode), + 'responseCode': const BillingResponseConverter().toJson(responseCode), 'purchasesList': <Map<String, dynamic>>[ buildPurchaseMap(dummyPurchase), ] @@ -111,21 +111,22 @@ test('should store platform exception in the response', () async { const String debugMessage = 'dummy message'; - final BillingResponse responseCode = BillingResponse.developerError; - final BillingResultWrapper expectedBillingResult = BillingResultWrapper( + const BillingResponse responseCode = BillingResponse.developerError; + const BillingResultWrapper expectedBillingResult = BillingResultWrapper( responseCode: responseCode, debugMessage: debugMessage); stubPlatform.addResponse( name: queryMethodName, value: <dynamic, dynamic>{ - 'responseCode': BillingResponseConverter().toJson(responseCode), + 'responseCode': + const BillingResponseConverter().toJson(responseCode), 'billingResult': buildBillingResultMap(expectedBillingResult), 'purchasesList': <Map<String, dynamic>>[] }, - additionalStepBeforeReturn: (_) { + additionalStepBeforeReturn: (dynamic _) { throw PlatformException( code: 'error_code', message: 'error_message', - details: {'info': 'error_info'}, + details: <dynamic, dynamic>{'info': 'error_info'}, ); }); final QueryPurchaseDetailsResponse response = @@ -134,7 +135,8 @@ expect(response.error, isNotNull); expect(response.error!.code, 'error_code'); expect(response.error!.message, 'error_message'); - expect(response.error!.details, {'info': 'error_info'}); + expect( + response.error!.details, <String, dynamic>{'info': 'error_info'}); }); }); }); @@ -147,7 +149,8 @@ stubPlatform.addResponse( name: isFeatureSupportedMethodName, value: false, - additionalStepBeforeReturn: (value) => arguments = value, + additionalStepBeforeReturn: (dynamic value) => + arguments = value as Map<dynamic, dynamic>, ); final bool isSupported = await iapAndroidPlatformAddition .isFeatureSupported(BillingClientFeature.subscriptions); @@ -160,7 +163,8 @@ stubPlatform.addResponse( name: isFeatureSupportedMethodName, value: true, - additionalStepBeforeReturn: (value) => arguments = value, + additionalStepBeforeReturn: (dynamic value) => + arguments = value as Map<dynamic, dynamic>, ); final bool isSupported = await iapAndroidPlatformAddition .isFeatureSupported(BillingClientFeature.subscriptions); @@ -172,9 +176,10 @@ group('launchPriceChangeConfirmationFlow', () { const String launchPriceChangeConfirmationFlowMethodName = 'BillingClient#launchPriceChangeConfirmationFlow (Activity, PriceChangeFlowParams, PriceChangeConfirmationListener)'; - const dummySku = 'sku'; + const String dummySku = 'sku'; - final expectedBillingResultPriceChangeConfirmation = BillingResultWrapper( + const BillingResultWrapper expectedBillingResultPriceChangeConfirmation = + BillingResultWrapper( responseCode: BillingResponse.ok, debugMessage: 'dummy message', );
diff --git a/packages/in_app_purchase/in_app_purchase_android/test/in_app_purchase_android_platform_test.dart b/packages/in_app_purchase/in_app_purchase_android/test/in_app_purchase_android_platform_test.dart index 9c167e5..b19d631 100644 --- a/packages/in_app_purchase/in_app_purchase_android/test/in_app_purchase_android_platform_test.dart +++ b/packages/in_app_purchase/in_app_purchase_android/test/in_app_purchase_android_platform_test.dart
@@ -33,8 +33,8 @@ widgets.WidgetsFlutterBinding.ensureInitialized(); const String debugMessage = 'dummy message'; - final BillingResponse responseCode = BillingResponse.ok; - final BillingResultWrapper expectedBillingResult = BillingResultWrapper( + const BillingResponse responseCode = BillingResponse.ok; + const BillingResultWrapper expectedBillingResult = BillingResultWrapper( responseCode: responseCode, debugMessage: debugMessage); stubPlatform.addResponse( name: startConnectionCall, @@ -70,28 +70,28 @@ }); group('querySkuDetails', () { - final String queryMethodName = + const String queryMethodName = 'BillingClient#querySkuDetailsAsync(SkuDetailsParams, SkuDetailsResponseListener)'; test('handles empty skuDetails', () async { const String debugMessage = 'dummy message'; - final BillingResponse responseCode = BillingResponse.ok; - final BillingResultWrapper expectedBillingResult = BillingResultWrapper( + const BillingResponse responseCode = BillingResponse.ok; + const BillingResultWrapper expectedBillingResult = BillingResultWrapper( responseCode: responseCode, debugMessage: debugMessage); stubPlatform.addResponse(name: queryMethodName, value: <String, dynamic>{ 'billingResult': buildBillingResultMap(expectedBillingResult), - 'skuDetailsList': [], + 'skuDetailsList': <Map<String, dynamic>>[], }); final ProductDetailsResponse response = - await iapAndroidPlatform.queryProductDetails(<String>[''].toSet()); + await iapAndroidPlatform.queryProductDetails(<String>{''}); expect(response.productDetails, isEmpty); }); test('should get correct product details', () async { const String debugMessage = 'dummy message'; - final BillingResponse responseCode = BillingResponse.ok; - final BillingResultWrapper expectedBillingResult = BillingResultWrapper( + const BillingResponse responseCode = BillingResponse.ok; + const BillingResultWrapper expectedBillingResult = BillingResultWrapper( responseCode: responseCode, debugMessage: debugMessage); stubPlatform.addResponse(name: queryMethodName, value: <String, dynamic>{ 'billingResult': buildBillingResultMap(expectedBillingResult), @@ -99,8 +99,8 @@ }); // Since queryProductDetails makes 2 platform method calls (one for each SkuType), the result will contain 2 dummyWrapper instead // of 1. - final ProductDetailsResponse response = await iapAndroidPlatform - .queryProductDetails(<String>['valid'].toSet()); + final ProductDetailsResponse response = + await iapAndroidPlatform.queryProductDetails(<String>{'valid'}); expect(response.productDetails.first.title, dummySkuDetails.title); expect(response.productDetails.first.description, dummySkuDetails.description); @@ -110,8 +110,8 @@ test('should get the correct notFoundIDs', () async { const String debugMessage = 'dummy message'; - final BillingResponse responseCode = BillingResponse.ok; - final BillingResultWrapper expectedBillingResult = BillingResultWrapper( + const BillingResponse responseCode = BillingResponse.ok; + const BillingResultWrapper expectedBillingResult = BillingResultWrapper( responseCode: responseCode, debugMessage: debugMessage); stubPlatform.addResponse(name: queryMethodName, value: <String, dynamic>{ 'billingResult': buildBillingResultMap(expectedBillingResult), @@ -119,41 +119,42 @@ }); // Since queryProductDetails makes 2 platform method calls (one for each SkuType), the result will contain 2 dummyWrapper instead // of 1. - final ProductDetailsResponse response = await iapAndroidPlatform - .queryProductDetails(<String>['invalid'].toSet()); + final ProductDetailsResponse response = + await iapAndroidPlatform.queryProductDetails(<String>{'invalid'}); expect(response.notFoundIDs.first, 'invalid'); }); test( 'should have error stored in the response when platform exception is thrown', () async { - final BillingResponse responseCode = BillingResponse.ok; + const BillingResponse responseCode = BillingResponse.ok; stubPlatform.addResponse( name: queryMethodName, value: <String, dynamic>{ - 'responseCode': BillingResponseConverter().toJson(responseCode), + 'responseCode': + const BillingResponseConverter().toJson(responseCode), 'skuDetailsList': <Map<String, dynamic>>[ buildSkuMap(dummySkuDetails) ] }, - additionalStepBeforeReturn: (_) { + additionalStepBeforeReturn: (dynamic _) { throw PlatformException( code: 'error_code', message: 'error_message', - details: {'info': 'error_info'}, + details: <dynamic, dynamic>{'info': 'error_info'}, ); }); // Since queryProductDetails makes 2 platform method calls (one for each SkuType), the result will contain 2 dummyWrapper instead // of 1. - final ProductDetailsResponse response = await iapAndroidPlatform - .queryProductDetails(<String>['invalid'].toSet()); - expect(response.notFoundIDs, ['invalid']); + final ProductDetailsResponse response = + await iapAndroidPlatform.queryProductDetails(<String>{'invalid'}); + expect(response.notFoundIDs, <String>['invalid']); expect(response.productDetails, isEmpty); expect(response.error, isNotNull); expect(response.error!.source, kIAPSource); expect(response.error!.code, 'error_code'); expect(response.error!.message, 'error_message'); - expect(response.error!.details, {'info': 'error_info'}); + expect(response.error!.details, <String, dynamic>{'info': 'error_info'}); }); }); @@ -161,13 +162,13 @@ const String queryMethodName = 'BillingClient#queryPurchases(String)'; test('handles error', () async { const String debugMessage = 'dummy message'; - final BillingResponse responseCode = BillingResponse.developerError; - final BillingResultWrapper expectedBillingResult = BillingResultWrapper( + const BillingResponse responseCode = BillingResponse.developerError; + const BillingResultWrapper expectedBillingResult = BillingResultWrapper( responseCode: responseCode, debugMessage: debugMessage); stubPlatform.addResponse(name: queryMethodName, value: <dynamic, dynamic>{ 'billingResult': buildBillingResultMap(expectedBillingResult), - 'responseCode': BillingResponseConverter().toJson(responseCode), + 'responseCode': const BillingResponseConverter().toJson(responseCode), 'purchasesList': <Map<String, dynamic>>[] }); @@ -175,9 +176,12 @@ iapAndroidPlatform.restorePurchases(), throwsA( isA<InAppPurchaseException>() - .having((e) => e.source, 'source', kIAPSource) - .having((e) => e.code, 'code', kRestoredPurchaseErrorCode) - .having((e) => e.message, 'message', responseCode.toString()), + .having( + (InAppPurchaseException e) => e.source, 'source', kIAPSource) + .having((InAppPurchaseException e) => e.code, 'code', + kRestoredPurchaseErrorCode) + .having((InAppPurchaseException e) => e.message, 'message', + responseCode.toString()), ), ); }); @@ -185,21 +189,22 @@ test('should store platform exception in the response', () async { const String debugMessage = 'dummy message'; - final BillingResponse responseCode = BillingResponse.developerError; - final BillingResultWrapper expectedBillingResult = BillingResultWrapper( + const BillingResponse responseCode = BillingResponse.developerError; + const BillingResultWrapper expectedBillingResult = BillingResultWrapper( responseCode: responseCode, debugMessage: debugMessage); stubPlatform.addResponse( name: queryMethodName, value: <dynamic, dynamic>{ - 'responseCode': BillingResponseConverter().toJson(responseCode), + 'responseCode': + const BillingResponseConverter().toJson(responseCode), 'billingResult': buildBillingResultMap(expectedBillingResult), 'purchasesList': <Map<String, dynamic>>[] }, - additionalStepBeforeReturn: (_) { + additionalStepBeforeReturn: (dynamic _) { throw PlatformException( code: 'error_code', message: 'error_message', - details: {'info': 'error_info'}, + details: <dynamic, dynamic>{'info': 'error_info'}, ); }); @@ -207,19 +212,23 @@ iapAndroidPlatform.restorePurchases(), throwsA( isA<PlatformException>() - .having((e) => e.code, 'code', 'error_code') - .having((e) => e.message, 'message', 'error_message') - .having((e) => e.details, 'details', {'info': 'error_info'}), + .having((PlatformException e) => e.code, 'code', 'error_code') + .having((PlatformException e) => e.message, 'message', + 'error_message') + .having((PlatformException e) => e.details, 'details', + <String, dynamic>{'info': 'error_info'}), ), ); }); test('returns SkuDetailsResponseWrapper', () async { - Completer completer = Completer(); - Stream<List<PurchaseDetails>> stream = iapAndroidPlatform.purchaseStream; + final Completer<List<PurchaseDetails>> completer = + Completer<List<PurchaseDetails>>(); + final Stream<List<PurchaseDetails>> stream = + iapAndroidPlatform.purchaseStream; - late StreamSubscription subscription; - subscription = stream.listen((purchaseDetailsList) { + late StreamSubscription<List<PurchaseDetails>> subscription; + subscription = stream.listen((List<PurchaseDetails> purchaseDetailsList) { if (purchaseDetailsList.first.status == PurchaseStatus.restored) { completer.complete(purchaseDetailsList); subscription.cancel(); @@ -227,13 +236,13 @@ }); const String debugMessage = 'dummy message'; - final BillingResponse responseCode = BillingResponse.ok; - final BillingResultWrapper expectedBillingResult = BillingResultWrapper( + const BillingResponse responseCode = BillingResponse.ok; + const BillingResultWrapper expectedBillingResult = BillingResultWrapper( responseCode: responseCode, debugMessage: debugMessage); stubPlatform.addResponse(name: queryMethodName, value: <String, dynamic>{ 'billingResult': buildBillingResultMap(expectedBillingResult), - 'responseCode': BillingResponseConverter().toJson(responseCode), + 'responseCode': const BillingResponseConverter().toJson(responseCode), 'purchasesList': <Map<String, dynamic>>[ buildPurchaseMap(dummyPurchase), ] @@ -246,8 +255,8 @@ final List<PurchaseDetails> restoredPurchases = await completer.future; expect(restoredPurchases.length, 2); - restoredPurchases.forEach((element) { - GooglePlayPurchaseDetails purchase = + for (final PurchaseDetails element in restoredPurchases) { + final GooglePlayPurchaseDetails purchase = element as GooglePlayPurchaseDetails; expect(purchase.productID, dummyPurchase.sku); @@ -260,40 +269,41 @@ expect(purchase.transactionDate, dummyPurchase.purchaseTime.toString()); expect(purchase.billingClientPurchase, dummyPurchase); expect(purchase.status, PurchaseStatus.restored); - }); + } }); }); group('make payment', () { - final String launchMethodName = + const String launchMethodName = 'BillingClient#launchBillingFlow(Activity, BillingFlowParams)'; const String consumeMethodName = 'BillingClient#consumeAsync(String, ConsumeResponseListener)'; test('buy non consumable, serializes and deserializes data', () async { - final SkuDetailsWrapper skuDetails = dummySkuDetails; - final String accountId = "hashedAccountId"; + const SkuDetailsWrapper skuDetails = dummySkuDetails; + const String accountId = 'hashedAccountId'; const String debugMessage = 'dummy message'; - final BillingResponse sentCode = BillingResponse.ok; - final BillingResultWrapper expectedBillingResult = BillingResultWrapper( + const BillingResponse sentCode = BillingResponse.ok; + const BillingResultWrapper expectedBillingResult = BillingResultWrapper( responseCode: sentCode, debugMessage: debugMessage); stubPlatform.addResponse( name: launchMethodName, value: buildBillingResultMap(expectedBillingResult), - additionalStepBeforeReturn: (_) { + additionalStepBeforeReturn: (dynamic _) { // Mock java update purchase callback. - MethodCall call = MethodCall(kOnPurchasesUpdated, { + final MethodCall call = + MethodCall(kOnPurchasesUpdated, <dynamic, dynamic>{ 'billingResult': buildBillingResultMap(expectedBillingResult), - 'responseCode': BillingResponseConverter().toJson(sentCode), - 'purchasesList': [ - { + 'responseCode': const BillingResponseConverter().toJson(sentCode), + 'purchasesList': <dynamic>[ + <dynamic, dynamic>{ 'orderId': 'orderID1', 'sku': skuDetails.sku, 'isAutoRenewing': false, - 'packageName': "package", + 'packageName': 'package', 'purchaseTime': 1231231231, - 'purchaseToken': "token", + 'purchaseToken': 'token', 'signature': 'sign', 'originalJson': 'json', 'developerPayload': 'dummy payload', @@ -304,10 +314,11 @@ }); iapAndroidPlatform.billingClient.callHandler(call); }); - Completer completer = Completer(); + final Completer<PurchaseDetails> completer = Completer<PurchaseDetails>(); PurchaseDetails purchaseDetails; - Stream purchaseStream = iapAndroidPlatform.purchaseStream; - late StreamSubscription subscription; + final Stream<List<PurchaseDetails>> purchaseStream = + iapAndroidPlatform.purchaseStream; + late StreamSubscription<List<PurchaseDetails>> subscription; subscription = purchaseStream.listen((_) { purchaseDetails = _.first; completer.complete(purchaseDetails); @@ -319,7 +330,7 @@ final bool launchResult = await iapAndroidPlatform.buyNonConsumable( purchaseParam: purchaseParam); - PurchaseDetails result = await completer.future; + final PurchaseDetails result = await completer.future; expect(launchResult, isTrue); expect(result.purchaseID, 'orderID1'); expect(result.status, PurchaseStatus.purchased); @@ -327,29 +338,31 @@ }); test('handles an error with an empty purchases list', () async { - final SkuDetailsWrapper skuDetails = dummySkuDetails; - final String accountId = "hashedAccountId"; + const SkuDetailsWrapper skuDetails = dummySkuDetails; + const String accountId = 'hashedAccountId'; const String debugMessage = 'dummy message'; - final BillingResponse sentCode = BillingResponse.error; - final BillingResultWrapper expectedBillingResult = BillingResultWrapper( + const BillingResponse sentCode = BillingResponse.error; + const BillingResultWrapper expectedBillingResult = BillingResultWrapper( responseCode: sentCode, debugMessage: debugMessage); stubPlatform.addResponse( name: launchMethodName, value: buildBillingResultMap(expectedBillingResult), - additionalStepBeforeReturn: (_) { + additionalStepBeforeReturn: (dynamic _) { // Mock java update purchase callback. - MethodCall call = MethodCall(kOnPurchasesUpdated, { + final MethodCall call = + MethodCall(kOnPurchasesUpdated, <dynamic, dynamic>{ 'billingResult': buildBillingResultMap(expectedBillingResult), - 'responseCode': BillingResponseConverter().toJson(sentCode), - 'purchasesList': [] + 'responseCode': const BillingResponseConverter().toJson(sentCode), + 'purchasesList': const <dynamic>[] }); iapAndroidPlatform.billingClient.callHandler(call); }); - Completer completer = Completer(); + final Completer<PurchaseDetails> completer = Completer<PurchaseDetails>(); PurchaseDetails purchaseDetails; - Stream purchaseStream = iapAndroidPlatform.purchaseStream; - late StreamSubscription subscription; + final Stream<List<PurchaseDetails>> purchaseStream = + iapAndroidPlatform.purchaseStream; + late StreamSubscription<List<PurchaseDetails>> subscription; subscription = purchaseStream.listen((_) { purchaseDetails = _.first; completer.complete(purchaseDetails); @@ -359,7 +372,7 @@ productDetails: GooglePlayProductDetails.fromSkuDetails(skuDetails), applicationUserName: accountId); await iapAndroidPlatform.buyNonConsumable(purchaseParam: purchaseParam); - PurchaseDetails result = await completer.future; + final PurchaseDetails result = await completer.future; expect(result.error, isNotNull); expect(result.error!.source, kIAPSource); @@ -369,29 +382,30 @@ test('buy consumable with auto consume, serializes and deserializes data', () async { - final SkuDetailsWrapper skuDetails = dummySkuDetails; - final String accountId = "hashedAccountId"; + const SkuDetailsWrapper skuDetails = dummySkuDetails; + const String accountId = 'hashedAccountId'; const String debugMessage = 'dummy message'; - final BillingResponse sentCode = BillingResponse.ok; - final BillingResultWrapper expectedBillingResult = BillingResultWrapper( + const BillingResponse sentCode = BillingResponse.ok; + const BillingResultWrapper expectedBillingResult = BillingResultWrapper( responseCode: sentCode, debugMessage: debugMessage); stubPlatform.addResponse( name: launchMethodName, value: buildBillingResultMap(expectedBillingResult), - additionalStepBeforeReturn: (_) { + additionalStepBeforeReturn: (dynamic _) { // Mock java update purchase callback. - MethodCall call = MethodCall(kOnPurchasesUpdated, { + final MethodCall call = + MethodCall(kOnPurchasesUpdated, <dynamic, dynamic>{ 'billingResult': buildBillingResultMap(expectedBillingResult), - 'responseCode': BillingResponseConverter().toJson(sentCode), - 'purchasesList': [ - { + 'responseCode': const BillingResponseConverter().toJson(sentCode), + 'purchasesList': <dynamic>[ + <dynamic, dynamic>{ 'orderId': 'orderID1', 'sku': skuDetails.sku, 'isAutoRenewing': false, - 'packageName': "package", + 'packageName': 'package', 'purchaseTime': 1231231231, - 'purchaseToken': "token", + 'purchaseToken': 'token', 'signature': 'sign', 'originalJson': 'json', 'developerPayload': 'dummy payload', @@ -402,24 +416,25 @@ }); iapAndroidPlatform.billingClient.callHandler(call); }); - Completer consumeCompleter = Completer(); + final Completer<String> consumeCompleter = Completer<String>(); // adding call back for consume purchase - final BillingResponse expectedCode = BillingResponse.ok; - final BillingResultWrapper expectedBillingResultForConsume = + const BillingResponse expectedCode = BillingResponse.ok; + const BillingResultWrapper expectedBillingResultForConsume = BillingResultWrapper( responseCode: expectedCode, debugMessage: debugMessage); stubPlatform.addResponse( name: consumeMethodName, value: buildBillingResultMap(expectedBillingResultForConsume), additionalStepBeforeReturn: (dynamic args) { - String purchaseToken = args['purchaseToken']; - consumeCompleter.complete((purchaseToken)); + final String purchaseToken = args['purchaseToken'] as String; + consumeCompleter.complete(purchaseToken); }); - Completer completer = Completer(); + final Completer<PurchaseDetails> completer = Completer<PurchaseDetails>(); PurchaseDetails purchaseDetails; - Stream purchaseStream = iapAndroidPlatform.purchaseStream; - late StreamSubscription subscription; + final Stream<List<PurchaseDetails>> purchaseStream = + iapAndroidPlatform.purchaseStream; + late StreamSubscription<List<PurchaseDetails>> subscription; subscription = purchaseStream.listen((_) { purchaseDetails = _.first; completer.complete(purchaseDetails); @@ -432,7 +447,8 @@ await iapAndroidPlatform.buyConsumable(purchaseParam: purchaseParam); // Verify that the result has succeeded - GooglePlayPurchaseDetails result = await completer.future; + final GooglePlayPurchaseDetails result = + await completer.future as GooglePlayPurchaseDetails; expect(launchResult, isTrue); expect(result.billingClientPurchase, isNotNull); expect(result.billingClientPurchase.purchaseToken, @@ -444,8 +460,8 @@ test('buyNonConsumable propagates failures to launch the billing flow', () async { const String debugMessage = 'dummy message'; - final BillingResponse sentCode = BillingResponse.error; - final BillingResultWrapper expectedBillingResult = BillingResultWrapper( + const BillingResponse sentCode = BillingResponse.error; + const BillingResultWrapper expectedBillingResult = BillingResultWrapper( responseCode: sentCode, debugMessage: debugMessage); stubPlatform.addResponse( name: launchMethodName, @@ -463,8 +479,8 @@ test('buyConsumable propagates failures to launch the billing flow', () async { const String debugMessage = 'dummy message'; - final BillingResponse sentCode = BillingResponse.developerError; - final BillingResultWrapper expectedBillingResult = BillingResultWrapper( + const BillingResponse sentCode = BillingResponse.developerError; + const BillingResultWrapper expectedBillingResult = BillingResultWrapper( responseCode: sentCode, debugMessage: debugMessage); stubPlatform.addResponse( name: launchMethodName, @@ -481,28 +497,29 @@ }); test('adds consumption failures to PurchaseDetails objects', () async { - final SkuDetailsWrapper skuDetails = dummySkuDetails; - final String accountId = "hashedAccountId"; + const SkuDetailsWrapper skuDetails = dummySkuDetails; + const String accountId = 'hashedAccountId'; const String debugMessage = 'dummy message'; - final BillingResponse sentCode = BillingResponse.ok; - final BillingResultWrapper expectedBillingResult = BillingResultWrapper( + const BillingResponse sentCode = BillingResponse.ok; + const BillingResultWrapper expectedBillingResult = BillingResultWrapper( responseCode: sentCode, debugMessage: debugMessage); stubPlatform.addResponse( name: launchMethodName, value: buildBillingResultMap(expectedBillingResult), - additionalStepBeforeReturn: (_) { + additionalStepBeforeReturn: (dynamic _) { // Mock java update purchase callback. - MethodCall call = MethodCall(kOnPurchasesUpdated, { + final MethodCall call = + MethodCall(kOnPurchasesUpdated, <dynamic, dynamic>{ 'billingResult': buildBillingResultMap(expectedBillingResult), - 'responseCode': BillingResponseConverter().toJson(sentCode), - 'purchasesList': [ - { + 'responseCode': const BillingResponseConverter().toJson(sentCode), + 'purchasesList': <dynamic>[ + <dynamic, dynamic>{ 'orderId': 'orderID1', 'sku': skuDetails.sku, 'isAutoRenewing': false, - 'packageName': "package", + 'packageName': 'package', 'purchaseTime': 1231231231, - 'purchaseToken': "token", + 'purchaseToken': 'token', 'signature': 'sign', 'originalJson': 'json', 'developerPayload': 'dummy payload', @@ -513,24 +530,25 @@ }); iapAndroidPlatform.billingClient.callHandler(call); }); - Completer consumeCompleter = Completer(); + final Completer<String> consumeCompleter = Completer<String>(); // adding call back for consume purchase - final BillingResponse expectedCode = BillingResponse.error; - final BillingResultWrapper expectedBillingResultForConsume = + const BillingResponse expectedCode = BillingResponse.error; + const BillingResultWrapper expectedBillingResultForConsume = BillingResultWrapper( responseCode: expectedCode, debugMessage: debugMessage); stubPlatform.addResponse( name: consumeMethodName, value: buildBillingResultMap(expectedBillingResultForConsume), additionalStepBeforeReturn: (dynamic args) { - String purchaseToken = args['purchaseToken']; + final String purchaseToken = args['purchaseToken'] as String; consumeCompleter.complete(purchaseToken); }); - Completer completer = Completer(); + final Completer<PurchaseDetails> completer = Completer<PurchaseDetails>(); PurchaseDetails purchaseDetails; - Stream purchaseStream = iapAndroidPlatform.purchaseStream; - late StreamSubscription subscription; + final Stream<List<PurchaseDetails>> purchaseStream = + iapAndroidPlatform.purchaseStream; + late StreamSubscription<List<PurchaseDetails>> subscription; subscription = purchaseStream.listen((_) { purchaseDetails = _.first; completer.complete(purchaseDetails); @@ -542,7 +560,8 @@ await iapAndroidPlatform.buyConsumable(purchaseParam: purchaseParam); // Verify that the result has an error for the failed consumption - GooglePlayPurchaseDetails result = await completer.future; + final GooglePlayPurchaseDetails result = + await completer.future as GooglePlayPurchaseDetails; expect(result.billingClientPurchase, isNotNull); expect(result.billingClientPurchase.purchaseToken, await consumeCompleter.future); @@ -554,29 +573,30 @@ test( 'buy consumable without auto consume, consume api should not receive calls', () async { - final SkuDetailsWrapper skuDetails = dummySkuDetails; - final String accountId = "hashedAccountId"; + const SkuDetailsWrapper skuDetails = dummySkuDetails; + const String accountId = 'hashedAccountId'; const String debugMessage = 'dummy message'; - final BillingResponse sentCode = BillingResponse.developerError; - final BillingResultWrapper expectedBillingResult = BillingResultWrapper( + const BillingResponse sentCode = BillingResponse.developerError; + const BillingResultWrapper expectedBillingResult = BillingResultWrapper( responseCode: sentCode, debugMessage: debugMessage); stubPlatform.addResponse( name: launchMethodName, value: buildBillingResultMap(expectedBillingResult), - additionalStepBeforeReturn: (_) { + additionalStepBeforeReturn: (dynamic _) { // Mock java update purchase callback. - MethodCall call = MethodCall(kOnPurchasesUpdated, { + final MethodCall call = + MethodCall(kOnPurchasesUpdated, <dynamic, dynamic>{ 'billingResult': buildBillingResultMap(expectedBillingResult), - 'responseCode': BillingResponseConverter().toJson(sentCode), - 'purchasesList': [ - { + 'responseCode': const BillingResponseConverter().toJson(sentCode), + 'purchasesList': <dynamic>[ + <dynamic, dynamic>{ 'orderId': 'orderID1', 'sku': skuDetails.sku, 'isAutoRenewing': false, - 'packageName': "package", + 'packageName': 'package', 'purchaseTime': 1231231231, - 'purchaseToken': "token", + 'purchaseToken': 'token', 'signature': 'sign', 'originalJson': 'json', 'developerPayload': 'dummy payload', @@ -587,22 +607,23 @@ }); iapAndroidPlatform.billingClient.callHandler(call); }); - Completer consumeCompleter = Completer(); + final Completer<String?> consumeCompleter = Completer<String?>(); // adding call back for consume purchase - final BillingResponse expectedCode = BillingResponse.ok; - final BillingResultWrapper expectedBillingResultForConsume = + const BillingResponse expectedCode = BillingResponse.ok; + const BillingResultWrapper expectedBillingResultForConsume = BillingResultWrapper( responseCode: expectedCode, debugMessage: debugMessage); stubPlatform.addResponse( name: consumeMethodName, value: buildBillingResultMap(expectedBillingResultForConsume), additionalStepBeforeReturn: (dynamic args) { - String purchaseToken = args['purchaseToken']; - consumeCompleter.complete((purchaseToken)); + final String purchaseToken = args['purchaseToken'] as String; + consumeCompleter.complete(purchaseToken); }); - Stream purchaseStream = iapAndroidPlatform.purchaseStream; - late StreamSubscription subscription; + final Stream<List<PurchaseDetails>> purchaseStream = + iapAndroidPlatform.purchaseStream; + late StreamSubscription<List<PurchaseDetails>> subscription; subscription = purchaseStream.listen((_) { consumeCompleter.complete(null); subscription.cancel(); @@ -618,28 +639,29 @@ test( 'should get canceled purchase status when response code is BillingResponse.userCanceled', () async { - final SkuDetailsWrapper skuDetails = dummySkuDetails; - final String accountId = "hashedAccountId"; + const SkuDetailsWrapper skuDetails = dummySkuDetails; + const String accountId = 'hashedAccountId'; const String debugMessage = 'dummy message'; - final BillingResponse sentCode = BillingResponse.userCanceled; - final BillingResultWrapper expectedBillingResult = BillingResultWrapper( + const BillingResponse sentCode = BillingResponse.userCanceled; + const BillingResultWrapper expectedBillingResult = BillingResultWrapper( responseCode: sentCode, debugMessage: debugMessage); stubPlatform.addResponse( name: launchMethodName, value: buildBillingResultMap(expectedBillingResult), - additionalStepBeforeReturn: (_) { + additionalStepBeforeReturn: (dynamic _) { // Mock java update purchase callback. - MethodCall call = MethodCall(kOnPurchasesUpdated, { + final MethodCall call = + MethodCall(kOnPurchasesUpdated, <dynamic, dynamic>{ 'billingResult': buildBillingResultMap(expectedBillingResult), - 'responseCode': BillingResponseConverter().toJson(sentCode), - 'purchasesList': [ - { + 'responseCode': const BillingResponseConverter().toJson(sentCode), + 'purchasesList': <dynamic>[ + <dynamic, dynamic>{ 'orderId': 'orderID1', 'sku': skuDetails.sku, 'isAutoRenewing': false, - 'packageName': "package", + 'packageName': 'package', 'purchaseTime': 1231231231, - 'purchaseToken': "token", + 'purchaseToken': 'token', 'signature': 'sign', 'originalJson': 'json', 'developerPayload': 'dummy payload', @@ -650,24 +672,25 @@ }); iapAndroidPlatform.billingClient.callHandler(call); }); - Completer consumeCompleter = Completer(); + final Completer<String> consumeCompleter = Completer<String>(); // adding call back for consume purchase - final BillingResponse expectedCode = BillingResponse.userCanceled; - final BillingResultWrapper expectedBillingResultForConsume = + const BillingResponse expectedCode = BillingResponse.userCanceled; + const BillingResultWrapper expectedBillingResultForConsume = BillingResultWrapper( responseCode: expectedCode, debugMessage: debugMessage); stubPlatform.addResponse( name: consumeMethodName, value: buildBillingResultMap(expectedBillingResultForConsume), additionalStepBeforeReturn: (dynamic args) { - String purchaseToken = args['purchaseToken']; + final String purchaseToken = args['purchaseToken'] as String; consumeCompleter.complete(purchaseToken); }); - Completer completer = Completer(); + final Completer<PurchaseDetails> completer = Completer<PurchaseDetails>(); PurchaseDetails purchaseDetails; - Stream purchaseStream = iapAndroidPlatform.purchaseStream; - late StreamSubscription subscription; + final Stream<List<PurchaseDetails>> purchaseStream = + iapAndroidPlatform.purchaseStream; + late StreamSubscription<List<PurchaseDetails>> subscription; subscription = purchaseStream.listen((_) { purchaseDetails = _.first; completer.complete(purchaseDetails); @@ -679,36 +702,39 @@ await iapAndroidPlatform.buyConsumable(purchaseParam: purchaseParam); // Verify that the result has an error for the failed consumption - GooglePlayPurchaseDetails result = await completer.future; + final GooglePlayPurchaseDetails result = + await completer.future as GooglePlayPurchaseDetails; expect(result.status, PurchaseStatus.canceled); }); test( 'should get purchased purchase status when upgrading subscription by deferred proration mode', () async { - final SkuDetailsWrapper skuDetails = dummySkuDetails; - final String accountId = "hashedAccountId"; + const SkuDetailsWrapper skuDetails = dummySkuDetails; + const String accountId = 'hashedAccountId'; const String debugMessage = 'dummy message'; - final BillingResponse sentCode = BillingResponse.ok; - final BillingResultWrapper expectedBillingResult = BillingResultWrapper( + const BillingResponse sentCode = BillingResponse.ok; + const BillingResultWrapper expectedBillingResult = BillingResultWrapper( responseCode: sentCode, debugMessage: debugMessage); stubPlatform.addResponse( name: launchMethodName, value: buildBillingResultMap(expectedBillingResult), - additionalStepBeforeReturn: (_) { + additionalStepBeforeReturn: (dynamic _) { // Mock java update purchase callback. - MethodCall call = MethodCall(kOnPurchasesUpdated, { + final MethodCall call = + MethodCall(kOnPurchasesUpdated, <dynamic, dynamic>{ 'billingResult': buildBillingResultMap(expectedBillingResult), - 'responseCode': BillingResponseConverter().toJson(sentCode), - 'purchasesList': [] + 'responseCode': const BillingResponseConverter().toJson(sentCode), + 'purchasesList': const <dynamic>[] }); iapAndroidPlatform.billingClient.callHandler(call); }); - Completer completer = Completer(); + final Completer<PurchaseDetails> completer = Completer<PurchaseDetails>(); PurchaseDetails purchaseDetails; - Stream purchaseStream = iapAndroidPlatform.purchaseStream; - late StreamSubscription subscription; + final Stream<List<PurchaseDetails>> purchaseStream = + iapAndroidPlatform.purchaseStream; + late StreamSubscription<List<PurchaseDetails>> subscription; subscription = purchaseStream.listen((_) { purchaseDetails = _.first; completer.complete(purchaseDetails); @@ -724,7 +750,7 @@ )); await iapAndroidPlatform.buyNonConsumable(purchaseParam: purchaseParam); - PurchaseDetails result = await completer.future; + final PurchaseDetails result = await completer.future; expect(result.status, PurchaseStatus.purchased); }); }); @@ -733,17 +759,18 @@ const String completeMethodName = 'BillingClient#(AcknowledgePurchaseParams params, (AcknowledgePurchaseParams, AcknowledgePurchaseResponseListener)'; test('complete purchase success', () async { - final BillingResponse expectedCode = BillingResponse.ok; + const BillingResponse expectedCode = BillingResponse.ok; const String debugMessage = 'dummy message'; - final BillingResultWrapper expectedBillingResult = BillingResultWrapper( + const BillingResultWrapper expectedBillingResult = BillingResultWrapper( responseCode: expectedCode, debugMessage: debugMessage); stubPlatform.addResponse( name: completeMethodName, value: buildBillingResultMap(expectedBillingResult), ); - PurchaseDetails purchaseDetails = + final PurchaseDetails purchaseDetails = GooglePlayPurchaseDetails.fromPurchase(dummyUnacknowledgedPurchase); - Completer completer = Completer(); + final Completer<BillingResultWrapper> completer = + Completer<BillingResultWrapper>(); purchaseDetails.status = PurchaseStatus.purchased; if (purchaseDetails.pendingCompletePurchase) { final BillingResultWrapper billingResultWrapper =
diff --git a/packages/in_app_purchase/in_app_purchase_android/test/stub_in_app_purchase_platform.dart b/packages/in_app_purchase/in_app_purchase_android/test/stub_in_app_purchase_platform.dart index 11a3426..75972e6 100644 --- a/packages/in_app_purchase/in_app_purchase_android/test/stub_in_app_purchase_platform.dart +++ b/packages/in_app_purchase/in_app_purchase_android/test/stub_in_app_purchase_platform.dart
@@ -5,11 +5,12 @@ import 'dart:async'; import 'package:flutter/services.dart'; -typedef void AdditionalSteps(dynamic args); +typedef AdditionalSteps = void Function(dynamic args); class StubInAppPurchasePlatform { - Map<String, dynamic> _expectedCalls = <String, dynamic>{}; - Map<String, AdditionalSteps?> _additionalSteps = <String, AdditionalSteps?>{}; + final Map<String, dynamic> _expectedCalls = <String, dynamic>{}; + final Map<String, AdditionalSteps?> _additionalSteps = + <String, AdditionalSteps?>{}; void addResponse( {required String name, dynamic value, @@ -18,7 +19,7 @@ _expectedCalls[name] = value; } - List<MethodCall> _previousCalls = <MethodCall>[]; + final List<MethodCall> _previousCalls = <MethodCall>[]; List<MethodCall> get previousCalls => _previousCalls; MethodCall previousCallMatching(String name) => _previousCalls.firstWhere((MethodCall call) => call.method == name);
diff --git a/script/configs/custom_analysis.yaml b/script/configs/custom_analysis.yaml index 2c87f48..89d061f 100644 --- a/script/configs/custom_analysis.yaml +++ b/script/configs/custom_analysis.yaml
@@ -15,4 +15,3 @@ - google_maps_flutter/google_maps_flutter_platform_interface - google_maps_flutter/google_maps_flutter_web - in_app_purchase/in_app_purchase -- in_app_purchase/in_app_purchase_android