From d869c13d59ed68b5383f7a79bb4261a32afceec1 Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Wed, 28 May 2025 15:38:52 +0200 Subject: [PATCH] Fix tests based on latest business logic --- .../src/Repository/PartnerReferralsData.php | 2 +- .../Repository/PartnerReferralsDataTest.php | 269 ++++++++++++++++++ 2 files changed, 270 insertions(+), 1 deletion(-) create mode 100644 tests/PHPUnit/ApiClient/Repository/PartnerReferralsDataTest.php diff --git a/modules/ppcp-api-client/src/Repository/PartnerReferralsData.php b/modules/ppcp-api-client/src/Repository/PartnerReferralsData.php index 72f639b64..88742374e 100644 --- a/modules/ppcp-api-client/src/Repository/PartnerReferralsData.php +++ b/modules/ppcp-api-client/src/Repository/PartnerReferralsData.php @@ -97,8 +97,8 @@ class PartnerReferralsData { $first_party_features[] = 'BILLING_AGREEMENT'; if ( $use_card_payments !== false ) { - $first_party_features[] = 'VAULT'; $first_party_features[] = 'FUTURE_PAYMENT'; + $first_party_features[] = 'VAULT'; } $payload = array( diff --git a/tests/PHPUnit/ApiClient/Repository/PartnerReferralsDataTest.php b/tests/PHPUnit/ApiClient/Repository/PartnerReferralsDataTest.php new file mode 100644 index 000000000..abf691e5b --- /dev/null +++ b/tests/PHPUnit/ApiClient/Repository/PartnerReferralsDataTest.php @@ -0,0 +1,269 @@ +data()` method to ensure it's appended at the end of the + * return URL as-is. + */ + private const TOKEN = 'SECURE_TOKEN'; + + /** + * Expected return URL to see at in the payload, including the ppcpToken. + */ + private const RETURN_URL = 'https://example.com/wp-admin/admin.php?page=wc-settings&tab=checkout§ion=ppcp-gateway&ppcpToken=SECURE_TOKEN'; + + private $testee; + private $dccApplies; + + public function setUp() : void { + parent::setUp(); + + $this->dccApplies = Mockery::mock( DccApplies::class ); + $this->testee = new PartnerReferralsData( $this->dccApplies ); + + when( 'admin_url' )->alias( static fn( string $path ) => self::ADMIN_URL . $path ); + when( 'add_query_arg' )->justReturn( self::RETURN_URL ); + } + + /** + * Base structure of the API payload. Each test should modify the returned + * value of the method to meet its expectations. + * + * This avoids repeating the full structure, while also highlighting the + * specific changes that different params will generate. + * + * @return array + */ + private function getBaseExpectedArray() : array { + return [ + 'partner_config_override' => [ + 'return_url' => self::RETURN_URL, + 'return_url_description' => 'Return to your shop.', + 'show_add_credit_card' => true, + ], + 'legal_consents' => [ + [ + 'type' => 'SHARE_DATA_CONSENT', + 'granted' => true, + ], + ], + 'operations' => [ + [ + 'operation' => 'API_INTEGRATION', + 'api_integration_preference' => [ + 'rest_api_integration' => [ + 'integration_method' => 'PAYPAL', + 'integration_type' => 'FIRST_PARTY', + 'first_party_details' => [ + 'features' => [ + 'PAYMENT', + 'REFUND', + 'ADVANCED_TRANSACTIONS_SEARCH', + 'TRACKING_SHIPMENT_READWRITE', + ], + 'seller_nonce' => self::DEFAULT_NONCE, + ], + ], + ], + ], + ], + ]; + } + + /** + * Data provider for testing flag combinations. + * + * @return array[] Test cases with [has_subscriptions, has_cards, is_acdc_eligible, + * expected_changes] + */ + public function flagCombinationsProvider() : array { + return [ + 'with subscriptions and cards, ACDC eligible' => [ + true, // With subscription? + true, // With cards? + true, // ACDC eligible? + [ + 'capabilities' => [ 'PAYPAL_WALLET_VAULTING_ADVANCED' ], + 'show_add_credit_card' => true, + 'has_vault_features' => true, // This is kept for backward compatibility + ], + ], + 'with subscriptions, no cards, ACDC eligible' => [ + true, // With subscription? + false, // With cards? + true, // ACDC eligible? + [ + 'capabilities' => [ 'PAYPAL_WALLET_VAULTING_ADVANCED' ], + 'show_add_credit_card' => false, + 'has_vault_features' => true, // This is kept for backward compatibility + ], + ], + 'no subscriptions, with cards, ACDC eligible' => [ + false, // With subscription? + true, // With cards? + true, // ACDC eligible? + [ + 'capabilities' => [ 'PAYPAL_WALLET_VAULTING_ADVANCED' ], + 'show_add_credit_card' => true, + 'has_vault_features' => false, // This is kept for backward compatibility + ], + ], + 'no subscriptions, no cards, ACDC eligible' => [ + false, // With subscription? + false, // With cards? + true, // ACDC eligible? + [ + 'capabilities' => [ 'PAYPAL_WALLET_VAULTING_ADVANCED' ], + 'show_add_credit_card' => false, + 'has_vault_features' => false, // This is kept for backward compatibility + ], + ], + 'with subscriptions and cards, ACDC is not eligible' => [ + true, // With subscription? + true, // With cards? + false, // ACDC eligible? + [ + 'show_add_credit_card' => true, + 'has_vault_features' => true, // This is kept for backward compatibility + ], + ], + 'with subscriptions, no cards, ACDC is not eligible' => [ + true, // With subscription? + false, // With cards? + false, // ACDC eligible? + [ + 'show_add_credit_card' => false, + 'has_vault_features' => true, // This is kept for backward compatibility + ], + ], + 'no subscriptions, with cards, ACDC is not eligible' => [ + false, // With subscription? + true, // With cards? + false, // ACDC eligible? + [ + 'show_add_credit_card' => true, + 'has_vault_features' => false, // This is kept for backward compatibility + ], + ], + 'no subscriptions, no cards, ACDC is not eligible' => [ + false, // With subscription? + false, // With cards? + false, // ACDC eligible? + [ + 'show_add_credit_card' => false, + 'has_vault_features' => false, // This is kept for backward compatibility + ], + ], + ]; + } + + /** + * Ensure the default "products" are derived from the DccApplies response. + */ + public function testDefaultValues() : void { + /** + * Case 1: The data() method gets no parameters, and the DccApplies check + * returns TRUE. Onboarding payload should indicate "PPCP" and "ADVANCED_VAULTING". + */ + $this->dccApplies->expects( 'for_country_currency' )->andReturn( true ); + $result = $this->testee->data(); + $this->assertEquals( [ 'PPCP', 'ADVANCED_VAULTING' ], $result['products'] ); + + /** + * Case 2: The data() method gets no parameters, and the DccApplies check + * returns FALSE. Onboarding payload should indicate "EXPRESS_CHECKOUT". + */ + $this->dccApplies->expects( 'for_country_currency' )->andReturn( false ); + $result = $this->testee->data(); + $this->assertEquals( [ 'EXPRESS_CHECKOUT' ], $result['products'] ); + } + + /** + * Ensure the generated API payload is stable and contains the expected values. + * + * The test only verifies the "products" and "token" arguments, as those are the + * core params present in the legacy and new UI. + */ + public function testDataStructure() : void { + $this->dccApplies->shouldReceive( 'for_country_currency' )->andReturn( true ); + + /** + * Undefined subscription: Keep vaulting in first-party with the default card payments set to true + */ + $result = $this->testee->data( [ 'PPCP' ], self::TOKEN ); + + $expected = $this->getBaseExpectedArray(); + + $expected['products'] = [ 'PPCP', 'ADVANCED_VAULTING' ]; + + $expected['operations'][0]['api_integration_preference']['rest_api_integration']['first_party_details']['features'][] = 'BILLING_AGREEMENT'; + $expected['operations'][0]['api_integration_preference']['rest_api_integration']['first_party_details']['features'][] = 'FUTURE_PAYMENT'; + $expected['operations'][0]['api_integration_preference']['rest_api_integration']['first_party_details']['features'][] = 'VAULT'; + + $expected['capabilities'][] = 'PAYPAL_WALLET_VAULTING_ADVANCED'; + + $this->assertEquals( $expected, $result ); + } + + /** + * Test how different flag combinations affect the data structure. + * Those flags are present in the new UI. + * + * @dataProvider flagCombinationsProvider + */ + public function testDataStructureWithFlags( bool $has_subscriptions, bool $has_cards, bool $is_acdc_eligible, array $expected_changes ) : void { + $this->dccApplies->shouldReceive( 'for_country_currency' )->andReturn( $is_acdc_eligible ); + + $result = $this->testee->data( [ 'PPCP' ], self::TOKEN, $has_subscriptions, $has_cards ); + $expected = $this->getBaseExpectedArray(); + + // Set products based on ACDC eligibility + $expected['products'] = $is_acdc_eligible ? [ 'PPCP', 'ADVANCED_VAULTING' ] : [ 'PPCP' ]; + + if ( isset( $expected_changes['capabilities'] ) ) { + $expected['capabilities'] = $expected_changes['capabilities']; + } else { + $this->assertArrayNotHasKey( 'capabilities', $expected ); + } + + $expected['partner_config_override']['show_add_credit_card'] = $expected_changes['show_add_credit_card']; + + $expected['operations'][0]['api_integration_preference']['rest_api_integration']['first_party_details']['features'][] = 'BILLING_AGREEMENT'; + + // Now vault features are only dependent on has_cards, not has_vault_features + if ( $has_cards !== false ) { + $expected['operations'][0]['api_integration_preference']['rest_api_integration']['first_party_details']['features'][] = 'FUTURE_PAYMENT'; + $expected['operations'][0]['api_integration_preference']['rest_api_integration']['first_party_details']['features'][] = 'VAULT'; + } else { + // Double-check that the features are not present in our expected array + $this->assertNotContains( 'FUTURE_PAYMENT', $expected['operations'][0]['api_integration_preference']['rest_api_integration']['first_party_details']['features'] ); + $this->assertNotContains( 'VAULT', $expected['operations'][0]['api_integration_preference']['rest_api_integration']['first_party_details']['features'] ); + } + + $this->assertEquals( $expected, $result ); + } +}