Skip to content

Commit

Permalink
Merge branch 'develop' into rpp/100-coverage-command
Browse files Browse the repository at this point in the history
  • Loading branch information
htdat authored Oct 26, 2023
2 parents f93c6a1 + 77b3acd commit b94ccdf
Show file tree
Hide file tree
Showing 15 changed files with 149 additions and 25 deletions.
4 changes: 4 additions & 0 deletions changelog/dev-fix-po-notice-not-appearing
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: minor
Type: fix

Update to properly show tooltip on Payments > Settings page when account is in PO state.
4 changes: 4 additions & 0 deletions changelog/fix-6950-fix-imp-mobile-tooltip
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: fix

Fixed tooltip alignment for mobile view in payment settings
4 changes: 4 additions & 0 deletions changelog/fix-express-checkout-wrapper-float
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: fix

Clear floats for payment request button wrapper.
4 changes: 4 additions & 0 deletions changelog/misc-checkout-scipt-alignment
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: minor
Type: update

Align deferred intent creation UPE checkout script with UPE inn terms of fonts appearance
5 changes: 5 additions & 0 deletions changelog/rpp-authentication-state-meta
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Significance: patch
Type: dev
Comment: Storing the metadata, that was forgotten in 7471


Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,16 @@ import { isPreviewing } from 'wcpay/checkout/preview';

jQuery( function ( $ ) {
enqueueFraudScripts( getUPEConfig( 'fraudServices' ) );
const publishableKey = getUPEConfig( 'publishableKey' );

if ( ! publishableKey ) {
// If no configuration is present, probably this is not the checkout page.
return;
}

const api = new WCPayAPI(
{
publishableKey: getUPEConfig( 'publishableKey' ),
publishableKey: publishableKey,
accountId: getUPEConfig( 'accountId' ),
forceNetworkSavedCards: getUPEConfig( 'forceNetworkSavedCards' ),
locale: getUPEConfig( 'locale' ),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Internal dependencies
*/
import { getUPEConfig } from 'wcpay/utils/checkout';
import { getAppearance } from '../../upe-styles';
import { getAppearance, getFontRulesFromPage } from '../../upe-styles';
import showErrorCheckout from 'wcpay/checkout/utils/show-error-checkout';
import {
appendFingerprintInputToForm,
Expand Down Expand Up @@ -160,6 +160,7 @@ async function createStripePaymentElement( api, paymentMethodType ) {
paymentMethodCreation: 'manual',
paymentMethodTypes: paymentMethodTypes,
appearance: initializeAppearance( api ),
fonts: getFontRulesFromPage(),
};

const elements = api
Expand Down
1 change: 1 addition & 0 deletions client/checkout/express-checkout-buttons.scss
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
.wcpay-payment-request-wrapper {
margin-top: 1em;
width: 100%;
clear: both;

&:first-child {
margin-top: 0;
Expand Down
22 changes: 16 additions & 6 deletions client/components/payment-methods-list/payment-method.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -111,23 +111,29 @@ const PaymentMethod = ( {
isPoEnabled,
isPoComplete,
}: PaymentMethodProps ): React.ReactElement => {
// We want to show a tooltip if PO is enabled and not yet complete. (We make an exception to not show this for card payments).
const isPoInProgress =
isPoEnabled &&
! isPoComplete &&
status !== upeCapabilityStatuses.ACTIVE;

// APMs are disabled if they are inactive or if Progressive Onboarding is enabled and not yet complete.
const disabled =
upeCapabilityStatuses.INACTIVE === status ||
( id !== 'card' && isPoEnabled && ! isPoComplete );
upeCapabilityStatuses.INACTIVE === status || isPoInProgress;
const {
accountFees,
}: { accountFees: Record< string, FeeStructure > } = useContext(
WCPaySettingsContext
);
const [ isManualCaptureEnabled ] = useManualCapture();

const needsAttention = [
const needsMoreInformation = [
upeCapabilityStatuses.INACTIVE,
upeCapabilityStatuses.PENDING_APPROVAL,
upeCapabilityStatuses.PENDING_VERIFICATION,
].includes( status );

const needsAttention = needsMoreInformation || isPoInProgress;
const shouldDisplayNotice = id === 'sofort';

const needsOverlay =
Expand Down Expand Up @@ -190,9 +196,13 @@ const PaymentMethod = ( {
'woocommerce-payments'
) }
/* eslint-disable-next-line max-len */
href={ getDocumentationUrlForDisabledPaymentMethod(
paymentMethodId
) }
href={
isPoInProgress
? 'https://woocommerce.com/document/woopayments/startup-guide/gradual-signup/#additional-payment-methods'
: getDocumentationUrlForDisabledPaymentMethod(
paymentMethodId
)
}
/>
),
},
Expand Down
15 changes: 0 additions & 15 deletions client/components/tooltip/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -52,21 +52,6 @@
padding: 10px;
text-align: center;

&::after {
content: ' ';
position: absolute;

// assuming all the tooltips are displayed at the top of the wrapped element.
// no need to complicate things since that's the only use case at the moment.
bottom: 0;
left: 50%;
transform: translate( -50%, 22px );
border: solid 15px transparent;
border-top-color: $gray-900;
// Ensure the tooltip arrow does not obscure the mouse target element.
pointer-events: none;
}

a {
color: var( --wp-admin-theme-color, $gutenberg-blue );
}
Expand Down
11 changes: 10 additions & 1 deletion client/components/tooltip/tooltip-base.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -223,9 +223,18 @@ const TooltipBase: React.FC< TooltipBaseProps > = ( {
wrappedElement.offsetWidth / 2 + wrappedElementRect.left;
const tooltipWidth = tooltipElement.offsetWidth;
let tooltipLeft = elementMiddle - tooltipWidth / 2;
const tooltipRight =
window.innerWidth -
( wrappedElementRect.left + tooltipElement.offsetWidth );

if ( tooltipLeft < 0 ) {
tooltipLeft = 10;
// create a gap with the left edge if the element is out of view port
tooltipLeft = 45;
} else if ( tooltipRight < 0 ) {
// create a gap with the right edge if the element is out of view port
tooltipLeft = tooltipLeft - 85;
}

tooltipElement.style.left = `${ tooltipLeft }px`;

// make it visible only after all the calculations are done.
Expand Down
1 change: 1 addition & 0 deletions src/Internal/Payment/State/InitialState.php
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ public function start_processing( PaymentRequest $request ) {

// Intent requires authorization (3DS check).
if ( Intent_Status::REQUIRES_ACTION === $intent->get_status() ) {
$this->order_service->update_order_from_intent_that_requires_action( $context->get_order_id(), $intent, $context );
return $this->create_state( AuthenticationRequiredState::class );
}

Expand Down
28 changes: 28 additions & 0 deletions src/Internal/Service/OrderService.php
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,34 @@ public function update_order_from_successful_intent(
}
}

/**
* Updates the order with the necessary details whenever an intent requires action.
*
* @param int $order_id ID of the order.
* @param WC_Payments_API_Abstract_Intention $intent Remote object. To be abstracted soon.
* @param PaymentContext $context Context for the payment.
* @throws Order_Not_Found_Exception
*/
public function update_order_from_intent_that_requires_action(
int $order_id,
WC_Payments_API_Abstract_Intention $intent,
PaymentContext $context
) {
$order = $this->get_order( $order_id );

$this->legacy_service->attach_intent_info_to_order(
$order,
$intent->get_id(),
$intent->get_status(),
$context->get_payment_method()->get_id(),
$context->get_customer_id(),
'',
$context->get_currency()
);

$this->legacy_service->update_order_status_from_intent( $order, $intent );
}

/**
* Given the charge data, checks if there was an exchange and adds it to the given order as metadata
*
Expand Down
16 changes: 15 additions & 1 deletion tests/unit/src/Internal/Payment/State/InitialStateTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit_Utils;
use WC_Order;
use WC_Payments_API_Payment_Intention;
use WC_Payments_Customer_Service;
use WCPay\Core\Exceptions\Server\Request\Invalid_Request_Parameter_Exception;
use WCPay\Internal\Payment\State\InitialState;
Expand Down Expand Up @@ -175,22 +176,35 @@ public function test_start_processing_will_transition_to_error_state_when_api_ex
}

public function test_processing_will_transition_to_auth_required_state() {
$order_id = 123;
$mock_request = $this->createMock( PaymentRequest::class );
$mock_auth_state = $this->createMock( AuthenticationRequiredState::class );

// Create an intent, and make sure it will be returned by the service.
$mock_intent = $this->createMock( WC_Payments_API_Payment_Intention::class );
$mock_intent->expects( $this->once() )->method( 'get_status' )->willReturn( Intent_Status::REQUIRES_ACTION );
$this->mock_payment_request_service->expects( $this->once() )
->method( 'create_intent' )
->with( $this->mock_context )
->willReturn( WC_Helper_Intention::create_intention( [ 'status' => Intent_Status::REQUIRES_ACTION ] ) );
->willReturn( $mock_intent );

// Let's mock these services in order to prevent real execution of them.
$this->mocked_sut->expects( $this->once() )->method( 'populate_context_from_request' )->with( $mock_request );
$this->mocked_sut->expects( $this->once() )->method( 'populate_context_from_order' );

// Before the transition, the order service should update the order.
$this->mock_context->expects( $this->once() )
->method( 'get_order_id' )
->willReturn( $order_id );
$this->mock_order_service->expects( $this->once() )
->method( 'update_order_from_intent_that_requires_action' )
->with( $order_id, $mock_intent, $this->mock_context );

$this->mock_state_factory->expects( $this->once() )
->method( 'create_state' )
->with( AuthenticationRequiredState::class, $this->mock_context )
->willReturn( $mock_auth_state );

$result = $this->mocked_sut->start_processing( $mock_request );
$this->assertSame( $mock_auth_state, $result );
}
Expand Down
47 changes: 47 additions & 0 deletions tests/unit/src/Internal/Service/OrderServiceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,53 @@ public function test_update_order_from_successful_intent( $intent ) {
$this->sut->update_order_from_successful_intent( $this->order_id, $intent, $mock_context );
}

/**
* Test for the `update_order_from_intent_that_requires_action` method.
*/
public function test_update_order_from_intent_that_requires_action() {
$intent_id = 'pi_XYZ';
$intent_status = 'success';
$customer_id = 'cus_XYZ';
$currency = 'usd';
$payment_method_id = 'pm_XYZ';

// Prepare the context, and all needed getters.
$mock_context = $this->createMock( PaymentContext::class );
$mock_context->expects( $this->once() )->method( 'get_payment_method' )->willReturn( new NewPaymentMethod( $payment_method_id ) );
$mock_context->expects( $this->once() )->method( 'get_customer_id' )->willReturn( $customer_id );
$mock_context->expects( $this->once() )->method( 'get_currency' )->willReturn( $currency );

// Create a mock order that will be used, and return it.
$mock_order = $this->createMock( WC_Order::class );
$this->sut->expects( $this->once() )
->method( 'get_order' )
->with( $this->order_id )
->willReturn( $mock_order );

// Prepare the intent, and all expected getters.
$mock_intent = $this->createMock( WC_Payments_API_Payment_Intention::class );
$mock_intent->expects( $this->once() )->method( 'get_id' )->willReturn( $intent_id );
$mock_intent->expects( $this->once() )->method( 'get_status' )->willReturn( $intent_status );

$this->mock_legacy_service->expects( $this->once() )
->method( 'attach_intent_info_to_order' )
->with(
$mock_order,
$intent_id,
$intent_status,
$payment_method_id,
$customer_id,
null,
$currency
);

$this->mock_legacy_service->expects( $this->once() )
->method( 'update_order_status_from_intent' )
->with( $mock_order, $mock_intent );

$this->sut->update_order_from_intent_that_requires_action( $this->order_id, $mock_intent, $mock_context );
}

public function provider_attach_exchange_info_to_order() {
return [
'Different store and account currencies' => [ 'USD', 'USD', 'EUR', null, null ],
Expand Down

0 comments on commit b94ccdf

Please sign in to comment.