Skip to content

Commit

Permalink
Allow plugin slugs and store slugs to diverge (#65294)
Browse files Browse the repository at this point in the history
hasMarketplaceProduct is sometimes called with product slugs and
sometimes called with store product slugs. In both cases they are
compared to the keys in the productList in the redux state, which are
store product slugs.

A product slug looks like: woocommerce-product-csv-import-suite

A store product slug looks like: wc_product_csv_import_suite_yearly

This change follows the approach proposed in pdh6GB-Pq-p2#comment-1538.
Specifically, it always compares against the billing_product_slug and
against the store product slug, removing the need to normalise slugs
before comparing.

A unit test has been added to support this, and one unit test removed.
The removed test wasn't a valid test case - it was supplying an
artificial slug which would never be supplied in normal circumstances,
not matching either kind of slug.

This fixes part of 634-gh-Automattic/dotcom-manage
  • Loading branch information
dsas authored Jul 7, 2022
1 parent 3a9f11a commit 6924f04
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 21 deletions.
18 changes: 9 additions & 9 deletions packages/calypso-products/src/has-marketplace-product.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
const cleanSlug = ( slug: string ) =>
slug && slug.replace( /_/g, '-' ).split( /-(monthly|yearly|2y)/ )[ 0 ];

/**
* Returns true if a list of products contains a marketplace product with the specified product slug.
* Returns true if a list of products includes a product with a matching product or store product slug.
*
* @param {object} productsList - List of products
* @param {string} productSlug - internal product slug, eg 'jetpack_premium'
* @param {string} searchSlug - Either a product slug e.g. woocommerce-product-csv-import-suite or store product slug, e.g wc_product_csv_import_suite_yearly
* @returns {boolean}
*/
export const hasMarketplaceProduct = (
productsList: Record< string, { product_type: string; product_slug: string } >,
productSlug: string
productsList: Record< string, { product_type: string; billing_product_slug: string } >,
searchSlug: string
): boolean =>
// storeProductSlug is from the legacy store_products system, billing_product_slug is from
// the non-legacy billing system and for marketplace plugins will match the slug of the plugin
// by convention.
Object.entries( productsList ).some(
( [ subscriptionSlug, { product_type } ] ) =>
cleanSlug( productSlug ) === cleanSlug( subscriptionSlug ) &&
( [ storeProductSlug, { product_type, billing_product_slug } ] ) =>
( searchSlug === storeProductSlug || searchSlug === billing_product_slug ) &&
// additional type check needed when called from JS context
typeof product_type === 'string' &&
product_type.startsWith( 'marketplace' )
Expand Down
54 changes: 42 additions & 12 deletions packages/calypso-products/test/has-marketplace-product.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,42 @@ describe( 'hasMarketplaceProduct', () => {
empty_product: {},
product_with_wrong_types: { product_type: 1, slug: 1 },
jetpack: { product_type: 'jetpack' },
woocommerce_bookings_monthly: { product_type: 'marketplace_plugin' },
woocommerce_bookings_yearly: { product_type: 'marketplace_plugin' },
woocommerce_bookings_2y: { product_type: 'marketplace_plugin' },
'woocommerce-subscriptions-monthly': { product_type: 'marketplace_plugin' },
'woocommerce-subscriptions-yearly': { product_type: 'marketplace_plugin' },
'woocommerce-subscriptions-2y': { product_type: 'marketplace_plugin' },
'woocommerce-test-plugin': { product_type: 'plugin' },
'woocommerce-test-plugin-advanced': { product_type: 'marketplace_plugin' },
woocommerce_bookings_monthly: {
product_type: 'marketplace_plugin',
billing_product_slug: 'woocommerce-bookings',
},
woocommerce_bookings_yearly: {
product_type: 'marketplace_plugin',
billing_product_slug: 'woocommerce-bookings',
},
woocommerce_bookings_2y: {
product_type: 'marketplace_plugin',
billing_product_slug: 'woocommerce-bookings',
},
'woocommerce-subscriptions-monthly': {
product_type: 'marketplace_plugin',
billing_product_slug: 'woocommerce-subscriptions',
},
'woocommerce-subscriptions-yearly': {
product_type: 'marketplace_plugin',
billing_product_slug: 'woocommerce-subscriptions',
},
'woocommerce-subscriptions-2y': {
product_type: 'marketplace_plugin',
billing_product_slug: 'woocommerce-subscriptions',
},
'woocommerce-test-plugin': {
product_type: 'plugin',
billing_product_slug: 'woocommerce-test-plugin',
},
'woocommerce-test-plugin-advanced': {
product_type: 'marketplace_plugin',
billing_product_slug: 'woocommerce-test-plugin-advanced',
},
wc_store_products_usually_underscored: {
product_type: 'marketplace_plugin',
billing_product_slug: 'wc-billing-product-slug-can-differ',
},
};

test( "should return false when the product isn't in the products list", () => {
Expand All @@ -35,11 +63,13 @@ describe( 'hasMarketplaceProduct', () => {
expect( hasMarketplaceProduct( productsList, 'woocommerce-test-plugin' ) ).toBe( false );
} );

describe( 'product is a marketplace product', () => {
test( 'should return true when the product slug contains underscores', () => {
expect( hasMarketplaceProduct( productsList, 'woocommerce_bookings' ) ).toBe( true );
} );
test( "should return true when the billing_product_slug matches even when key doesn't match", () => {
expect( hasMarketplaceProduct( productsList, 'wc-billing-product-slug-can-differ' ) ).toBe(
true
);
} );

describe( 'product is a marketplace product', () => {
test( 'should return true when the product slug contains dashes', () => {
expect( hasMarketplaceProduct( productsList, 'woocommerce-subscriptions' ) ).toBe( true );
} );
Expand Down

0 comments on commit 6924f04

Please sign in to comment.