1818import static io .flutter .plugins .inapppurchase .Translator .fromSkuDetailsList ;
1919import static java .util .Arrays .asList ;
2020import static java .util .Collections .singletonList ;
21+ import static java .util .Collections .unmodifiableList ;
2122import static java .util .stream .Collectors .toList ;
2223import static org .junit .Assert .assertEquals ;
2324import static org .junit .Assert .assertNull ;
@@ -261,7 +262,7 @@ public void querySkuDetailsAsync_clientDisconnected() {
261262 }
262263
263264 @ Test
264- public void launchBillingFlow_ok_nullAccountId () {
265+ public void launchBillingFlow_ok_null_AccountId () {
265266 // Fetch the sku details first and then prepare the launch billing flow call
266267 String skuId = "foo" ;
267268 queryForSkus (singletonList (skuId ));
@@ -292,6 +293,40 @@ public void launchBillingFlow_ok_nullAccountId() {
292293 verify (result , times (1 )).success (fromBillingResult (billingResult ));
293294 }
294295
296+ @ Test
297+ public void launchBillingFlow_ok_null_OldSku () {
298+ // Fetch the sku details first and then prepare the launch billing flow call
299+ String skuId = "foo" ;
300+ String accountId = "account" ;
301+ queryForSkus (singletonList (skuId ));
302+ HashMap <String , Object > arguments = new HashMap <>();
303+ arguments .put ("sku" , skuId );
304+ arguments .put ("accountId" , accountId );
305+ arguments .put ("oldSku" , null );
306+ MethodCall launchCall = new MethodCall (LAUNCH_BILLING_FLOW , arguments );
307+
308+ // Launch the billing flow
309+ BillingResult billingResult =
310+ BillingResult .newBuilder ()
311+ .setResponseCode (100 )
312+ .setDebugMessage ("dummy debug message" )
313+ .build ();
314+ when (mockBillingClient .launchBillingFlow (any (), any ())).thenReturn (billingResult );
315+ methodChannelHandler .onMethodCall (launchCall , result );
316+
317+ // Verify we pass the arguments to the billing flow
318+ ArgumentCaptor <BillingFlowParams > billingFlowParamsCaptor =
319+ ArgumentCaptor .forClass (BillingFlowParams .class );
320+ verify (mockBillingClient ).launchBillingFlow (any (), billingFlowParamsCaptor .capture ());
321+ BillingFlowParams params = billingFlowParamsCaptor .getValue ();
322+ assertEquals (params .getSku (), skuId );
323+ assertEquals (params .getAccountId (), accountId );
324+ assertNull (params .getOldSku ());
325+ // Verify we pass the response code to result
326+ verify (result , never ()).error (any (), any (), any ());
327+ verify (result , times (1 )).success (fromBillingResult (billingResult ));
328+ }
329+
295330 @ Test
296331 public void launchBillingFlow_ok_null_Activity () {
297332 methodChannelHandler .setActivity (null );
@@ -311,6 +346,42 @@ public void launchBillingFlow_ok_null_Activity() {
311346 verify (result , never ()).success (any ());
312347 }
313348
349+ @ Test
350+ public void launchBillingFlow_ok_oldSku () {
351+ // Fetch the sku details first and query the method call
352+ String skuId = "foo" ;
353+ String accountId = "account" ;
354+ String oldSkuId = "oldFoo" ;
355+ queryForSkus (unmodifiableList (asList (skuId , oldSkuId )));
356+ HashMap <String , Object > arguments = new HashMap <>();
357+ arguments .put ("sku" , skuId );
358+ arguments .put ("accountId" , accountId );
359+ arguments .put ("oldSku" , oldSkuId );
360+ MethodCall launchCall = new MethodCall (LAUNCH_BILLING_FLOW , arguments );
361+
362+ // Launch the billing flow
363+ BillingResult billingResult =
364+ BillingResult .newBuilder ()
365+ .setResponseCode (100 )
366+ .setDebugMessage ("dummy debug message" )
367+ .build ();
368+ when (mockBillingClient .launchBillingFlow (any (), any ())).thenReturn (billingResult );
369+ methodChannelHandler .onMethodCall (launchCall , result );
370+
371+ // Verify we pass the arguments to the billing flow
372+ ArgumentCaptor <BillingFlowParams > billingFlowParamsCaptor =
373+ ArgumentCaptor .forClass (BillingFlowParams .class );
374+ verify (mockBillingClient ).launchBillingFlow (any (), billingFlowParamsCaptor .capture ());
375+ BillingFlowParams params = billingFlowParamsCaptor .getValue ();
376+ assertEquals (params .getSku (), skuId );
377+ assertEquals (params .getAccountId (), accountId );
378+ assertEquals (params .getOldSku (), oldSkuId );
379+
380+ // Verify we pass the response code to result
381+ verify (result , never ()).error (any (), any (), any ());
382+ verify (result , times (1 )).success (fromBillingResult (billingResult ));
383+ }
384+
314385 @ Test
315386 public void launchBillingFlow_ok_AccountId () {
316387 // Fetch the sku details first and query the method call
@@ -344,6 +415,79 @@ public void launchBillingFlow_ok_AccountId() {
344415 verify (result , times (1 )).success (fromBillingResult (billingResult ));
345416 }
346417
418+ @ Test
419+ public void launchBillingFlow_ok_Proration () {
420+ // Fetch the sku details first and query the method call
421+ String skuId = "foo" ;
422+ String oldSkuId = "oldFoo" ;
423+ String accountId = "account" ;
424+ int prorationMode = BillingFlowParams .ProrationMode .IMMEDIATE_AND_CHARGE_PRORATED_PRICE ;
425+ queryForSkus (unmodifiableList (asList (skuId , oldSkuId )));
426+ HashMap <String , Object > arguments = new HashMap <>();
427+ arguments .put ("sku" , skuId );
428+ arguments .put ("accountId" , accountId );
429+ arguments .put ("oldSku" , oldSkuId );
430+ arguments .put ("prorationMode" , prorationMode );
431+ MethodCall launchCall = new MethodCall (LAUNCH_BILLING_FLOW , arguments );
432+
433+ // Launch the billing flow
434+ BillingResult billingResult =
435+ BillingResult .newBuilder ()
436+ .setResponseCode (100 )
437+ .setDebugMessage ("dummy debug message" )
438+ .build ();
439+ when (mockBillingClient .launchBillingFlow (any (), any ())).thenReturn (billingResult );
440+ methodChannelHandler .onMethodCall (launchCall , result );
441+
442+ // Verify we pass the arguments to the billing flow
443+ ArgumentCaptor <BillingFlowParams > billingFlowParamsCaptor =
444+ ArgumentCaptor .forClass (BillingFlowParams .class );
445+ verify (mockBillingClient ).launchBillingFlow (any (), billingFlowParamsCaptor .capture ());
446+ BillingFlowParams params = billingFlowParamsCaptor .getValue ();
447+ assertEquals (params .getSku (), skuId );
448+ assertEquals (params .getAccountId (), accountId );
449+ assertEquals (params .getOldSku (), oldSkuId );
450+ assertEquals (params .getReplaceSkusProrationMode (), prorationMode );
451+
452+ // Verify we pass the response code to result
453+ verify (result , never ()).error (any (), any (), any ());
454+ verify (result , times (1 )).success (fromBillingResult (billingResult ));
455+ }
456+
457+ @ Test
458+ public void launchBillingFlow_ok_Proration_with_null_OldSku () {
459+ // Fetch the sku details first and query the method call
460+ String skuId = "foo" ;
461+ String accountId = "account" ;
462+ String queryOldSkuId = "oldFoo" ;
463+ String oldSkuId = null ;
464+ int prorationMode = BillingFlowParams .ProrationMode .IMMEDIATE_AND_CHARGE_PRORATED_PRICE ;
465+ queryForSkus (unmodifiableList (asList (skuId , queryOldSkuId )));
466+ HashMap <String , Object > arguments = new HashMap <>();
467+ arguments .put ("sku" , skuId );
468+ arguments .put ("accountId" , accountId );
469+ arguments .put ("oldSku" , oldSkuId );
470+ arguments .put ("prorationMode" , prorationMode );
471+ MethodCall launchCall = new MethodCall (LAUNCH_BILLING_FLOW , arguments );
472+
473+ // Launch the billing flow
474+ BillingResult billingResult =
475+ BillingResult .newBuilder ()
476+ .setResponseCode (100 )
477+ .setDebugMessage ("dummy debug message" )
478+ .build ();
479+ when (mockBillingClient .launchBillingFlow (any (), any ())).thenReturn (billingResult );
480+ methodChannelHandler .onMethodCall (launchCall , result );
481+
482+ // Assert that we sent an error back.
483+ verify (result )
484+ .error (
485+ contains ("IN_APP_PURCHASE_REQUIRE_OLD_SKU" ),
486+ contains ("launchBillingFlow failed because oldSku is null" ),
487+ any ());
488+ verify (result , never ()).success (any ());
489+ }
490+
347491 @ Test
348492 public void launchBillingFlow_clientDisconnected () {
349493 // Prepare the launch call after disconnecting the client
@@ -381,6 +525,27 @@ public void launchBillingFlow_skuNotFound() {
381525 verify (result , never ()).success (any ());
382526 }
383527
528+ @ Test
529+ public void launchBillingFlow_oldSkuNotFound () {
530+ // Try to launch the billing flow for a random sku ID
531+ establishConnectedBillingClient (null , null );
532+ String skuId = "foo" ;
533+ String accountId = "account" ;
534+ String oldSkuId = "oldSku" ;
535+ queryForSkus (singletonList (skuId ));
536+ HashMap <String , Object > arguments = new HashMap <>();
537+ arguments .put ("sku" , skuId );
538+ arguments .put ("accountId" , accountId );
539+ arguments .put ("oldSku" , oldSkuId );
540+ MethodCall launchCall = new MethodCall (LAUNCH_BILLING_FLOW , arguments );
541+
542+ methodChannelHandler .onMethodCall (launchCall , result );
543+
544+ // Assert that we sent an error back.
545+ verify (result ).error (contains ("IN_APP_PURCHASE_INVALID_OLD_SKU" ), contains (oldSkuId ), any ());
546+ verify (result , never ()).success (any ());
547+ }
548+
384549 @ Test
385550 public void queryPurchases () {
386551 establishConnectedBillingClient (null , null );
0 commit comments