From d0fe5575e76a0fe3060148ed07e5450c39ca18a4 Mon Sep 17 00:00:00 2001 From: Manzoor Wani Date: Mon, 19 Aug 2024 05:36:15 -0700 Subject: [PATCH] Social: Migrate supported services list to the new initial state (#38924) * Add supported services to the initial state * Update TS types * Create a utility function for social script data * Use supported services from script data * Remove unused store selector * Add changelog * Fix and clean up tests --- ...ate-migrate-services-list-to-initial-state | 4 +++ .../tests/confirmation-form.test.js | 32 +++++++----------- .../services/use-supported-services.tsx | 27 ++++++++------- .../social-store/selectors/connection-data.js | 11 ------- .../src/social-store/types.ts | 10 ------ .../publicize-components/src/types/types.ts | 12 ++++++- .../src/utils/script-data.ts | 11 +++++++ .../src/utils/test-factory.js | 12 +++---- ...ate-migrate-services-list-to-initial-state | 4 +++ .../src/class-publicize-script-data.php | 32 ++++++++++++++++++ .../class-settings.php | 33 ++----------------- 11 files changed, 94 insertions(+), 94 deletions(-) create mode 100644 projects/js-packages/publicize-components/changelog/update-migrate-services-list-to-initial-state create mode 100644 projects/js-packages/publicize-components/src/utils/script-data.ts create mode 100644 projects/packages/publicize/changelog/update-migrate-services-list-to-initial-state diff --git a/projects/js-packages/publicize-components/changelog/update-migrate-services-list-to-initial-state b/projects/js-packages/publicize-components/changelog/update-migrate-services-list-to-initial-state new file mode 100644 index 0000000000000..358081071accf --- /dev/null +++ b/projects/js-packages/publicize-components/changelog/update-migrate-services-list-to-initial-state @@ -0,0 +1,4 @@ +Significance: patch +Type: changed + +Social: Migrated services list to the initial state diff --git a/projects/js-packages/publicize-components/src/components/manage-connections-modal/tests/confirmation-form.test.js b/projects/js-packages/publicize-components/src/components/manage-connections-modal/tests/confirmation-form.test.js index e9937f30d2296..4bba1efacf7e8 100644 --- a/projects/js-packages/publicize-components/src/components/manage-connections-modal/tests/confirmation-form.test.js +++ b/projects/js-packages/publicize-components/src/components/manage-connections-modal/tests/confirmation-form.test.js @@ -1,13 +1,8 @@ import { render, screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { setup } from '../../../utils/test-factory'; -import { useSupportedServices } from '../../services/use-supported-services'; import { ConfirmationForm } from '../confirmation-form'; -jest.mock( '../../services/use-supported-services', () => ( { - useSupportedServices: jest.fn(), -} ) ); - describe( 'ConfirmationForm', () => { let stubCreateConnection; @@ -16,22 +11,18 @@ describe( 'ConfirmationForm', () => { ( { stubCreateConnection } = setup( { connections: [ { - service_name: 'service-1', - external_id: 'test-account-1', + service_name: 'facebook', + external_id: 'additional-1', external_name: 'Test Account', external_profile_picture: 'https://example.com/profile.jpg', }, ], } ) ); - - useSupportedServices.mockReturnValue( [ - { ID: 'service-1', external_users_only: false, multiple_external_user_ID_support: true }, - ] ); } ); const keyringResult = { ID: 'service-1', - service: 'service-1', + service: 'facebook', external_display: 'Test Account', external_ID: 'test-account-1', external_profile_picture: 'https://example.com/profile.jpg', @@ -59,7 +50,6 @@ describe( 'ConfirmationForm', () => { renderComponent(); expect( screen.getByText( /Select the account you'd like to connect/ ) ).toBeInTheDocument(); - expect( screen.getByText( 'Test Account' ) ).toBeInTheDocument(); expect( screen.getByText( 'Additional User 1' ) ).toBeInTheDocument(); expect( screen.getByText( 'Additional User 2' ) ).toBeInTheDocument(); } ); @@ -80,7 +70,7 @@ describe( 'ConfirmationForm', () => { { display_name: 'Additional User 2', profile_picture: 'https://example.com/additional2.jpg', - service_name: 'service-1', + service_name: 'facebook', external_id: 'additional-2', } ) @@ -96,15 +86,15 @@ describe( 'ConfirmationForm', () => { await waitFor( () => expect( stubCreateConnection ).toHaveBeenCalledWith( { - external_user_ID: 'additional-1', + external_user_ID: 'additional-2', keyring_connection_ID: 'service-1', shared: true, }, { - display_name: 'Additional User 1', - profile_picture: 'https://example.com/additional1.jpg', - service_name: 'service-1', - external_id: 'additional-1', + display_name: 'Additional User 2', + profile_picture: 'https://example.com/additional2.jpg', + service_name: 'facebook', + external_id: 'additional-2', } ) ); @@ -123,7 +113,7 @@ describe( 'ConfirmationForm', () => { renderComponent(); expect( screen.getByText( 'Already connected' ) ).toBeInTheDocument(); - expect( screen.getByText( 'Test Account' ) ).toBeInTheDocument(); - expect( screen.queryByLabelText( 'Test Account' ) ).not.toBeInTheDocument(); // Should not be selectable + expect( screen.getByText( 'Additional User 1' ) ).toBeInTheDocument(); + expect( screen.queryByLabelText( 'Additional User 1' ) ).not.toBeInTheDocument(); // Should not be selectable } ); } ); diff --git a/projects/js-packages/publicize-components/src/components/services/use-supported-services.tsx b/projects/js-packages/publicize-components/src/components/services/use-supported-services.tsx index 1a448388e3516..a83688fb61cad 100644 --- a/projects/js-packages/publicize-components/src/components/services/use-supported-services.tsx +++ b/projects/js-packages/publicize-components/src/components/services/use-supported-services.tsx @@ -1,7 +1,6 @@ import { SocialServiceIcon } from '@automattic/jetpack-components'; import { ExternalLink } from '@wordpress/components'; -import { useSelect } from '@wordpress/data'; -import { createInterpolateElement } from '@wordpress/element'; +import { createInterpolateElement, useMemo } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; import connectionsFacebook from '../../assets/connections-facebook.png'; import connectionsInstagramBusiness from '../../assets/connections-instagram-business.png'; @@ -9,8 +8,8 @@ import connectionsLinkedin from '../../assets/connections-linkedin.png'; import connectionsNextdoor from '../../assets/connections-nextdoor.png'; import connectionsThreads from '../../assets/connections-threads.png'; import connectionsTumblr from '../../assets/connections-tumblr.png'; -import { store } from '../../social-store'; -import { ConnectionService } from '../../social-store/types'; +import { ConnectionService } from '../../types/types'; +import { getSocialScriptData } from '../../utils/script-data'; export type Badge = { text: string; @@ -30,16 +29,16 @@ export interface SupportedService extends ConnectionService { * @returns {Array< SupportedService >} The list of supported services */ export function useSupportedServices(): Array< SupportedService > { - const availableServices = useSelect( select => { - return select( store ) - .getServices() - .reduce< Record< string, ConnectionService > >( - ( serviceData, service ) => ( { - ...serviceData, - [ service.ID ]: service, - } ), - {} - ); + const availableServices = useMemo( () => { + const { supported_services } = getSocialScriptData(); + + return supported_services.reduce< Record< string, ConnectionService > >( + ( serviceData, service ) => ( { + ...serviceData, + [ service.ID ]: service, + } ), + {} + ); }, [] ); const badgeNew: Badge = { diff --git a/projects/js-packages/publicize-components/src/social-store/selectors/connection-data.js b/projects/js-packages/publicize-components/src/social-store/selectors/connection-data.js index a9427c8333c78..12eadb9a05610 100644 --- a/projects/js-packages/publicize-components/src/social-store/selectors/connection-data.js +++ b/projects/js-packages/publicize-components/src/social-store/selectors/connection-data.js @@ -189,17 +189,6 @@ export function isMastodonAccountAlreadyConnected( state, username ) { } ); } -/** - * Returns the services list from the store. - * - * @param {import("../types").SocialStoreState} state - State object. - * - * @returns {Array} The services list - */ -export function getServices( state ) { - return state.connectionData?.services ?? []; -} - /** * Returns the latest KeyringResult from the store. * diff --git a/projects/js-packages/publicize-components/src/social-store/types.ts b/projects/js-packages/publicize-components/src/social-store/types.ts index b49dd98900267..fa786da610e83 100644 --- a/projects/js-packages/publicize-components/src/social-store/types.ts +++ b/projects/js-packages/publicize-components/src/social-store/types.ts @@ -28,16 +28,6 @@ export type Connection = { status: ConnectionStatus; }; -export type ConnectionService = { - ID: string; - label: string; - type: 'publicize' | 'other'; - description: string; - connect_URL: string; - external_users_only?: boolean; - multiple_external_user_ID_support?: boolean; -}; - export type ConnectionData = { connections: Connection[]; deletingConnections?: Array< number | string >; diff --git a/projects/js-packages/publicize-components/src/types/types.ts b/projects/js-packages/publicize-components/src/types/types.ts index 05adb13d3c4be..255fff7d4fd7d 100644 --- a/projects/js-packages/publicize-components/src/types/types.ts +++ b/projects/js-packages/publicize-components/src/types/types.ts @@ -2,9 +2,20 @@ export interface FeatureFlags { useAdminUiV1: boolean; } +export type ConnectionService = { + ID: string; + label: string; + type: 'publicize' | 'other'; + description: string; + connect_URL: string; + external_users_only?: boolean; + multiple_external_user_ID_support?: boolean; +}; + export interface SocialScriptData { is_publicize_enabled: boolean; feature_flags: FeatureFlags; + supported_services: Array< ConnectionService >; } type JetpackSettingsSelectors = { @@ -21,7 +32,6 @@ type JetpackSettingsSelectors = { type ConnectionDataSelectors = { getConnections: () => Array< object >; - getServices: () => Array< object >; getConnectionsAdminUrl: () => string; hasConnections: () => boolean; }; diff --git a/projects/js-packages/publicize-components/src/utils/script-data.ts b/projects/js-packages/publicize-components/src/utils/script-data.ts new file mode 100644 index 0000000000000..9707648ae940b --- /dev/null +++ b/projects/js-packages/publicize-components/src/utils/script-data.ts @@ -0,0 +1,11 @@ +import { getScriptData } from '@automattic/jetpack-script-data'; +import { SocialScriptData } from '../types/types'; + +/** + * Get the social script data from the window object. + * + * @returns {SocialScriptData} The social script data. + */ +export function getSocialScriptData(): SocialScriptData { + return getScriptData().social; +} diff --git a/projects/js-packages/publicize-components/src/utils/test-factory.js b/projects/js-packages/publicize-components/src/utils/test-factory.js index d1d951c2ae86a..7c2b310f63807 100644 --- a/projects/js-packages/publicize-components/src/utils/test-factory.js +++ b/projects/js-packages/publicize-components/src/utils/test-factory.js @@ -2,7 +2,6 @@ import { render, renderHook } from '@testing-library/react'; import { useSelect, useDispatch } from '@wordpress/data'; import ConnectionManagement from '../components/connection-management'; import { ConnectionManagementPageObject } from '../components/connection-management/tests/pageObjects/ConnectionManagementPage'; -import { useSupportedServices } from '../components/services/use-supported-services'; import useSocialMediaConnections from '../hooks/use-social-media-connections'; import { store } from '../social-store'; import { SUPPORTED_SERVICES_MOCK } from './test-constants'; @@ -12,10 +11,6 @@ jest.mock( '../hooks/use-social-media-connections', () => ( { default: jest.fn(), } ) ); -jest.mock( '../components/services/use-supported-services', () => ( { - useSupportedServices: jest.fn(), -} ) ); - export const setup = ( { connections = [ { service_name: 'twitter', connection_id: '1', display_name: 'Twitter', can_disconnect: true }, @@ -56,7 +51,12 @@ export const setup = ( { refresh: jest.fn(), } ); - useSupportedServices.mockReturnValue( SUPPORTED_SERVICES_MOCK ); + global.JetpackScriptData = { + ...global.JetpackScriptData, + social: { + supported_services: SUPPORTED_SERVICES_MOCK, + }, + }; return { stubDeleteConnectionById, diff --git a/projects/packages/publicize/changelog/update-migrate-services-list-to-initial-state b/projects/packages/publicize/changelog/update-migrate-services-list-to-initial-state new file mode 100644 index 0000000000000..358081071accf --- /dev/null +++ b/projects/packages/publicize/changelog/update-migrate-services-list-to-initial-state @@ -0,0 +1,4 @@ +Significance: patch +Type: changed + +Social: Migrated services list to the initial state diff --git a/projects/packages/publicize/src/class-publicize-script-data.php b/projects/packages/publicize/src/class-publicize-script-data.php index d688b958f37e6..e1fe96bfd185d 100644 --- a/projects/packages/publicize/src/class-publicize-script-data.php +++ b/projects/packages/publicize/src/class-publicize-script-data.php @@ -7,6 +7,8 @@ namespace Automattic\Jetpack\Publicize; +use Automattic\Jetpack\Connection\Client; +use Automattic\Jetpack\Connection\Manager; use Automattic\Jetpack\Current_Plan; use Automattic\Jetpack\Publicize\Publicize_Utils as Utils; @@ -83,6 +85,7 @@ public static function get_admin_script_data() { return array_merge( $basic_data, array( + 'supported_services' => self::get_supported_services(), /** * 'store' => self::get_store_script_data(), * 'urls' => self::get_urls(), @@ -133,4 +136,33 @@ public static function has_feature_flag( $feature ): bool { return Current_Plan::supports( 'social-' . $feature ); } + + /** + * Get the list of supported Publicize services. + * + * @return array List of external services and their settings. + */ + public static function get_supported_services() { + $site_id = Manager::get_site_id(); + if ( is_wp_error( $site_id ) ) { + return array(); + } + $path = sprintf( '/sites/%d/external-services', $site_id ); + $response = Client::wpcom_json_api_request_as_user( $path ); + if ( is_wp_error( $response ) ) { + return array(); + } + $body = json_decode( wp_remote_retrieve_body( $response ) ); + + $services = $body->services ?? array(); + + return array_values( + array_filter( + (array) $services, + function ( $service ) { + return isset( $service->type ) && 'publicize' === $service->type; + } + ) + ); + } } diff --git a/projects/packages/publicize/src/jetpack-social-settings/class-settings.php b/projects/packages/publicize/src/jetpack-social-settings/class-settings.php index ba80820206a49..800de227aae1b 100644 --- a/projects/packages/publicize/src/jetpack-social-settings/class-settings.php +++ b/projects/packages/publicize/src/jetpack-social-settings/class-settings.php @@ -7,9 +7,9 @@ namespace Automattic\Jetpack\Publicize\Jetpack_Social_Settings; -use Automattic\Jetpack\Connection\Client; use Automattic\Jetpack\Connection\Manager; use Automattic\Jetpack\Modules; +use Automattic\Jetpack\Publicize\Publicize_Script_Data; use Automattic\Jetpack\Publicize\Social_Image_Generator\Templates; /** @@ -211,7 +211,7 @@ public function get_initial_state() { $settings['connectionData'] = array( 'connections' => $publicize->get_all_connections_for_user(), 'adminUrl' => esc_url_raw( $publicize->publicize_connections_url( 'jetpack-social-connections-admin-page' ) ), - 'services' => $this->get_services(), + 'services' => Publicize_Script_Data::get_supported_services(), ); $settings['is_publicize_enabled'] = true; @@ -231,35 +231,6 @@ public function get_initial_state() { return $settings; } - /** - * Get the list of supported Publicize services. - * - * @return array List of external services and their settings. - */ - public function get_services() { - $site_id = Manager::get_site_id(); - if ( is_wp_error( $site_id ) ) { - return array(); - } - $path = sprintf( '/sites/%d/external-services', $site_id ); - $response = Client::wpcom_json_api_request_as_user( $path ); - if ( is_wp_error( $response ) ) { - return array(); - } - $body = json_decode( wp_remote_retrieve_body( $response ) ); - - $services = $body->services ?? array(); - - return array_values( - array_filter( - (array) $services, - function ( $service ) { - return isset( $service->type ) && 'publicize' === $service->type; - } - ) - ); - } - /** * Update the settings. *