Commit 8af8b9e5904 for woocommerce
commit 8af8b9e59040d998fb9723f65887b61df2e331fc
Author: Vlad Olaru <vlad.olaru@automattic.com>
Date: Tue Oct 6 17:09:55 2026 +0300
Fix WooCommerce Services installation timing telemetry (#69406)
* fix: Correct WooCommerce Tax installation timing telemetry
The core profiler retains the Tax extension key, but the server returns
installation durations under the installable plugin slug. Looking up the
full key silently recorded zero and placed Tax in the fastest bucket.
Resolve only the Tax timing key while preserving its identity in state.
Keep other suffixes, event schemas, and total elapsed timing unchanged.
Regression tests cover the stored duration and both Tracks payloads.
* dev: Add changelog for Tax timing telemetry correction
* fix: Preserve the Tax timing lookup key type
Use the known Tax plugin slug literal so the duration lookup remains within the PluginNames union. The generic slug helper widened the key to string and failed the CI TypeScript check.
* fix: Correct WooCommerce Services shipping timing telemetry
The Shipping alias uses the same server duration key as the Tax alias.
Read that duration while retaining the selected extension identifier.
Cover both aliases through the installer and completion events.
* dev: Update changelog for WooCommerce Services telemetry
* fix: Match installation timing keys to requested plugin slugs
Use the existing slug helper for both the install request and its timing
lookup. Preserve full selected identifiers while covering suffixed keys
beyond Tax, Shipping, and alternate recommendations.
Add PayPal Wallet timing and fallback regressions, including both
completion events.
* dev: Clarify changelog coverage for suffixed plugin keys
diff --git a/plugins/woocommerce/changelog/fix-core-profiler-tax-install-time b/plugins/woocommerce/changelog/fix-core-profiler-tax-install-time
new file mode 100644
index 00000000000..2c91889282d
--- /dev/null
+++ b/plugins/woocommerce/changelog/fix-core-profiler-tax-install-time
@@ -0,0 +1,3 @@
+Significance: patch
+Type: dev
+Comment: Correct plugin timing telemetry for suffixed keys; no merchant-facing installation change.
diff --git a/plugins/woocommerce/client/admin/client/core-profiler/actions/test/tracks.test.ts b/plugins/woocommerce/client/admin/client/core-profiler/actions/test/tracks.test.ts
index c708258948d..d380d163b9f 100644
--- a/plugins/woocommerce/client/admin/client/core-profiler/actions/test/tracks.test.ts
+++ b/plugins/woocommerce/client/admin/client/core-profiler/actions/test/tracks.test.ts
@@ -2,13 +2,17 @@
* External dependencies
*/
import { recordEvent } from '@woocommerce/tracks';
+import { createActor, fromPromise, waitFor } from 'xstate5';
/**
* Internal dependencies
*/
import tracksActions, { resetShippingPartnerImpressionFlag } from '../tracks';
import type { CoreProfilerStateMachineContext } from '../../index';
-import type { PluginInstallError } from '../../services/installAndActivatePlugins';
+import {
+ pluginInstallerMachine,
+ PluginInstallError,
+} from '../../services/installAndActivatePlugins';
jest.mock( '@woocommerce/tracks', () => ( {
recordEvent: jest.fn(),
@@ -440,3 +444,119 @@ describe( 'Core Profiler shipping partner tracking', () => {
} );
} );
} );
+
+describe( 'Core Profiler installation timing', () => {
+ beforeEach( () => {
+ jest.clearAllMocks();
+ } );
+
+ it.each( [
+ [
+ 'woocommerce-services:tax',
+ 'woocommerce-services',
+ 'woocommerce_services',
+ ],
+ [
+ 'woocommerce-services:shipping',
+ 'woocommerce-services',
+ 'woocommerce_services',
+ ],
+ [
+ 'woocommerce-paypal-payments:wallet-only',
+ 'woocommerce-paypal-payments',
+ 'woocommerce_paypal_payments',
+ ],
+ ] )(
+ 'records the server duration for %s in both completion events',
+ async ( plugin, slug, trackKey ) => {
+ const machine = pluginInstallerMachine.provide( {
+ actors: {
+ installPlugin: fromPromise( async () => ( {
+ data: {
+ install_time: { [ slug ]: 4000 },
+ },
+ } ) ),
+ },
+ actions: {
+ updateParentWithPluginProgress: jest.fn(),
+ updateParentWithInstallationSuccess: ( { context } ) => {
+ tracksActions.recordSuccessfulPluginInstallation( {
+ context: makeContext(),
+ event: {
+ type: 'PLUGINS_INSTALLATION_COMPLETED',
+ payload: {
+ installationCompletedResult: {
+ installedPlugins:
+ context.installedPlugins,
+ totalTime: 12000,
+ },
+ },
+ },
+ } );
+ },
+ },
+ } );
+ const service = createActor( machine, {
+ input: {
+ selectedPlugins: [ plugin ],
+ pluginsAvailable: [],
+ },
+ } ).start();
+
+ await waitFor( service, ( snapshot ) =>
+ snapshot.matches( 'reportSuccess' )
+ );
+
+ expect( recordEvent ).toHaveBeenCalledWith(
+ 'coreprofiler_store_extension_installed_and_activated',
+ {
+ success: true,
+ extension: trackKey,
+ install_time: '2-5s',
+ }
+ );
+ expect( recordEvent ).toHaveBeenCalledWith(
+ 'coreprofiler_store_extensions_installed_and_activated',
+ {
+ success: true,
+ installed_extensions: [ trackKey ],
+ total_time: '10-15s',
+ [ `install_time_${ trackKey }` ]: '2-5s',
+ }
+ );
+ expect( recordEvent ).toHaveBeenCalledTimes( 2 );
+ service.stop();
+ }
+ );
+
+ it.each( [ 'mailpoet', 'mailpoet:alt' ] )(
+ 'preserves the normalized identifier and duration for %s',
+ ( plugin ) => {
+ tracksActions.recordSuccessfulPluginInstallation( {
+ context: makeContext(),
+ event: {
+ type: 'PLUGINS_INSTALLATION_COMPLETED',
+ payload: {
+ installationCompletedResult: {
+ installedPlugins: [ { plugin, installTime: 4000 } ],
+ totalTime: 12000,
+ },
+ },
+ },
+ } );
+ expect( recordEvent ).toHaveBeenCalledWith(
+ 'coreprofiler_store_extension_installed_and_activated',
+ { success: true, extension: 'mailpoet', install_time: '2-5s' }
+ );
+ expect( recordEvent ).toHaveBeenCalledWith(
+ 'coreprofiler_store_extensions_installed_and_activated',
+ {
+ success: true,
+ installed_extensions: [ 'mailpoet' ],
+ total_time: '10-15s',
+ install_time_mailpoet: '2-5s',
+ }
+ );
+ }
+ );
+} );
diff --git a/plugins/woocommerce/client/admin/client/core-profiler/pages/Plugins/test/Plugins.test.tsx b/plugins/woocommerce/client/admin/client/core-profiler/pages/Plugins/test/Plugins.test.tsx
index 77fc6bbcf82..533b14f0023 100644
--- a/plugins/woocommerce/client/admin/client/core-profiler/pages/Plugins/test/Plugins.test.tsx
+++ b/plugins/woocommerce/client/admin/client/core-profiler/pages/Plugins/test/Plugins.test.tsx
@@ -320,6 +320,24 @@ describe( 'computePluginsSelection', () => {
{ key: 'plugin3', is_activated: false },
];
+ it( 'preserves Tax and alternate selection keys while normalizing shown slugs', () => {
+ const plugins = [
+ { key: 'woocommerce-services:tax', is_activated: false },
+ { key: 'mailpoet:alt', is_activated: false },
+ ] as Extension[];
+
+ const result = computePluginsSelection( plugins, new Set( plugins ) );
+
+ expect( result.selectedPluginKeys ).toEqual( [
+ 'woocommerce-services:tax',
+ 'mailpoet:alt',
+ ] );
+ expect( result.pluginsShown ).toEqual( [
+ 'woocommerce-services:tax',
+ 'mailpoet',
+ ] );
+ } );
+
it( 'correctly computes selection when no plugins are selected', () => {
const selectedPlugins = new Set< Extension >();
const result = computePluginsSelection(
diff --git a/plugins/woocommerce/client/admin/client/core-profiler/services/installAndActivatePlugins.ts b/plugins/woocommerce/client/admin/client/core-profiler/services/installAndActivatePlugins.ts
index 54eaee12c07..d945bc3b826 100644
--- a/plugins/woocommerce/client/admin/client/core-profiler/services/installAndActivatePlugins.ts
+++ b/plugins/woocommerce/client/admin/client/core-profiler/services/installAndActivatePlugins.ts
@@ -246,7 +246,7 @@ export const pluginInstallerMachine = createMachine(
(
event as DoneActorEvent< InstallAndActivateSuccessResponse >
).output.data.install_time[
- plugin.replace( ':alt', '' )
+ getPluginSlug( plugin )
] || 0,
},
];
diff --git a/plugins/woocommerce/client/admin/client/core-profiler/services/test/installAndActivatePlugins.test.ts b/plugins/woocommerce/client/admin/client/core-profiler/services/test/installAndActivatePlugins.test.ts
index a9be52d58db..ad6675cf97b 100644
--- a/plugins/woocommerce/client/admin/client/core-profiler/services/test/installAndActivatePlugins.test.ts
+++ b/plugins/woocommerce/client/admin/client/core-profiler/services/test/installAndActivatePlugins.test.ts
@@ -27,27 +27,39 @@ describe( 'pluginInstallerMachine', () => {
jest.resetAllMocks();
} );
- it.each( [
- [ 'mailpoet:alt', 'mailpoet', 4000 ],
- [ 'woocommerce-services:tax', 'woocommerce-services', 0 ],
+ it.each< [ string, string, number, number ] >( [
+ [ 'woocommerce-services:tax', 'woocommerce-services', 4000, 4000 ],
+ [ 'woocommerce-services', 'woocommerce-services', 4000, 4000 ],
+ [ 'mailpoet', 'mailpoet', 4000, 4000 ],
+ [ 'mailpoet:alt', 'mailpoet', 4000, 4000 ],
+ [ 'woocommerce-services:tax', 'unrelated-plugin', 4000, 0 ],
+ [ 'woocommerce-services:shipping', 'woocommerce-services', 4000, 4000 ],
+ [ 'woocommerce-services:shipping', 'unrelated-plugin', 4000, 0 ],
+ [
+ 'woocommerce-paypal-payments:wallet-only',
+ 'woocommerce-paypal-payments',
+ 4000,
+ 4000,
+ ],
+ [
+ 'woocommerce-paypal-payments:wallet-only',
+ 'unrelated-plugin',
+ 4000,
+ 0,
+ ],
] )(
- 'preserves trunk installation timing for %s',
- async ( plugin, slug, installTime ) => {
- const machineUnderTest = pluginInstallerMachine.provide( {
+ 'records %s duration from %s without changing its key',
+ async ( plugin, slug, duration, expectedDuration ) => {
+ const machine = pluginInstallerMachine.provide( {
...mockConfig,
actors: {
installPlugin: fromPromise( async () => ( {
- data: {
- install_time: { [ slug ]: 4000 },
- },
+ data: { install_time: { [ slug ]: duration } },
} ) ),
},
} );
- const service = createActor( machineUnderTest, {
- input: {
- selectedPlugins: [ plugin ],
- pluginsAvailable: [],
- },
+ const service = createActor( machine, {
+ input: { selectedPlugins: [ plugin ], pluginsAvailable: [] },
} ).start();
try {
@@ -56,7 +68,7 @@ describe( 'pluginInstallerMachine', () => {
);
expect( snapshot.context.installedPlugins ).toEqual( [
- { plugin, installTime },
+ { plugin, installTime: expectedDuration },
] );
} finally {
service.stop();