From 7ddcd05cc8fae08aeb0561ad025cbedc06f49711 Mon Sep 17 00:00:00 2001 From: Peter Petrov Date: Wed, 9 Oct 2024 14:41:49 +0300 Subject: [PATCH] Sync my jetpack's Boost page with Boost's getting started page (#39130) * Sync my jetpack's Boost page with Boost's getting started page * add changelog * Remove unused prop * Update Boost pricing table to rely on the same data as my jetpack * Add features list component to reduce code repetition * Fix type incompatibility * Remove unused code * add changelog * Reduce localized data * Update premium pricing to rely on my jetpack variables instead of own * Remove unused type * Use data sync for 'my jetpack' data instead of directly localizing * Add test for my jetpack data in Boost * Fix test signature * Update prop name * Simplify tests * Update php tests to be less strict in terms of feature order * Add a check for feature count --- ...-boost-getting-started-page-to-match-boost | 4 + .../my-jetpack/src/products/class-boost.php | 97 ++++++-- .../plugins/boost/app/admin/class-config.php | 1 - .../boost-pricing-table.tsx | 63 ++++- .../boost-pricing-table/lib/features.tsx | 233 ------------------ .../app/assets/src/js/lib/stores/product.ts | 49 ++++ .../pages/getting-started/getting-started.tsx | 3 - projects/plugins/boost/app/lib/My_Jetpack.php | 19 ++ .../plugins/boost/app/lib/Premium_Pricing.php | 6 +- .../sync-getting-started-page-with-my-jetpack | 4 + .../boost/tests/php/class-my-jetpack.php | 58 +++++ projects/plugins/boost/wp-js-data-sync.php | 2 + 12 files changed, 272 insertions(+), 267 deletions(-) create mode 100644 projects/packages/my-jetpack/changelog/update-boost-getting-started-page-to-match-boost delete mode 100644 projects/plugins/boost/app/assets/src/js/features/boost-pricing-table/lib/features.tsx create mode 100644 projects/plugins/boost/app/assets/src/js/lib/stores/product.ts create mode 100644 projects/plugins/boost/app/lib/My_Jetpack.php create mode 100644 projects/plugins/boost/changelog/sync-getting-started-page-with-my-jetpack create mode 100644 projects/plugins/boost/tests/php/class-my-jetpack.php diff --git a/projects/packages/my-jetpack/changelog/update-boost-getting-started-page-to-match-boost b/projects/packages/my-jetpack/changelog/update-boost-getting-started-page-to-match-boost new file mode 100644 index 0000000000000..e6af00536b568 --- /dev/null +++ b/projects/packages/my-jetpack/changelog/update-boost-getting-started-page-to-match-boost @@ -0,0 +1,4 @@ +Significance: patch +Type: changed + +Update Boost's pricing table to include latest feature list. diff --git a/projects/packages/my-jetpack/src/products/class-boost.php b/projects/packages/my-jetpack/src/products/class-boost.php index a9f9b0f58f14b..9a60573323751 100644 --- a/projects/packages/my-jetpack/src/products/class-boost.php +++ b/projects/packages/my-jetpack/src/products/class-boost.php @@ -134,7 +134,7 @@ public static function get_tiers() { public static function get_features_by_tier() { return array( array( - 'name' => __( 'Optimize CSS Loading', 'jetpack-my-jetpack' ), + 'name' => __( 'Auto CSS Optimization', 'jetpack-my-jetpack' ), 'info' => array( 'content' => __( 'Move important styling information to the start of the page, which helps pages display your content sooner, so your users don’t have to wait for the entire page to load. Commonly referred to as Critical CSS.', @@ -143,8 +143,8 @@ public static function get_features_by_tier() { ), 'tiers' => array( self::FREE_TIER_SLUG => array( - 'included' => true, - 'description' => __( 'Must be done manually', 'jetpack-my-jetpack' ), + 'included' => false, + 'description' => __( 'Manual', 'jetpack-my-jetpack' ), 'info' => array( 'title' => __( 'Manual Critical CSS regeneration', 'jetpack-my-jetpack' ), 'content' => __( @@ -163,7 +163,7 @@ public static function get_features_by_tier() { ), self::UPGRADED_TIER_SLUG => array( 'included' => true, - 'description' => __( 'Automatically updated', 'jetpack-my-jetpack' ), + 'description' => __( 'Included', 'jetpack-my-jetpack' ), 'info' => array( 'title' => __( 'Automatic Critical CSS regeneration', 'jetpack-my-jetpack' ), 'content' => __( @@ -176,15 +176,51 @@ public static function get_features_by_tier() { ), ), array( - 'name' => __( 'Defer non-essential JavaScript', 'jetpack-my-jetpack' ), + 'name' => __( 'Automatic image size analysis', 'jetpack-my-jetpack' ), 'info' => array( 'content' => __( - 'Run non-essential JavaScript after the page has loaded so that styles and images can load more quickly.', + 'Scan your site for images that aren’t properly sized for the device they’re being viewed on.', + 'jetpack-my-jetpack' + ), + ), + 'tiers' => array( + self::FREE_TIER_SLUG => array( 'included' => false ), + self::UPGRADED_TIER_SLUG => array( 'included' => true ), + ), + ), + array( + 'name' => __( 'Historical performance scores', 'jetpack-my-jetpack' ), + 'info' => array( + 'content' => __( + 'Get access to your historical performance scores and see advanced Core Web Vitals data.', 'jetpack-my-jetpack' ), - 'link' => array( - 'id' => 'jetpack-boost-defer-js', - 'title' => 'web.dev', + ), + 'tiers' => array( + self::FREE_TIER_SLUG => array( 'included' => false ), + self::UPGRADED_TIER_SLUG => array( 'included' => true ), + ), + ), + array( + 'name' => __( 'Dedicated email support', 'jetpack-my-jetpack' ), + 'info' => array( + 'content' => __( + '

Paid customers get dedicated email support from our world-class Happiness Engineers to help with any issue.

+

All other questions are handled by our team as quickly as we are able to go through the WordPress support forum.

', + 'jetpack-my-jetpack' + ), + ), + 'tiers' => array( + self::FREE_TIER_SLUG => array( 'included' => false ), + self::UPGRADED_TIER_SLUG => array( 'included' => true ), + ), + ), + array( + 'name' => __( 'Page Cache', 'jetpack-my-jetpack' ), + 'info' => array( + 'content' => __( + 'Page caching speeds up load times by storing a copy of each web page on the first visit, allowing subsequent visits to be served instantly. This reduces server load and improves user experience by delivering content faster, without waiting for the page to be generated again.', + 'jetpack-my-jetpack' ), ), 'tiers' => array( @@ -193,15 +229,37 @@ public static function get_features_by_tier() { ), ), array( - 'name' => __( 'Lazy image loading', 'jetpack-my-jetpack' ), + 'name' => __( 'Image CDN Quality Settings', 'jetpack-my-jetpack' ), 'info' => array( 'content' => __( - 'Improve page loading speed by only loading images when they are required.', + 'Fine-tune image quality settings to your liking.', 'jetpack-my-jetpack' ), - 'link' => array( - 'id' => 'jetpack-boost-lazy-load', - 'title' => 'web.dev', + ), + 'tiers' => array( + self::FREE_TIER_SLUG => array( 'included' => false ), + self::UPGRADED_TIER_SLUG => array( 'included' => true ), + ), + ), + array( + 'name' => __( 'Image CDN Auto-Resize Lazy Images', 'jetpack-my-jetpack' ), + 'info' => array( + 'content' => __( + 'Optimizes lazy-loaded images by dynamically serving perfectly sized images for each device.', + 'jetpack-my-jetpack' + ), + ), + 'tiers' => array( + self::FREE_TIER_SLUG => array( 'included' => false ), + self::UPGRADED_TIER_SLUG => array( 'included' => true ), + ), + ), + array( + 'name' => __( 'Image CDN', 'jetpack-my-jetpack' ), + 'info' => array( + 'content' => __( + 'Deliver images from Jetpack\'s Content Delivery Network. Automatically resizes your images to an appropriate size, converts them to modern efficient formats like WebP, and serves them from a worldwide network of servers.', + 'jetpack-my-jetpack' ), ), 'tiers' => array( @@ -223,10 +281,10 @@ public static function get_features_by_tier() { ), ), array( - 'name' => __( 'Image CDN', 'jetpack-my-jetpack' ), + 'name' => __( 'Defer non-essential JavaScript', 'jetpack-my-jetpack' ), 'info' => array( 'content' => __( - 'Deliver images from Jetpack\'s Content Delivery Network. Automatically resizes your images to an appropriate size, converts them to modern efficient formats like WebP, and serves them from a worldwide network of servers.', + 'Run non-essential JavaScript after the page has loaded so that styles and images can load more quickly.', 'jetpack-my-jetpack' ), ), @@ -236,16 +294,15 @@ public static function get_features_by_tier() { ), ), array( - 'name' => __( 'Dedicated email support', 'jetpack-my-jetpack' ), + 'name' => __( 'Concatenate JS and CSS', 'jetpack-my-jetpack' ), 'info' => array( 'content' => __( - '

Paid customers get dedicated email support from our world-class Happiness Engineers to help with any issue.

-

All other questions are handled by our team as quickly as we are able to go through the WordPress support forum.

', + 'Boost your website performance by merging and compressing JavaScript and CSS files, reducing site loading time and number of requests.', 'jetpack-my-jetpack' ), ), 'tiers' => array( - self::FREE_TIER_SLUG => array( 'included' => false ), + self::FREE_TIER_SLUG => array( 'included' => true ), self::UPGRADED_TIER_SLUG => array( 'included' => true ), ), ), diff --git a/projects/plugins/boost/app/admin/class-config.php b/projects/plugins/boost/app/admin/class-config.php index 0bbad13c953fe..6930c86e0db70 100644 --- a/projects/plugins/boost/app/admin/class-config.php +++ b/projects/plugins/boost/app/admin/class-config.php @@ -4,7 +4,6 @@ use Automattic\Jetpack\Status; use Automattic\Jetpack\Status\Host; - /** * Handle the configuration constants. * diff --git a/projects/plugins/boost/app/assets/src/js/features/boost-pricing-table/boost-pricing-table.tsx b/projects/plugins/boost/app/assets/src/js/features/boost-pricing-table/boost-pricing-table.tsx index 1d9092d4c3c6c..0c35668713d65 100644 --- a/projects/plugins/boost/app/assets/src/js/features/boost-pricing-table/boost-pricing-table.tsx +++ b/projects/plugins/boost/app/assets/src/js/features/boost-pricing-table/boost-pricing-table.tsx @@ -1,23 +1,57 @@ -import { type PricingSchema, usePricing } from '$lib/stores/pricing'; +import { usePricing } from '$lib/stores/pricing'; +import { useProduct } from '$lib/stores/product'; import { Button, Notice, PricingTable, PricingTableColumn, PricingTableHeader, + PricingTableItem, ProductPrice, } from '@automattic/jetpack-components'; -import { boostFeatureList } from './lib/features'; import { __ } from '@wordpress/i18n'; type BoostPricingTableProps = { - pricing: PricingSchema; onPremiumCTA: () => void; onFreeCTA: () => void; chosenFreePlan: boolean; chosenPaidPlan: boolean; }; +type BoostPricingTablesFeaturesListProps = { + feature: { + included: boolean; + description?: string; + info?: { + title?: string; + content: string; + class?: string; + }; + }; +}; + +const BoostPricingTablesFeaturesList = ( { feature }: BoostPricingTablesFeaturesListProps ) => { + const { description, included, info } = feature; + + let labelText; + if ( description ) { + labelText = { description }; + } + + return ( + : null + } + tooltipClassName={ info?.class } + /> + ); +}; + export const BoostPricingTable = ( { onPremiumCTA, onFreeCTA, @@ -25,6 +59,7 @@ export const BoostPricingTable = ( { chosenPaidPlan, }: BoostPricingTableProps ) => { const pricing = usePricing(); + const product = useProduct(); // If the first year discount ends, we want to show the default label. const legend = pricing?.isIntroductoryOffer @@ -32,6 +67,7 @@ export const BoostPricingTable = ( { : undefined; const isDiscounted = pricing?.priceBefore && pricing?.priceBefore > pricing?.priceAfter; + const featuresByTier = product?.features_by_tier ?? []; return ( <> @@ -49,7 +85,15 @@ export const BoostPricingTable = ( { feature.description ) } + items={ featuresByTier.map( ( { name, info } ) => ( { + name, + tooltipTitle: info?.title, + tooltipInfo: info?.content ? ( + // eslint-disable-next-line react/no-danger +
+ ) : null, + tooltipPlacement: 'bottom-start', + } ) ) } > { [ @@ -70,7 +114,12 @@ export const BoostPricingTable = ( { { __( 'Get Boost', 'jetpack-boost' ) } , - ...boostFeatureList.map( feature => feature.premium ), + ...featuresByTier.map( ( tierFeature, mapIndex ) => ( + + ) ), ] } @@ -92,7 +141,9 @@ export const BoostPricingTable = ( { { __( 'Start for free', 'jetpack-boost' ) } , - ...boostFeatureList.map( feature => feature.free ), + ...featuresByTier.map( ( { tiers }, index ) => ( + + ) ), ] } diff --git a/projects/plugins/boost/app/assets/src/js/features/boost-pricing-table/lib/features.tsx b/projects/plugins/boost/app/assets/src/js/features/boost-pricing-table/lib/features.tsx deleted file mode 100644 index 0c6b056cd4ce2..0000000000000 --- a/projects/plugins/boost/app/assets/src/js/features/boost-pricing-table/lib/features.tsx +++ /dev/null @@ -1,233 +0,0 @@ -import { PricingTable, PricingTableItem, getRedirectUrl } from '@automattic/jetpack-components'; -import { createInterpolateElement } from '@wordpress/element'; -import { __ } from '@wordpress/i18n'; -import React, { ReactElement } from 'react'; - -type PricingTableItemProps = React.ComponentProps< typeof PricingTableItem >; -type PricingTableProps = React.ComponentProps< typeof PricingTable >; - -const cssOptimizationContext = __( - 'Move important styling information to the start of the page, which helps pages display your content sooner, so your users don’t have to wait for the entire page to load. Commonly referred to as Critical CSS.', - 'jetpack-boost' -); - -const manuallyUpdatedContext = ( - - { __( - 'To enhance the speed of your site, with this plan you will need to optimize CSS by using the Manual Critical CSS generation feature whenever you:', - 'jetpack-boost' - ) } -
-
-
    -
  • { __( 'Make theme changes.', 'jetpack-boost' ) }
  • -
  • { __( 'Write a new post/page.', 'jetpack-boost' ) }
  • -
  • { __( 'Edit a post/page.', 'jetpack-boost' ) }
  • -
  • - { __( - 'Activate, deactivate, or update plugins that impact your site layout or HTML structure.', - 'jetpack-boost' - ) } -
  • -
  • - { __( - 'Change settings of plugins that impact your site layout or HTML structure.', - 'jetpack-boost' - ) } -
  • -
  • - { __( - 'Upgrade your WordPress version if the new release includes core CSS changes.', - 'jetpack-boost' - ) } -
  • -
-
-); - -const automaticallyUpdatedContext = ( - - { __( - 'It’s essential to regenerate Critical CSS to optimize your site speed whenever your HTML or CSS structure changes. Being on top of this can be tedious and time-consuming.', - 'jetpack-boost' - ) } -
-
- { __( - 'Boost’s cloud service can automatically detect when your site needs the Critical CSS regenerated, and perform this function behind the scenes without requiring you to monitor it manually.', - 'jetpack-boost' - ) } -
-); - -const pageCacheContext = __( - 'Page caching speeds up load times by storing a copy of each web page on the first visit, allowing subsequent visits to be served instantly. This reduces server load and improves user experience by delivering content faster, without waiting for the page to be generated again.', - 'jetpack-boost' -); - -const imageCdnContext = __( - `Deliver images from Jetpack's Content Delivery Network. Automatically resizes your images to an appropriate size, converts them to modern efficient formats like WebP, and serves them from a worldwide network of servers.`, - 'jetpack-boost' -); - -const isaContext = __( - "Scan your site for images that aren't properly sized for the device they're being viewed on.", - 'jetpack-boost' -); - -const performanceHistoryContext = __( - 'Get access to your historical performance scores and see advanced Core Web Vitals data.', - 'jetpack-boost' -); - -const deferJSContextTemplate = __( - 'Run non-essential JavaScript after the page has loaded so that styles and images can load more quickly. Read more on web.dev.', - 'jetpack-boost' -); - -const deferJSContext = createInterpolateElement( deferJSContextTemplate, { - // eslint-disable-next-line jsx-a11y/anchor-has-content - link: , -} ); - -const imageGuideContext = __( - 'Discover and fix images with a suboptimal resolution, aspect ratio, or file size, improving user experience and page speed.', - 'jetpack-boost' -); - -const supportContext = __( - `Paid customers get dedicated email support from our world-class Happiness Engineers to help with any issue.

All other questions are handled by our team as quickly as we are able to go through the WordPress support forum.`, - 'jetpack-boost' -); - -const concatenateContext = __( - 'Boost your website performance by merging and compressing JavaScript and CSS files, reducing site loading time and number of requests.', - 'jetpack-boost' -); - -type FeatureItem = { - description: PricingTableProps[ 'items' ][ number ]; - free: ReactElement< PricingTableItemProps >; - premium: ReactElement< PricingTableItemProps >; -}; - -export const boostFeatureList: FeatureItem[] = [ - { - description: { - name: __( 'Auto CSS Optimization', 'jetpack-boost' ), - tooltipInfo: cssOptimizationContext, - tooltipPlacement: 'bottom-start', - }, - free: ( - - ), - premium: ( - { __( 'Included', 'jetpack-boost' ) } } - tooltipTitle={ __( 'Automatic Critical CSS regeneration', 'jetpack-boost' ) } - tooltipInfo={ automaticallyUpdatedContext } - tooltipClassName="wide-tooltip" - /> - ), - }, - { - description: { - name: __( 'Automatic image size analysis', 'jetpack-boost' ), - tooltipInfo: isaContext, - tooltipPlacement: 'bottom-start', - }, - free: , - premium: , - }, - { - description: { - name: __( 'Historical performance scores', 'jetpack-boost' ), - tooltipInfo: performanceHistoryContext, - tooltipPlacement: 'bottom-start', - }, - free: , - premium: , - }, - { - description: { - name: __( 'Dedicated email support', 'jetpack-boost' ), - tooltipInfo: , - tooltipPlacement: 'bottom-start', - }, - free: , - premium: , - }, - { - description: { - name: __( 'Page Cache', 'jetpack-boost' ), - tooltipInfo: pageCacheContext, - tooltipPlacement: 'bottom-start', - }, - free: , - premium: , - }, - { - description: { - name: __( 'Image CDN Quality Settings', 'jetpack-boost' ), - tooltipInfo: __( 'Fine-tune image quality settings to your liking.', 'jetpack-boost' ), - tooltipPlacement: 'bottom-start', - }, - free: , - premium: , - }, - { - description: { - name: __( 'Image CDN Auto-Resize Lazy Images', 'jetpack-boost' ), - tooltipInfo: __( - 'Optimizes lazy-loaded images by dynamically serving perfectly sized images for each device.', - 'jetpack-boost' - ), - tooltipPlacement: 'bottom-start', - }, - free: , - premium: , - }, - { - description: { - name: __( 'Image CDN', 'jetpack-boost' ), - tooltipInfo: imageCdnContext, - tooltipPlacement: 'bottom-start', - }, - free: , - premium: , - }, - { - description: { - name: __( 'Image guide', 'jetpack-boost' ), - tooltipInfo: imageGuideContext, - tooltipPlacement: 'bottom-start', - }, - free: , - premium: , - }, - { - description: { - name: __( 'Defer non-essential JavaScript', 'jetpack-boost' ), - tooltipInfo: deferJSContext, - tooltipPlacement: 'bottom-start', - }, - free: , - premium: , - }, - { - description: { - name: __( 'Concatenate JS and CSS', 'jetpack-boost' ), - tooltipInfo: concatenateContext, - tooltipPlacement: 'bottom-start', - }, - free: , - premium: , - }, -]; diff --git a/projects/plugins/boost/app/assets/src/js/lib/stores/product.ts b/projects/plugins/boost/app/assets/src/js/lib/stores/product.ts new file mode 100644 index 0000000000000..c46e31854640b --- /dev/null +++ b/projects/plugins/boost/app/assets/src/js/lib/stores/product.ts @@ -0,0 +1,49 @@ +import { useDataSync } from '@automattic/jetpack-react-data-sync-client'; +import { z } from 'zod'; + +const ProductSchema = z + .object( { + tiers: z.array( z.string() ), + features_by_tier: z.array( + z.object( { + name: z.string(), + info: z.object( { + title: z.string().optional(), + content: z.string(), + } ), + tiers: z.object( { + free: z.object( { + included: z.boolean(), + description: z.string().optional(), + info: z + .object( { + title: z.string().optional(), + content: z.string(), + class: z.string().optional(), + } ) + .optional(), + } ), + upgraded: z.object( { + included: z.boolean(), + description: z.string().optional(), + info: z + .object( { + title: z.string().optional(), + content: z.string(), + class: z.string().optional(), + } ) + .optional(), + } ), + } ), + } ) + ), + } ) + .nullable(); + +export type ProductSchema = z.infer< typeof ProductSchema >; + +export const useProduct = () => { + const [ { data } ] = useDataSync( 'jetpack_boost_ds', 'product', ProductSchema ); + + return data; +}; diff --git a/projects/plugins/boost/app/assets/src/js/pages/getting-started/getting-started.tsx b/projects/plugins/boost/app/assets/src/js/pages/getting-started/getting-started.tsx index acf2a5611353e..ed69d93e3c63c 100644 --- a/projects/plugins/boost/app/assets/src/js/pages/getting-started/getting-started.tsx +++ b/projects/plugins/boost/app/assets/src/js/pages/getting-started/getting-started.tsx @@ -10,7 +10,6 @@ import styles from './getting-started.module.scss'; import { useGettingStarted } from '$lib/stores/getting-started'; import { useNavigate } from 'react-router-dom'; import { __ } from '@wordpress/i18n'; -import { usePricing } from '$lib/stores/pricing'; import { usePremiumFeatures } from '$lib/stores/premium-features'; import { useSingleModuleState } from '$features/module/lib/stores'; @@ -23,7 +22,6 @@ const GettingStarted: React.FC = () => { site: { domain }, } = Jetpack_Boost; - const pricing = usePricing(); const premiumFeatures = usePremiumFeatures(); const isPremium = premiumFeatures.length > 0; @@ -92,7 +90,6 @@ const GettingStarted: React.FC = () => {
initialize( 'premium' ) } onFreeCTA={ () => initialize( 'free' ) } chosenFreePlan={ selectedPlan === 'free' } diff --git a/projects/plugins/boost/app/lib/My_Jetpack.php b/projects/plugins/boost/app/lib/My_Jetpack.php new file mode 100644 index 0000000000000..53e24e0ddb399 --- /dev/null +++ b/projects/plugins/boost/app/lib/My_Jetpack.php @@ -0,0 +1,19 @@ + $product::get_tiers(), + 'features_by_tier' => $product::get_features_by_tier(), + ); + } +} diff --git a/projects/plugins/boost/app/lib/Premium_Pricing.php b/projects/plugins/boost/app/lib/Premium_Pricing.php index 2a4a75ea420c8..a38ea5964cac4 100644 --- a/projects/plugins/boost/app/lib/Premium_Pricing.php +++ b/projects/plugins/boost/app/lib/Premium_Pricing.php @@ -2,20 +2,18 @@ namespace Automattic\Jetpack_Boost\Lib; +use Automattic\Jetpack\My_Jetpack\Products\Boost; use Automattic\Jetpack\My_Jetpack\Wpcom_Products; use Automattic\Jetpack\Status; class Premium_Pricing { - const PRODUCT_SLUG_BASE = 'jetpack_boost'; - /** * Get an object containing the yearly pricing information for Jetpack Boost. * * Used by Jetpack_Boost js constants and data sync. */ public static function get_yearly_pricing() { - $yearly_pricing_slug = self::PRODUCT_SLUG_BASE . '_yearly'; - $yearly_pricing = Wpcom_Products::get_product_pricing( $yearly_pricing_slug ); + $yearly_pricing = Wpcom_Products::get_product_pricing( Boost::UPGRADED_TIER_PRODUCT_SLUG ); if ( empty( $yearly_pricing ) ) { // In offline mode, we don't have access to the pricing data and it's not an error. diff --git a/projects/plugins/boost/changelog/sync-getting-started-page-with-my-jetpack b/projects/plugins/boost/changelog/sync-getting-started-page-with-my-jetpack new file mode 100644 index 0000000000000..36c6f0f624152 --- /dev/null +++ b/projects/plugins/boost/changelog/sync-getting-started-page-with-my-jetpack @@ -0,0 +1,4 @@ +Significance: patch +Type: changed + +General: Sync Boost's Getting Started page with My Jetpack's version. diff --git a/projects/plugins/boost/tests/php/class-my-jetpack.php b/projects/plugins/boost/tests/php/class-my-jetpack.php new file mode 100644 index 0000000000000..8c376297a5731 --- /dev/null +++ b/projects/plugins/boost/tests/php/class-my-jetpack.php @@ -0,0 +1,58 @@ +returnArg(); + + $this->product = My_Jetpack::get_product(); + } + + public function test_is_correct_tiers() { + $expected = array( + 'upgraded', + 'free', + ); + + $actual = $this->product['tiers']; + $this->assertEquals( $expected, $actual ); + } + + public function test_is_correct_features_count() { + $total_features = 11; + $this->assertCount( $total_features, $this->product['features_by_tier'], 'Expected ' . $total_features . ' features, got ' . count( $this->product['features_by_tier'] ) ); + } + + public function test_all_features_have_required_keys() { + foreach ( $this->product['features_by_tier'] as $feature ) { + $this->checkForRequiredKeys( $feature ); + } + } + + /** + * Checks that a feature has the required keys + * for rendering the UI. + * + * @param array $feature The feature to check. + */ + private function checkForRequiredKeys( $feature ) { + $this->assertIsArray( $feature ); + $this->assertIsString( $feature['name'] ); + $this->assertIsArray( $feature['info'] ); + $this->assertIsString( $feature['info']['content'] ); + $this->assertIsArray( $feature['tiers'] ); + $this->assertIsArray( $feature['tiers']['free'] ); + $this->assertIsBool( $feature['tiers']['free']['included'] ); + $this->assertIsArray( $feature['tiers']['upgraded'] ); + $this->assertIsBool( $feature['tiers']['upgraded']['included'] ); + } +} diff --git a/projects/plugins/boost/wp-js-data-sync.php b/projects/plugins/boost/wp-js-data-sync.php index 318ef4ddcf6c2..28d5d69cd2af7 100644 --- a/projects/plugins/boost/wp-js-data-sync.php +++ b/projects/plugins/boost/wp-js-data-sync.php @@ -16,6 +16,7 @@ use Automattic\Jetpack_Boost\Lib\Critical_CSS\Data_Sync_Actions\Set_Provider_CSS; use Automattic\Jetpack_Boost\Lib\Critical_CSS\Data_Sync_Actions\Set_Provider_Error_Dismissed; use Automattic\Jetpack_Boost\Lib\Critical_CSS\Data_Sync_Actions\Set_Provider_Errors; +use Automattic\Jetpack_Boost\Lib\My_Jetpack; use Automattic\Jetpack_Boost\Lib\Premium_Features; use Automattic\Jetpack_Boost\Lib\Premium_Pricing; use Automattic\Jetpack_Boost\Lib\Status; @@ -346,6 +347,7 @@ function jetpack_boost_initialize_datasync() { jetpack_boost_register_readonly_option( 'connection', array( new Connection(), 'get_connection_api_response' ) ); jetpack_boost_register_readonly_option( 'pricing', array( Premium_Pricing::class, 'get_yearly_pricing' ) ); +jetpack_boost_register_readonly_option( 'product', array( My_Jetpack::class, 'get_product' ) ); jetpack_boost_register_readonly_option( 'premium_features', array( Premium_Features::class, 'get_features' ) ); jetpack_boost_register_readonly_option( 'cache_debug_log', array( Logger::class, 'read' ) ); jetpack_boost_register_readonly_option( 'cache_engine_loading', array( Boost_Cache::class, 'is_loaded' ) );