From 5a78940e97b271e1f38b8cd09156ab5aeb838e42 Mon Sep 17 00:00:00 2001 From: Vraja Das Date: Wed, 8 Jan 2025 16:52:18 +0200 Subject: [PATCH] WIP GSK integration card --- .../google-site-kit-integration.js | 232 +++++++++++------- .../recommended-integrations.js | 10 +- .../integrations-page/simple-integration.js | 2 +- .../components/site-kit-consent-modal.js | 4 +- .../GoogleSiteKitIntegration.test.js | 73 ++---- src/integrations/admin/integrations-page.php | 12 +- .../Integrations_Page_Integration_Test.php | 18 +- 7 files changed, 199 insertions(+), 152 deletions(-) diff --git a/packages/js/src/integrations-page/google-site-kit-integration.js b/packages/js/src/integrations-page/google-site-kit-integration.js index 249476c9316..2c289bb1ca8 100644 --- a/packages/js/src/integrations-page/google-site-kit-integration.js +++ b/packages/js/src/integrations-page/google-site-kit-integration.js @@ -1,9 +1,9 @@ import { __, sprintf } from "@wordpress/i18n"; import { CheckIcon, XIcon } from "@heroicons/react/solid"; -import { Fragment, createInterpolateElement, useMemo, useCallback } from "@wordpress/element"; +import { createInterpolateElement, useCallback } from "@wordpress/element"; +import PropTypes from "prop-types"; import { SimpleIntegration } from "./simple-integration"; import { ReactComponent as SiteKitLogo } from "../../images/site-kit-logo.svg"; -import { get } from "lodash"; import { useToggleState } from "@yoast/ui-library"; import { SiteKitConsentModal } from "../shared-admin/components"; @@ -30,110 +30,176 @@ const integration = { logo: SiteKitLogo, }; -const buttonLabels = { - install: sprintf( +const buttonProps = { + install: { + children: sprintf( /* translators: 1: Site Kit by Google */ - __( "Install %1$s", "wordpress-seo" ), - "Site Kit by Google" - ), - activate: sprintf( + __( "Install %1$s", "wordpress-seo" ), + "Site Kit by Google" + ), + as: "a", + href: "/wp-admin/plugin-install.php?s=google%2520site%2520kit&tab=search&type=term", + }, + activate: { + children: sprintf( /* translators: 1: Site Kit by Google */ - __( "Activate %1$s", "wordpress-seo" ), - "Site Kit by Google" - ), - setup: sprintf( + __( "Activate %1$s", "wordpress-seo" ), + "Site Kit by Google" + ), + as: "a", + href: "/wp-admin/plugins.php", + }, + setup: { + children: sprintf( /* translators: 1: Site Kit by Google */ - __( "Set up %1$s", "wordpress-seo" ), - "Site Kit by Google" - ), - connect: sprintf( + __( "Set up %1$s", "wordpress-seo" ), + "Site Kit by Google" + ), + as: "a", + href: "/wp-admin/admin.php?page=googlesitekit-splash", + }, + connect: { + children: sprintf( /* translators: 1: Site Kit by Google */ - __( "Connect %1$s", "wordpress-seo" ), - "Site Kit by Google" - ), - disconnect: __( "Disconnect", "wordpress-seo" ), + __( "Connect %1$s", "wordpress-seo" ), + "Site Kit by Google" + ), + as: "button", + }, + disconnect: { + children: __( "Disconnect", "wordpress-seo" ), + as: "button", + variant: "secondary", + }, +}; + +/** + * The NotConnected component. + * + * @param {boolean} isConnected Whether the integration is connected. + * @param {boolean} afterSetup Whether the integration has been set up. + * @param {boolean} isActive Whether the integration is active. + * + * @returns {JSX.Element} The NotConnected component. + */ +const NotConnected = ( { isConnected, afterSetup, isActive } ) => { + return ( ! isConnected || ! afterSetup ) && isActive && <> + + { __( "Not connected", "wordpress-seo" ) } + + + ; +}; + +NotConnected.propTypes = { + isConnected: PropTypes.bool.isRequired, + afterSetup: PropTypes.bool.isRequired, + isActive: PropTypes.bool.isRequired, +}; + +/** + * Plugin not detected. + * + * @param {boolean} isActive Whether the integration is active. + * @param {boolean} isInstalled Whether the integration is installed. + * + * @returns {JSX.Element} The PluginNotDetected component. + */ +const PluginNotDetected = ( { isActive, isInstalled } ) => { + return ( ! isActive || ! isInstalled ) && <> + + { __( "Plugin not detected", "wordpress-seo" ) } + + + ; +}; + +PluginNotDetected.propTypes = { + isActive: PropTypes.bool.isRequired, + isInstalled: PropTypes.bool.isRequired, +}; + +/** + * The successfully Connected component. + * + * @param {boolean} isActive Whether the integration is active. + * @param {boolean} afterSetup Whether the integration has been set up. + * @param {boolean} isConnected Whether the integration is connected. + * + * @returns {JSX.Element} The SuccessfullyConnected component. + */ +const SuccessfullyConnected = ( { isActive, afterSetup, isConnected } ) => { + return isActive && afterSetup && isConnected && <> + + { __( "Successfully connected", "wordpress-seo" ) } + + + ; +}; + +SuccessfullyConnected.propTypes = { + isActive: PropTypes.bool.isRequired, + afterSetup: PropTypes.bool.isRequired, + isConnected: PropTypes.bool.isRequired, }; /** * The Site Kit integration component. * + * @param {boolean} isActive Whether the integration is active. + * @param {boolean} afterSetup Whether the integration has been set up. + * @param {boolean} isInstalled Whether the integration is installed. + * @param {boolean} isConnected Whether the integration is connected. + * * @returns {WPElement} The Site Kit integration component. */ -export const GoogleSiteKitIntegration = () => { - const { isActive, afterSetup, isInstalled, isConnected } = get( window, "wpseoIntegrationsData.googleSiteKit", { isActive: false, afterSetup: false, isInstalled: false, isConnected: false } ); +export const GoogleSiteKitIntegration = ( { isActive, afterSetup, isInstalled, isConnected } ) => { const [ isModalOpen, toggleModal ] = useToggleState( false ); - const getButtonConfig = useCallback( () => { - const button = { - className: "yst-mt-6 yst-w-full", - as: "a", - id: "google-site-kit-button", - }; - - if ( ! isInstalled ) { - button.children = buttonLabels.install; - button.href = "/wp-admin/plugin-install.php?s=google%2520site%2520kit&tab=search&type=term"; - } else if ( ! isActive ) { - button.children = buttonLabels.activate; - button.href = "/wp-admin/plugins.php"; - } else if ( ! afterSetup ) { - button.children = buttonLabels.setup; - button.href = "/wp-admin/admin.php?page=googlesitekit-splash"; - } else if ( ! isConnected ) { - button.children = buttonLabels.connect; - button.onClick = toggleModal; - button.as = "button"; - } else if ( isConnected ) { - button.children = buttonLabels.disconnect; - button.as = "button"; - button.variant = "secondary"; + const getButtonProps = useCallback( () => { + switch ( true ) { + case ( ! isInstalled ): + return buttonProps.install; + case ( ! isActive ): + return buttonProps.activate; + case ( ! afterSetup ): + return buttonProps.setup; + case ( ! isConnected ): + return { ...buttonProps.connect, onClick: toggleModal }; + case ( isConnected ): + return buttonProps.disconnect; } - - return button; }, [ isInstalled, isActive, afterSetup, isConnected ] ); - const notConnected = useMemo( () => ! isConnected || ! afterSetup, [ isConnected, afterSetup ] ); - const pluginNotDetected = useMemo( () => ! isActive || ! isInstalled, [ isActive, isInstalled ] ); - const successfullyConnected = useMemo( () => isActive && afterSetup && isConnected, [ isActive, afterSetup, isConnected ] ); - return ( <> - - { successfullyConnected && - { __( "Successfully connected", "wordpress-seo" ) } - - } - - { notConnected && isActive && - - { - __( "Not connected", "wordpress-seo" ) - } - - - } - - { pluginNotDetected && - - { - __( "Plugin not detected", "wordpress-seo" ) - } - - - } + + + ); }; + +GoogleSiteKitIntegration.propTypes = { + isActive: PropTypes.bool.isRequired, + afterSetup: PropTypes.bool.isRequired, + isInstalled: PropTypes.bool.isRequired, + isConnected: PropTypes.bool.isRequired, +}; diff --git a/packages/js/src/integrations-page/recommended-integrations.js b/packages/js/src/integrations-page/recommended-integrations.js index bd4de0d59d3..a4f7e8ad845 100644 --- a/packages/js/src/integrations-page/recommended-integrations.js +++ b/packages/js/src/integrations-page/recommended-integrations.js @@ -63,7 +63,7 @@ const integrations = [ }, ]; -const isGoogleSiteKitFeatureEnabled = get( window, "wpseoIntegrationsData.googleSiteKit.featureEnabled", false ); +const isGoogleSiteKitFeatureEnabled = get( window, "wpseoIntegrationsData.google_site_kit_feature", false ); const RecommendedIntegrations = [ integrations.map( ( integration, index ) => { @@ -81,9 +81,15 @@ const RecommendedIntegrations = [ } ), ]; +const googleSiteKitProps = { + isInstalled: get( window, "wpseoIntegrationsData.google_site_kit_installed", false ) === "1", + isActive: get( window, "wpseoIntegrationsData.google_site_kit_active", false ) === "1", + afterSetup: get( window, "wpseoIntegrationsData.google_site_kit_setup", false ) === "1", + isConnected: get( window, "wpseoIntegrationsData.google_site_kit_connect", false ) === "1", +}; if ( isGoogleSiteKitFeatureEnabled ) { - RecommendedIntegrations.push( ); + RecommendedIntegrations.push( ); } export { RecommendedIntegrations }; diff --git a/packages/js/src/integrations-page/simple-integration.js b/packages/js/src/integrations-page/simple-integration.js index 05f500ea35a..ebc5abcddd3 100644 --- a/packages/js/src/integrations-page/simple-integration.js +++ b/packages/js/src/integrations-page/simple-integration.js @@ -13,7 +13,7 @@ import { getIsFreeIntegrationOrPremiumAvailable } from "./helper"; * @param {object} integration The integration. * @param {boolean} isActive The integration state. * @param {wp.Element} children The child components. - * @param {wp.Element} button The button component. + * @param {object} button The button component props. * * @returns {WPElement} A card representing an integration. */ diff --git a/packages/js/src/shared-admin/components/site-kit-consent-modal.js b/packages/js/src/shared-admin/components/site-kit-consent-modal.js index 30a9566da05..2b33b7eb64c 100644 --- a/packages/js/src/shared-admin/components/site-kit-consent-modal.js +++ b/packages/js/src/shared-admin/components/site-kit-consent-modal.js @@ -8,7 +8,7 @@ import { PropTypes } from "prop-types"; * @param {boolean} isOpen Whether the modal is open. * @param {Function} onClose Callback to close the modal. * - * @returns {WPElement} The Site Kit consent modal component. + * @returns {JSX.Element} The Site Kit consent modal component. */ export const SiteKitConsentModal = ( { isOpen, onClose } ) => { return ( @@ -19,7 +19,7 @@ export const SiteKitConsentModal = ( { isOpen, onClose } ) => { { __( "Connect Site Kit by Google", "wordpress-seo" ) } -

{ __( "Connect your Google account to view traffic and search rankings on your dashboard.", "wordpress-seo" ) }

+ { __( "Connect your Google account to view traffic and search rankings on your dashboard.", "wordpress-seo" ) }
diff --git a/packages/js/tests/integrations-page/GoogleSiteKitIntegration.test.js b/packages/js/tests/integrations-page/GoogleSiteKitIntegration.test.js index 3a835f6d737..24efdb6d7b1 100644 --- a/packages/js/tests/integrations-page/GoogleSiteKitIntegration.test.js +++ b/packages/js/tests/integrations-page/GoogleSiteKitIntegration.test.js @@ -1,7 +1,6 @@ import React from "react"; import { render, screen } from "../test-utils"; import { GoogleSiteKitIntegration } from "../../src/integrations-page/google-site-kit-integration"; -import { expect } from "@jest/globals"; describe( "GoogleSiteKitIntegration", () => { it( "renders the integration component", () => { @@ -9,32 +8,34 @@ describe( "GoogleSiteKitIntegration", () => { expect( screen.getByText( "Site Kit by Google" ) ).toBeInTheDocument(); } ); - it( "shows 'Install Site Kit by Google' link when not installed", () => { - window.wpseoIntegrationsData = { - googleSiteKit: { - isActive: false, - afterSetup: false, - isInstalled: false, - isConnected: false, - }, - }; - render( ); + it.each( [ + [ "not installed, not active, not after setup, and not connected", false, false, false, false ], + [ "not installed, not active, after setup, and not connected", false, false, true, false ], + [ "not installed, not active, after setup, and connected", false, false, true, true ], + ] )( "shows 'Install Site Kit by Google' link when not installed when %s", ( _title, isInstalled, isActive, afterSetup, isConnected ) => { + render( ); const link = screen.getByRole( "link", { name: "Install Site Kit by Google" } ); expect( link ).toBeInTheDocument(); expect( link ).toHaveAttribute( "href", "/wp-admin/plugin-install.php?s=google%2520site%2520kit&tab=search&type=term" ); expect( screen.getByText( "Plugin not detected" ) ).toBeInTheDocument(); } ); - it( "shows 'Activate Site Kit by Google' button when installed but not active", () => { - window.wpseoIntegrationsData = { - googleSiteKit: { - isActive: false, - afterSetup: false, - isInstalled: true, - isConnected: false, - }, - }; - render( ); + it.each( [ + [ "installed, not active, not after setup, and not connected", true, false, false, false ], + [ "installed, not active, after setup, and not connected", true, false, true, false ], + [ "installed, not active, after setup, and connected", true, false, true, true ], + ] )( "shows 'Activate Site Kit by Google' button when installed but not active when %s", ( _title, isInstalled, isActive, afterSetup, isConnected ) => { + render( ); const link = screen.getByRole( "link", { name: "Activate Site Kit by Google" } ); expect( link ).toBeInTheDocument(); expect( link ).toHaveAttribute( "href", "/wp-admin/plugins.php" ); @@ -42,15 +43,7 @@ describe( "GoogleSiteKitIntegration", () => { } ); it( "shows 'Set up Site Kit by Google' button when active but not set up", () => { - window.wpseoIntegrationsData = { - googleSiteKit: { - isActive: true, - afterSetup: false, - isInstalled: true, - isConnected: false, - }, - }; - render( ); + render( ); const link = screen.getByRole( "link", { name: "Set up Site Kit by Google" } ); expect( link ).toBeInTheDocument(); expect( link ).toHaveAttribute( "href", "/wp-admin/admin.php?page=googlesitekit-splash" ); @@ -58,29 +51,13 @@ describe( "GoogleSiteKitIntegration", () => { } ); it( "shows 'Connect Site Kit by Google' button when set up but not connected", () => { - window.wpseoIntegrationsData = { - googleSiteKit: { - isActive: true, - afterSetup: true, - isInstalled: true, - isConnected: false, - }, - }; - render( ); + render( ); expect( screen.getByRole( "button", { name: "Connect Site Kit by Google" } ) ).toBeInTheDocument(); expect( screen.getByText( "Not connected" ) ).toBeInTheDocument(); } ); it( "shows 'Disconnect' button when connected", () => { - window.wpseoIntegrationsData = { - googleSiteKit: { - isActive: true, - afterSetup: true, - isInstalled: true, - isConnected: true, - }, - }; - render( ); + render( ); expect( screen.getByRole( "button", { name: "Disconnect" } ) ).toBeInTheDocument(); expect( screen.getByText( "Successfully connected" ) ).toBeInTheDocument(); } ); diff --git a/src/integrations/admin/integrations-page.php b/src/integrations/admin/integrations-page.php index c0971fe30d8..005442deee1 100644 --- a/src/integrations/admin/integrations-page.php +++ b/src/integrations/admin/integrations-page.php @@ -194,13 +194,11 @@ public function enqueue_assets() { 'mastodon_active' => $mastodon_active, 'is_multisite' => \is_multisite(), 'plugin_url' => \plugins_url( '', \WPSEO_FILE ), - 'googleSiteKit' => [ - 'isInstalled' => \file_exists( \WP_PLUGIN_DIR . '/' . $google_site_kit_file ), - 'isActive' => \is_plugin_active( $google_site_kit_file ), - 'afterSetup' => \get_option( 'googlesitekit_has_connected_admins', false ) === '1', - 'isConnected' => $this->options_helper->get( 'google_site_kit_connected', false ), - 'featureEnabled' => $google_site_kit_conditional->is_met(), - ], + 'google_site_kit_installed' => \file_exists( \WP_PLUGIN_DIR . '/' . $google_site_kit_file ), + 'google_site_kit_active' => \is_plugin_active( $google_site_kit_file ), + 'google_site_kit_setup' => \get_option( 'googlesitekit_has_connected_admins', false ) === '1', + 'google_site_kit_connected' => $this->options_helper->get( 'google_site_kit_connected', false ), + 'google_site_kit_feature' => $google_site_kit_conditional->is_met(), ] ); } diff --git a/tests/Unit/Integrations/Admin/Integrations_Page_Integration_Test.php b/tests/Unit/Integrations/Admin/Integrations_Page_Integration_Test.php index 3af733356c6..5a9593409c3 100644 --- a/tests/Unit/Integrations/Admin/Integrations_Page_Integration_Test.php +++ b/tests/Unit/Integrations/Admin/Integrations_Page_Integration_Test.php @@ -122,13 +122,15 @@ public function test_enqueue_assets() { Monkey\Functions\expect( 'get_site_url' ) ->andReturn( 'https://www.example.com' ); - Monkey\Functions\expect( 'is_plugin_active' )->times( 6 )->andReturnTrue(); + Monkey\Functions\expect( 'is_plugin_active' )->times( 5 )->andReturnTrue(); + Monkey\Functions\expect( 'is_plugin_active' )->with( 'google-site-kit/google-site-kit.php' )->once()->andReturnFalse(); Monkey\Functions\expect( 'wp_nonce_url' )->times( 3 )->andReturn( 'nonce' ); Monkey\Functions\expect( 'self_admin_url' )->times( 3 )->andReturn( 'https://www.example.com' ); Monkey\Functions\expect( 'plugins_url' )->andReturn( 'https://www.example.com' ); Monkey\Functions\expect( 'admin_url' )->andReturn( 'https://www.example.com' ); - $this->options_helper->expects( 'get' )->times( 6 )->andReturnTrue(); + $this->options_helper->expects( 'get' )->times( 5 )->andReturnTrue(); + $this->options_helper->expects( 'get' )->with( 'google_site_kit_connected', false )->once()->andReturnFalse(); $this->admin_asset_manager->expects( 'localize_script' )->with( 'integrations-page', @@ -159,13 +161,11 @@ public function test_enqueue_assets() { 'mastodon_active' => false, 'is_multisite' => false, 'plugin_url' => 'https://www.example.com', - 'googleSiteKit' => [ - 'isInstalled' => false, - 'isActive' => true, - 'afterSetup' => false, - 'isConnected' => true, - 'featureEnabled' => false, - ], + 'google_site_kit_installed' => false, + 'google_site_kit_active' => false, + 'google_site_kit_setup' => false, + 'google_site_kit_connected' => false, + 'google_site_kit_feature' => false, ] );