* Add payment gateway suggestions unit tests

* Fix up old key fields

* Fix up lingering semantic inconsistencies

* Add changelog entry

* Add in default payment gateways for tests

* Handle PR feedback

* Fix up rebased changelog entries
This commit is contained in:
Joshua T Flowers 2021-06-15 17:24:10 -04:00 committed by GitHub
parent 399ef81b11
commit f57edb6e6c
8 changed files with 236 additions and 52 deletions

View File

@ -77,6 +77,7 @@ Release and roadmap notes are available on the [WooCommerce Developers Blog](htt
- Add: SlotFill to Abbreviated Notification panel #7091
- Add: Add unit tests around extended payment gateway controller #7133
- Add: Add payment gateway suggestion unit tests #7142
- Fix: WCPay not working in local payments task #7151
- Fix: Include onboarding settings on the analytic pages #7109
- Fix: RemoteFreeExtension hide bundle when all of its plugins are not visible #7182

View File

@ -42,7 +42,7 @@ class OnboardingPayments extends \WC_REST_Data_Controller {
array(
array(
'methods' => \WP_REST_Server::READABLE,
'callback' => array( $this, 'get_available_methods' ),
'callback' => array( $this, 'get_suggestions' ),
'permission_callback' => array( $this, 'get_items_permissions_check' ),
),
'schema' => array( $this, 'get_public_item_schema' ),
@ -65,14 +65,14 @@ class OnboardingPayments extends \WC_REST_Data_Controller {
}
/**
* Return available payment methods.
* Return available payment gateway suggestions.
*
* @param \WP_REST_Request $request Request data.
*
* @return \WP_Error|\WP_REST_Response
*/
public function get_available_methods( $request ) {
return PaymentGatewaySuggestions::get_methods();
public function get_suggestions( $request ) {
return PaymentGatewaySuggestions::get_suggestions();
}
}

View File

@ -46,7 +46,7 @@ class DataSourcePoller {
$data_sources = apply_filters( 'woocommerce_admin_payment_gateway_suggestions_data_sources', self::DATA_SOURCES );
// Note that this merges the specs from the data sources based on the
// key - last one wins.
// id - last one wins.
foreach ( $data_sources as $url ) {
$specs_from_data_source = self::read_data_source( $url );
self::merge_specs( $specs_from_data_source, $specs, $url );
@ -115,8 +115,8 @@ class DataSourcePoller {
continue;
}
$key = $spec->key;
$specs[ $key ] = $spec;
$id = $spec->id;
$specs[ $id ] = $spec;
}
}
@ -132,9 +132,9 @@ class DataSourcePoller {
$logger = self::get_logger();
$logger_context = array( 'source' => $url );
if ( ! isset( $spec->key ) ) {
if ( ! isset( $spec->id ) ) {
$logger->error(
'Spec is invalid because the key is missing in feed',
'Spec is invalid because the id is missing in feed',
$logger_context
);
// phpcs:ignore

View File

@ -168,7 +168,7 @@ class DefaultPaymentGateways {
),
),
array(
'key' => 'eway_payments',
'id' => 'eway_payments',
'title' => __( 'eWAY', 'woocommerce-admin' ),
'content' => __( 'The eWAY extension for WooCommerce allows you to take credit card payments directly on your store without redirecting your customers to a third party site to make payment.', 'woocommerce-admin' ),
'image' => WC()->plugin_url() . '/assets/images/eway-logo.jpg',

View File

@ -1,33 +0,0 @@
<?php
/**
* Evaluates the spec and returns a status.
*/
namespace Automattic\WooCommerce\Admin\Features\PaymentGatewaySuggestions;
defined( 'ABSPATH' ) || exit;
use Automattic\WooCommerce\Admin\RemoteInboxNotifications\RuleEvaluator;
/**
* Evaluates the spec and returns the evaluated method.
*/
class EvaluateMethod {
/**
* Evaluates the spec and returns the method.
*
* @param array $spec The method to evaluate.
* @return array The evaluated method.
*/
public static function evaluate( $spec ) {
$rule_evaluator = new RuleEvaluator();
$method = (object) $spec;
if ( isset( $method->is_visible ) ) {
$is_visible = $rule_evaluator->evaluate( $method->is_visible );
$method->is_visible = $is_visible;
}
return $method;
}
}

View File

@ -0,0 +1,33 @@
<?php
/**
* Evaluates the spec and returns a status.
*/
namespace Automattic\WooCommerce\Admin\Features\PaymentGatewaySuggestions;
defined( 'ABSPATH' ) || exit;
use Automattic\WooCommerce\Admin\RemoteInboxNotifications\RuleEvaluator;
/**
* Evaluates the spec and returns the evaluated suggestion.
*/
class EvaluateSuggestion {
/**
* Evaluates the spec and returns the suggestion.
*
* @param array $spec The suggestion to evaluate.
* @return array The evaluated suggestion.
*/
public static function evaluate( $spec ) {
$rule_evaluator = new RuleEvaluator();
$suggestion = (object) $spec;
if ( isset( $suggestion->is_visible ) ) {
$is_visible = $rule_evaluator->evaluate( $suggestion->is_visible );
$suggestion->is_visible = $is_visible;
}
return $suggestion;
}
}

View File

@ -29,20 +29,20 @@ class Init {
/**
* Go through the specs and run them.
*/
public static function get_methods() {
$methods = array();
$specs = self::get_specs();
public static function get_suggestions() {
$suggestions = array();
$specs = self::get_specs();
foreach ( $specs as $spec ) {
$method = EvaluateMethod::evaluate( $spec );
$methods[] = $method;
$suggestion = EvaluateSuggestion::evaluate( $spec );
$suggestions[] = $suggestion;
}
return array_values(
array_filter(
$methods,
function( $method ) {
return ! property_exists( $method, 'is_visible' ) || $method->is_visible;
$suggestions,
function( $suggestion ) {
return ! property_exists( $suggestion, 'is_visible' ) || $suggestion->is_visible;
}
)
);
@ -83,7 +83,7 @@ class Init {
}
/**
* Localize the provided method.
* Localize the provided suggestion.
*
* @param array $specs The specs to localize.
* @return array Localized specs.

View File

@ -0,0 +1,183 @@
<?php
/**
* Test the class that parses the payment suggestions.
*
* @package WooCommerce\Admin\Tests\PaymentGatewaySuggestions
*/
use Automattic\WooCommerce\Admin\Features\PaymentGatewaySuggestions\Init as PaymentGatewaySuggestions;
use Automattic\WooCommerce\Admin\Features\PaymentGatewaySuggestions\DefaultPaymentGateways;
/**
* class WC_Tests_PaymentGatewaySuggestions_Init
*/
class WC_Tests_PaymentGatewaySuggestions_Init extends WC_Unit_Test_Case {
/**
* Set up.
*/
public function setUp() {
parent::setUp();
add_filter(
'transient_' . PaymentGatewaySuggestions::SPECS_TRANSIENT_NAME,
function( $value ) {
if ( $value ) {
return $value;
}
return array(
array(
'id' => 'default-gateway',
),
);
}
);
}
/**
* Tear down.
*/
public function tearDown() {
parent::tearDown();
PaymentGatewaySuggestions::delete_specs_transient();
remove_all_filters( 'transient_' . PaymentGatewaySuggestions::SPECS_TRANSIENT_NAME );
}
/**
* Add test specs.
*/
public function get_mock_specs() {
return array(
array(
'id' => 'mock-gateway',
'is_visible' => (object) array(
'type' => 'base_location_country',
'value' => 'ZA',
'operation' => '=',
),
),
);
}
/**
* Test that default gateways are provided when remote sources don't exist.
*/
public function test_get_default_specs() {
remove_all_filters( 'transient_' . PaymentGatewaySuggestions::SPECS_TRANSIENT_NAME );
add_filter(
'woocommerce_admin_payment_gateway_suggestions_data_sources',
function() {
return array();
},
PHP_INT_MAX
);
$specs = PaymentGatewaySuggestions::get_specs();
$defaults = DefaultPaymentGateways::get_all();
$this->assertEquals( $defaults, $specs );
}
/**
* Test that specs are read from cache when they exist.
*/
public function test_specs_transient() {
set_transient(
PaymentGatewaySuggestions::SPECS_TRANSIENT_NAME,
array(
array(
'id' => 'mock-gateway1',
),
array(
'id' => 'mock-gateway2',
),
)
);
$suggestions = PaymentGatewaySuggestions::get_suggestions();
$this->assertCount( 2, $suggestions );
}
/**
* Test that non-matched suggestions are not shown.
*/
public function test_non_matching_suggestions() {
update_option( 'woocommerce_default_country', 'US' );
set_transient(
PaymentGatewaySuggestions::SPECS_TRANSIENT_NAME,
$this->get_mock_specs()
);
$suggestions = PaymentGatewaySuggestions::get_suggestions();
$this->assertCount( 0, $suggestions );
}
/**
* Test that matched suggestions are shown.
*/
public function test_matching_suggestions() {
update_option( 'woocommerce_default_country', 'ZA' );
set_transient(
PaymentGatewaySuggestions::SPECS_TRANSIENT_NAME,
$this->get_mock_specs()
);
$suggestions = PaymentGatewaySuggestions::get_suggestions();
$this->assertEquals( 'mock-gateway', $suggestions[0]->id );
}
/**
* Test that the transient is deleted on locale change.
*/
public function test_delete_transient_on_locale_change() {
set_transient(
PaymentGatewaySuggestions::SPECS_TRANSIENT_NAME,
array(
array(
'id' => 'mock-gateway',
),
)
);
add_filter(
'get_available_languages',
function( $languages ) {
$languages[] = 'zh_TW';
return $languages;
}
);
$wp_locale_switcher = new WP_Locale_switcher();
$wp_locale_switcher->switch_to_locale( 'zh_TW' );
$suggestions = PaymentGatewaySuggestions::get_suggestions();
$wp_locale_switcher->switch_to_locale( 'en_US' );
$this->assertEquals( 'default-gateway', $suggestions[0]->id );
}
/**
* Test that the locale is filter based on current store locale.
*/
public function test_localization() {
$wp_locale_switcher = new WP_Locale_switcher();
$wp_locale_switcher->switch_to_locale( 'en_US' );
$specs = array(
(object) array(
'id' => 'mock-gateway',
'locales' => array(
(object) array(
'locale' => 'en_US',
'title' => 'Mock Gateway',
),
(object) array(
'locale' => 'zh_TW',
'title' => '測試付款方式',
),
),
),
);
$localized_specs = PaymentGatewaySuggestions::localize( $specs );
$this->assertEquals( 'Mock Gateway', $localized_specs[0]->title );
$this->assertCount( 1, $localized_specs );
}
}