Skip to content

Commit

Permalink
Merge pull request #2526 from woocommerce/tweak/shipping-adjustments
Browse files Browse the repository at this point in the history
Adjust auto-sync shipping option
  • Loading branch information
jorgemd24 committed Sep 3, 2024
2 parents 9edf689 + 8f3231f commit 8cbbde7
Show file tree
Hide file tree
Showing 11 changed files with 459 additions and 31 deletions.
45 changes: 26 additions & 19 deletions js/src/components/shipping-rate-section/shipping-rate-section.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import RadioHelperText from '.~/wcdl/radio-helper-text';
import AppDocumentationLink from '.~/components/app-documentation-link';
import VerticalGapLayout from '.~/components/vertical-gap-layout';
import FlatShippingRatesInputCards from './flat-shipping-rates-input-cards';
import useSettings from '.~/components/free-listings/configure-product-listings/useSettings';
import useMCSetup from '.~/hooks/useMCSetup';

/**
* @fires gla_documentation_link_click with `{ context: 'setup-mc-shipping', link_id: 'shipping-read-more', href: 'https://support.google.com/merchants/answer/7050921' }`
Expand All @@ -22,8 +24,16 @@ import FlatShippingRatesInputCards from './flat-shipping-rates-input-cards';

const ShippingRateSection = () => {
const { getInputProps, values } = useAdaptiveFormContext();
const { settings } = useSettings();
const { hasFinishedResolution, data: mcSetup } = useMCSetup();
const inputProps = getInputProps( 'shipping_rate' );

// Hide the automatic shipping rate option if there are no shipping rates and the merchant is onboarding.
const hideAutomatticShippingRate =
! settings?.shipping_rates_count &&
hasFinishedResolution &&
mcSetup?.status === 'incomplete';

return (
<Section
title={ __( 'Shipping rates', 'google-listings-and-ads' ) }
Expand Down Expand Up @@ -51,27 +61,24 @@ const ShippingRateSection = () => {
<Section.Card>
<Section.Card.Body>
<VerticalGapLayout size="large">
<AppRadioContentControl
{ ...inputProps }
label={ createInterpolateElement(
__(
'<strong>Recommended:</strong> Automatically sync my store’s shipping settings to Google.',
'google-listings-and-ads'
),
{
strong: <strong></strong>,
}
) }
value="automatic"
collapsible
>
<RadioHelperText>
{ __(
'My current settings and any future changes to my store’s shipping rates and classes will be automatically synced to Google Merchant Center.',
{ ! hideAutomatticShippingRate && (
<AppRadioContentControl
{ ...inputProps }
label={ __(
'Automatically sync my store’s shipping settings to Google.',
'google-listings-and-ads'
) }
</RadioHelperText>
</AppRadioContentControl>
value="automatic"
collapsible
>
<RadioHelperText>
{ __(
'My current settings and any future changes to my store’s shipping rates and classes will be automatically synced to Google Merchant Center.',
'google-listings-and-ads'
) }
</RadioHelperText>
</AppRadioContentControl>
) }
<AppRadioContentControl
{ ...inputProps }
label={ __(
Expand Down
211 changes: 211 additions & 0 deletions js/src/components/shipping-rate-section/shipping-rate-section.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
/**
* External dependencies
*/
import '@testing-library/jest-dom';
import { render } from '@testing-library/react';

/**
* Internal dependencies
*/
import useSettings from '.~/components/free-listings/configure-product-listings/useSettings';
import useMCSetup from '.~/hooks/useMCSetup';
import ShippingRateSection from './shipping-rate-section';
//import FlatShippingRatesInputCards from './flat-shipping-rates-input-cards';

jest.mock( './flat-shipping-rates-input-cards', () => () => <></> );

jest.mock( '.~/components/adaptive-form', () => ( {
useAdaptiveFormContext: jest
.fn()
.mockName( 'useAdaptiveFormContext' )
.mockImplementation( () => {
return {
getInputProps: () => {
return {
checked: true,
className: '',
help: null,
onBlur: () => {},
onChange: () => {},
selected: 'flat',
value: 'flat',
};
},
values: {
countries: [ 'ES' ],
language: 'English',
locale: 'en_US',
location: 'selected',
offer_free_shipping: false,
shipping_country_rates: [],
shipping_country_times: [],
shipping_rate: 'flat',
shipping_time: 'flat',
tax_rate: null,
},
};
} ),
} ) );

jest.mock(
'.~/components/free-listings/configure-product-listings/useSettings'
);
jest.mock( '.~/hooks/useMCSetup' );

describe( 'ShippingRateSection', () => {
it( 'shouldnt render automatic rates if there are not shipping rates and it is onboarding', () => {
useMCSetup.mockImplementation( () => {
return {
hasFinishedResolution: true,
data: {
status: 'incomplete',
},
};
} );

useSettings.mockImplementation( () => {
return {
settings: {
shipping_rates_count: 0,
},
};
} );

const { getByText, queryByRole } = render( <ShippingRateSection /> );

expect(
getByText(
'My shipping settings are simple. I can manually estimate flat shipping rates.'
)
).toBeInTheDocument();

expect(
getByText(
'My shipping settings are complex. I will enter my shipping rates and times manually in Google Merchant Center.'
)
).toBeInTheDocument();

expect(
queryByRole(
'Automatically sync my store’s shipping settings to Google.'
)
).not.toBeInTheDocument();
} );

it( 'should render automatic rates if there are shipping rates and it is onboarding', () => {
useMCSetup.mockImplementation( () => {
return {
hasFinishedResolution: true,
data: {
status: 'incomplete',
},
};
} );

useSettings.mockImplementation( () => {
return {
settings: {
shipping_rates_count: 1,
},
};
} );

const { getByText } = render( <ShippingRateSection /> );

expect(
getByText(
'My shipping settings are simple. I can manually estimate flat shipping rates.'
)
).toBeInTheDocument();

expect(
getByText(
'My shipping settings are complex. I will enter my shipping rates and times manually in Google Merchant Center.'
)
).toBeInTheDocument();

expect(
getByText(
'Automatically sync my store’s shipping settings to Google.'
)
).toBeInTheDocument();
} );

it( 'should render automatic rates if there are not shipping rates and it is not onboarding', () => {
useMCSetup.mockImplementation( () => {
return {
hasFinishedResolution: true,
data: {
status: 'completed',
},
};
} );

useSettings.mockImplementation( () => {
return {
settings: {
shipping_rates_count: 0,
},
};
} );

const { getByText } = render( <ShippingRateSection /> );

expect(
getByText(
'My shipping settings are simple. I can manually estimate flat shipping rates.'
)
).toBeInTheDocument();

expect(
getByText(
'My shipping settings are complex. I will enter my shipping rates and times manually in Google Merchant Center.'
)
).toBeInTheDocument();

expect(
getByText(
'Automatically sync my store’s shipping settings to Google.'
)
).toBeInTheDocument();
} );

it( 'should render automatic rates if there are shipping rates and it is not onboarding', () => {
useMCSetup.mockImplementation( () => {
return {
hasFinishedResolution: true,
data: {
status: 'completed',
},
};
} );

useSettings.mockImplementation( () => {
return {
settings: {
shipping_rates_count: 1,
},
};
} );

const { getByText } = render( <ShippingRateSection /> );

expect(
getByText(
'My shipping settings are simple. I can manually estimate flat shipping rates.'
)
).toBeInTheDocument();

expect(
getByText(
'My shipping settings are complex. I will enter my shipping rates and times manually in Google Merchant Center.'
)
).toBeInTheDocument();

expect(
getByText(
'Automatically sync my store’s shipping settings to Google.'
)
).toBeInTheDocument();
} );
} );
2 changes: 1 addition & 1 deletion js/src/setup-mc/setup-stepper/saved-setup-stepper.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ const SavedSetupStepper = ( { savedStep } ) => {
if ( settings?.shipping_rate === null ) {
saveSettings( {
...settings,
shipping_rate: 'automatic',
shipping_rate: 'flat',
shipping_time: 'flat',
} );
}
Expand Down
38 changes: 35 additions & 3 deletions src/API/Site/Controllers/MerchantCenter/SettingsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
use Automattic\WooCommerce\GoogleListingsAndAds\API\Site\Controllers\BaseOptionsController;
use Automattic\WooCommerce\GoogleListingsAndAds\API\TransportMethods;
use Automattic\WooCommerce\GoogleListingsAndAds\Options\OptionsInterface;
use Automattic\WooCommerce\GoogleListingsAndAds\Shipping\ShippingZone;
use Automattic\WooCommerce\GoogleListingsAndAds\Proxies\RESTServer;
use WP_REST_Request as Request;

defined( 'ABSPATH' ) || exit;
Expand All @@ -17,6 +19,22 @@
*/
class SettingsController extends BaseOptionsController {

/**
* @var ShippingZone
*/
protected $shipping_zone;

/**
* SettingsController constructor.
*
* @param RESTServer $server
* @param ShippingZone $shipping_zone
*/
public function __construct( RESTServer $server, ShippingZone $shipping_zone ) {
parent::__construct( $server );
$this->shipping_zone = $shipping_zone;
}

/**
* Register rest routes with WordPress.
*/
Expand Down Expand Up @@ -46,9 +64,10 @@ public function register_routes(): void {
*/
protected function get_settings_endpoint_read_callback(): callable {
return function () {
$data = $this->options->get( OptionsInterface::MERCHANT_CENTER, [] );
$schema = $this->get_schema_properties();
$items = [];
$data = $this->options->get( OptionsInterface::MERCHANT_CENTER, [] );
$data['shipping_rates_count'] = $this->shipping_zone->get_shipping_rates_count();
$schema = $this->get_schema_properties();
$items = [];
foreach ( $schema as $key => $property ) {
$items[ $key ] = $data[ $key ] ?? $property['default'] ?? null;
}
Expand All @@ -71,6 +90,9 @@ protected function get_settings_endpoint_edit_callback(): callable {
}

foreach ( $schema as $key => $property ) {
if ( ! in_array( 'edit', $property['context'] ?? [], true ) ) {
continue;
}
$options[ $key ] = $request->get_param( $key ) ?? $options[ $key ] ?? $property['default'] ?? null;
}

Expand Down Expand Up @@ -178,6 +200,16 @@ protected function get_schema_properties(): array {
'validate_callback' => 'rest_validate_request_arg',
'default' => false,
],
'shipping_rates_count' => [
'type' => 'number',
'description' => __(
'The number of shipping rates in WC ready to be used in the Merchant Center.',
'google-listings-and-ads'
),
'context' => [ 'view' ],
'validate_callback' => 'rest_validate_request_arg',
'default' => 0,
],
];
}

Expand Down
2 changes: 1 addition & 1 deletion src/Internal/DependencyManagement/RESTServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ public function provides( string $service ): bool {
* @return void
*/
public function register() {
$this->share( SettingsController::class );
$this->share( SettingsController::class, ShippingZone::class );
$this->share( ConnectionController::class );
$this->share( AdsAccountController::class, AdsAccountService::class );
$this->share( AdsCampaignController::class, AdsCampaign::class );
Expand Down
10 changes: 10 additions & 0 deletions src/Shipping/ShippingZone.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,16 @@ public function get_shipping_countries(): array {
return array_values( $countries );
}

/**
* Get the number of shipping rates enable in WooCommerce.
*
* @return int
*/
public function get_shipping_rates_count(): int {
$this->parse_shipping_zones();
return count( $this->location_rates ?? [] );
}

/**
* Returns the available shipping rates for a country and its subdivisions.
*
Expand Down
Loading

0 comments on commit 8cbbde7

Please sign in to comment.