From c29ef0aa069366993d434cb70de5cdd83e8ebba0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dami=C3=A1n=20Su=C3=A1rez?= Date: Tue, 7 Nov 2023 21:17:25 +0000 Subject: [PATCH 1/3] AI Assistant: register isFetching state in the plans store (#33996) * introduce fetchAiAssistantFeature action * resolver calls the action * register isFetching prop state * changelog * rename isFetching with isRequesting * store metadata in the _meta prop * introduce the `_meta` field --- ...ess-com-introduce-is-fetching-in-assistant | 4 + .../extensions/store/wordpress-com/actions.ts | 60 ++++++++++++ .../extensions/store/wordpress-com/index.ts | 97 ++++++++++--------- .../extensions/store/wordpress-com/types.ts | 3 + 4 files changed, 119 insertions(+), 45 deletions(-) create mode 100644 projects/plugins/jetpack/changelog/update-store-wordpress-com-introduce-is-fetching-in-assistant diff --git a/projects/plugins/jetpack/changelog/update-store-wordpress-com-introduce-is-fetching-in-assistant b/projects/plugins/jetpack/changelog/update-store-wordpress-com-introduce-is-fetching-in-assistant new file mode 100644 index 0000000000000..c4224e9c0b3f8 --- /dev/null +++ b/projects/plugins/jetpack/changelog/update-store-wordpress-com-introduce-is-fetching-in-assistant @@ -0,0 +1,4 @@ +Significance: patch +Type: enhancement + +AI Assistant: register isFetching state in the plans store diff --git a/projects/plugins/jetpack/extensions/store/wordpress-com/actions.ts b/projects/plugins/jetpack/extensions/store/wordpress-com/actions.ts index dc1519a162e28..64e84d027b416 100644 --- a/projects/plugins/jetpack/extensions/store/wordpress-com/actions.ts +++ b/projects/plugins/jetpack/extensions/store/wordpress-com/actions.ts @@ -1,8 +1,42 @@ +/** + * External dependencies + */ +import apiFetch from '@wordpress/api-fetch'; /** * Types */ import type { Plan } from './types'; import type { AiFeatureProps } from './types'; +import type { SiteAIAssistantFeatureEndpointResponseProps } from '../../types'; + +/** + * Map the response from the `sites/$site/ai-assistant-feature` + * endpoint to the AI Assistant feature props. + * @param { SiteAIAssistantFeatureEndpointResponseProps } response - The response from the endpoint. + * @returns { AiFeatureProps } The AI Assistant feature props. + */ +export function mapAIFeatureResponseToAiFeatureProps( + response: SiteAIAssistantFeatureEndpointResponseProps +): AiFeatureProps { + return { + hasFeature: !! response[ 'has-feature' ], + isOverLimit: !! response[ 'is-over-limit' ], + requestsCount: response[ 'requests-count' ], + requestsLimit: response[ 'requests-limit' ], + requireUpgrade: !! response[ 'site-require-upgrade' ], + errorMessage: response[ 'error-message' ], + errorCode: response[ 'error-code' ], + upgradeType: response[ 'upgrade-type' ], + usagePeriod: { + currentStart: response[ 'usage-period' ]?.[ 'current-start' ], + nextStart: response[ 'usage-period' ]?.[ 'next-start' ], + requestsCount: response[ 'usage-period' ]?.[ 'requests-count' ] || 0, + }, + currentTier: { + value: response[ 'current-tier' ]?.value || 1, + }, + }; +} const actions = { setPlans( plans: Array< Plan > ) { @@ -25,6 +59,32 @@ const actions = { feature, }; }, + + /** + * Thunk action to fetch the AI Assistant feature from the API. + * + * @returns {Function} The thunk action. + */ + fetchAiAssistantFeature() { + return async ( { dispatch } ) => { + // Dispatch isFetching action. + dispatch( { type: 'REQUEST_AI_ASSISTANT_FEATURE' } ); + + try { + const response: SiteAIAssistantFeatureEndpointResponseProps = await apiFetch( { + path: '/wpcom/v2/jetpack-ai/ai-assistant-feature', + } ); + + // Store the feature in the store. + dispatch( + actions.storeAiAssistantFeature( mapAIFeatureResponseToAiFeatureProps( response ) ) + ); + } catch ( err ) { + // @todo: Handle error. + console.error( err ); // eslint-disable-line no-console + } + }; + }, }; export default actions; diff --git a/projects/plugins/jetpack/extensions/store/wordpress-com/index.ts b/projects/plugins/jetpack/extensions/store/wordpress-com/index.ts index 96cdd3d321b54..ef337a7726118 100644 --- a/projects/plugins/jetpack/extensions/store/wordpress-com/index.ts +++ b/projects/plugins/jetpack/extensions/store/wordpress-com/index.ts @@ -1,7 +1,6 @@ /** * External dependencies */ -import apiFetch from '@wordpress/api-fetch'; import { createReduxStore, register } from '@wordpress/data'; /** * Internal dependencies @@ -10,44 +9,36 @@ import actions from './actions'; /** * Types */ -import type { AiFeatureProps, PlanStateProps } from './types'; -import type { SiteAIAssistantFeatureEndpointResponseProps } from '../../types'; +import type { PlanStateProps } from './types'; const store = 'wordpress-com/plans'; const INITIAL_STATE: PlanStateProps = { plans: [], - features: {}, -}; - -/** - * Map the response from the `sites/$site/ai-assistant-feature` - * endpoint to the AI Assistant feature props. - * @param { SiteAIAssistantFeatureEndpointResponseProps } response - The response from the endpoint. - * @returns { AiFeatureProps } The AI Assistant feature props. - */ -function mapAIFeatureResponseToAiFeatureProps( - response: SiteAIAssistantFeatureEndpointResponseProps -): AiFeatureProps { - return { - hasFeature: !! response[ 'has-feature' ], - isOverLimit: !! response[ 'is-over-limit' ], - requestsCount: response[ 'requests-count' ], - requestsLimit: response[ 'requests-limit' ], - requireUpgrade: !! response[ 'site-require-upgrade' ], - errorMessage: response[ 'error-message' ], - errorCode: response[ 'error-code' ], - upgradeType: response[ 'upgrade-type' ], - usagePeriod: { - currentStart: response[ 'usage-period' ]?.[ 'current-start' ], - nextStart: response[ 'usage-period' ]?.[ 'next-start' ], - requestsCount: response[ 'usage-period' ]?.[ 'requests-count' ] || 0, - }, - currentTier: { - value: response[ 'current-tier' ]?.value || 1, + features: { + aiAssistant: { + hasFeature: false, + isOverLimit: false, + requestsCount: 0, + requestsLimit: 0, + requireUpgrade: false, + errorMessage: '', + errorCode: '', + upgradeType: 'default', + currentTier: { + value: 1, + }, + usagePeriod: { + currentStart: '', + nextStart: '', + requestsCount: 0, + }, + _meta: { + isRequesting: false, + }, }, - }; -} + }, +}; const wordpressPlansStore = createReduxStore( store, { __experimentalUseThunks: true, @@ -60,12 +51,33 @@ const wordpressPlansStore = createReduxStore( store, { plans: action.plans, }; + case 'REQUEST_AI_ASSISTANT_FEATURE': + return { + ...state, + features: { + ...state.features, + aiAssistant: { + ...state.features.aiAssistant, + _meta: { + ...state.features.aiAssistant._meta, + isRequesting: true, + }, + }, + }, + }; + case 'STORE_AI_ASSISTANT_FEATURE': { return { ...state, features: { ...state.features, - aiAssistant: action.feature, + aiAssistant: { + ...action.feature, + _meta: { + ...state.features.aiAssistant._meta, + isRequesting: false, + }, + }, }, }; } @@ -117,18 +129,13 @@ const wordpressPlansStore = createReduxStore( store, { return actions.setPlans( plans ); }, - getAiAssistantFeature: - () => - async ( { dispatch } ) => { - const response: SiteAIAssistantFeatureEndpointResponseProps = await apiFetch( { - path: '/wpcom/v2/jetpack-ai/ai-assistant-feature', - } ); + getAiAssistantFeature: ( state: PlanStateProps ) => { + if ( state?.features?.aiAssistant ) { + return; + } - // Store the feature in the store. - dispatch( - actions.storeAiAssistantFeature( mapAIFeatureResponseToAiFeatureProps( response ) ) - ); - }, + return actions.fetchAiAssistantFeature(); + }, }, } ); diff --git a/projects/plugins/jetpack/extensions/store/wordpress-com/types.ts b/projects/plugins/jetpack/extensions/store/wordpress-com/types.ts index 37d871d912fac..39f6aa8ad8033 100644 --- a/projects/plugins/jetpack/extensions/store/wordpress-com/types.ts +++ b/projects/plugins/jetpack/extensions/store/wordpress-com/types.ts @@ -31,4 +31,7 @@ export type AiFeatureProps = { nextStart: string; requestsCount: number; }; + _meta?: { + isRequesting: boolean; + }; }; From 5912a924018549996ac5583c336d55aa830d84d5 Mon Sep 17 00:00:00 2001 From: Kuba Birecki Date: Tue, 7 Nov 2023 22:31:31 +0100 Subject: [PATCH 2/3] Add lint configs for VS Code (#33405) * Add lint configs for VS Code * Update prettier.prettierPath value * Switch to PHPCodeSniffer instead of PHPCS extension --- .vscode/settings.json | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 57b09de909ad9..caec5f18317f2 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -19,5 +19,16 @@ "**/.cache/**", "**/jetpack_vendor/**/jetpack_vendor/**", "**/jetpack_vendor/**" - ] + ], + "phpCodeSniffer.autoExecutable": true, + "phpCodeSniffer.standard": "Automatic", + "phpCodeSniffer.exclude": [ + "**/.git/**", + "**/.svn/**", + "**/.hg/**", + "**/.cache/**", + "**/jetpack_vendor/**", + "**/vendor/**", + ], + "prettier.prettierPath": "tools/js-tools/node_modules/prettier/index.cjs" } \ No newline at end of file From ee82adabbca4b04c0136a28b967a4dfcadb2f544 Mon Sep 17 00:00:00 2001 From: Brad Jorsch Date: Tue, 7 Nov 2023 16:39:23 -0500 Subject: [PATCH 3/3] lazy-images: Hack to fix tests (#33999) Looks like #23716 back April 2022 in made packages/status depend on the `Jetpack_Options` class without adding an actual dependency. And nothing caught it because any tests hitting those code paths happened to provide the dep themselves, until now that WorDBless brings in WP 6.4 which makes the lazy-images tests start trying to call the "disable" function that was added as part of the deprecation process for that package. Unfortunately `Jetpack_Options` was merged into packages/connection not long after that happened, and Connection depends on Status so we can't make Status depend on Connection. While we sort that out, let's hack the lazy-image tests to not try to disable the module like they didn't before so the failing tests don't block everything else. --- .../lazy-images/changelog/fix-hack-fix-lazy-images-tests | 5 +++++ projects/packages/lazy-images/src/lazy-images.php | 5 +++++ projects/packages/lazy-images/tests/php/bootstrap.php | 2 ++ .../lazy-images/tests/php/test_class.lazy-images.php | 2 ++ 4 files changed, 14 insertions(+) create mode 100644 projects/packages/lazy-images/changelog/fix-hack-fix-lazy-images-tests diff --git a/projects/packages/lazy-images/changelog/fix-hack-fix-lazy-images-tests b/projects/packages/lazy-images/changelog/fix-hack-fix-lazy-images-tests new file mode 100644 index 0000000000000..6e50dc4fc541c --- /dev/null +++ b/projects/packages/lazy-images/changelog/fix-hack-fix-lazy-images-tests @@ -0,0 +1,5 @@ +Significance: patch +Type: fixed +Comment: Hack tests to pass by avoiding calling `Modules::disable()` from packages/status, which has an undeclared dependency on `Jetpack_Options` which is currently in packages/connection. + + diff --git a/projects/packages/lazy-images/src/lazy-images.php b/projects/packages/lazy-images/src/lazy-images.php index 725ae0743faef..551c2255d3157 100644 --- a/projects/packages/lazy-images/src/lazy-images.php +++ b/projects/packages/lazy-images/src/lazy-images.php @@ -82,6 +82,11 @@ public static function instance() { * @return bool */ public static function should_force_deactivate() { + // Don't try disabling when running phpunit tests. A bug in packages/status makes that fail. + if ( Constants::is_true( 'IS_JETPACK_LAZY_IMAGES_TESTS' ) ) { + return false; + } + // If Gutenberg is not installed, // check if we run a version of WP that would conflict with Lazy Images. if ( ! Constants::is_true( 'IS_GUTENBERG_PLUGIN' ) ) { diff --git a/projects/packages/lazy-images/tests/php/bootstrap.php b/projects/packages/lazy-images/tests/php/bootstrap.php index e96b603a0d7b6..f0eef7365a2d8 100644 --- a/projects/packages/lazy-images/tests/php/bootstrap.php +++ b/projects/packages/lazy-images/tests/php/bootstrap.php @@ -5,6 +5,8 @@ * @package automattic/jetpack-lazy-images */ +define( 'IS_JETPACK_LAZY_IMAGES_TESTS', true ); // flag for hack + /** * Load the composer autoloader. */ diff --git a/projects/packages/lazy-images/tests/php/test_class.lazy-images.php b/projects/packages/lazy-images/tests/php/test_class.lazy-images.php index d9c97373977ea..dee261f47c5ec 100644 --- a/projects/packages/lazy-images/tests/php/test_class.lazy-images.php +++ b/projects/packages/lazy-images/tests/php/test_class.lazy-images.php @@ -615,6 +615,8 @@ public function test_should_force_deactivate( $version_details, $expected ) { global $wp_version; $previous_version = $wp_version; + Constants::set_constant( 'IS_JETPACK_LAZY_IMAGES_TESTS', false ); // disable hack for this test + Constants::set_constant( 'IS_GUTENBERG_PLUGIN', $version_details['gutenberg'] ); Constants::set_constant( 'GUTENBERG_VERSION', $version_details['gutenberg_version'] ); if ( true === $version_details['is_gutenberg_dev'] ) {