From 5b7c3ec6ea117b86eabaa5277b5909d5b64c6516 Mon Sep 17 00:00:00 2001 From: Renatho De Carli Rosa Date: Tue, 15 Oct 2024 17:03:50 -0300 Subject: [PATCH 1/4] Create pending sticker when loading the step --- .../site-migration-how-to-migrate/index.tsx | 64 +++++++++++++------ 1 file changed, 43 insertions(+), 21 deletions(-) diff --git a/client/landing/stepper/declarative-flow/internals/steps-repository/site-migration-how-to-migrate/index.tsx b/client/landing/stepper/declarative-flow/internals/steps-repository/site-migration-how-to-migrate/index.tsx index e22728e37cd65..fc86aa80912bb 100644 --- a/client/landing/stepper/declarative-flow/internals/steps-repository/site-migration-how-to-migrate/index.tsx +++ b/client/landing/stepper/declarative-flow/internals/steps-repository/site-migration-how-to-migrate/index.tsx @@ -1,6 +1,6 @@ import { StepContainer } from '@automattic/onboarding'; import { useTranslate } from 'i18n-calypso'; -import { FC, useMemo } from 'react'; +import { FC, useMemo, useEffect } from 'react'; import DocumentHead from 'calypso/components/data/document-head'; import FormattedHeader from 'calypso/components/formatted-header'; import { useUpdateMigrationStatus } from 'calypso/data/site-migration/use-update-migration-status'; @@ -13,10 +13,48 @@ import { recordTracksEvent } from 'calypso/lib/analytics/tracks'; import { usePresalesChat } from 'calypso/lib/presales-chat'; import useHostingProviderName from 'calypso/site-profiler/hooks/use-hosting-provider-name'; import FlowCard from '../components/flow-card'; -import type { StepProps } from '../../types'; +import type { NavigationControls, StepProps } from '../../types'; import './style.scss'; +interface PendingMigrationStatusProps { + onSubmit?: Pick< NavigationControls, 'submit' >[ 'submit' ]; +} + +const usePendingMigrationStatus = ( { onSubmit }: PendingMigrationStatusProps ) => { + const site = useSite(); + const siteId = site?.ID; + + const canInstallPlugins = site?.plan?.features?.active.find( + ( feature ) => feature === 'install-plugins' + ) + ? true + : false; + + const { updateMigrationStatus } = useUpdateMigrationStatus(); + + // Register pending migration status when loading the step. + useEffect( () => { + if ( siteId ) { + updateMigrationStatus( siteId, 'migration-pending' ); + } + }, [ siteId, updateMigrationStatus ] ); + + const onOptionClick = ( how: string ) => { + const destination = canInstallPlugins ? 'migrate' : 'upgrade'; + if ( siteId ) { + const parsedHow = how === HOW_TO_MIGRATE_OPTIONS.DO_IT_MYSELF ? 'diy' : how; + updateMigrationStatus( siteId, `migration-pending-${ parsedHow }` ); + } + + if ( onSubmit ) { + return onSubmit( { how, destination } ); + } + }; + + return { onOptionClick }; +}; + interface Props extends StepProps { headerText?: string; subHeaderText?: string; @@ -26,7 +64,6 @@ const SiteMigrationHowToMigrate: FC< Props > = ( props ) => { const { navigation, headerText } = props; const translate = useTranslate(); - const site = useSite(); const importSiteQueryParam = useQuery().get( 'from' ) || ''; usePresalesChat( 'wpcom' ); @@ -64,29 +101,14 @@ const SiteMigrationHowToMigrate: FC< Props > = ( props ) => { urlData ); + const { onOptionClick } = usePendingMigrationStatus( { onSubmit: navigation.submit } ); + const hostingProviderSlug = hostingProviderData?.hosting_provider?.slug; const shouldDisplayHostIdentificationMessage = hostingProviderSlug && hostingProviderSlug !== 'unknown' && hostingProviderSlug !== 'automattic'; - const canInstallPlugins = site?.plan?.features?.active.find( - ( feature ) => feature === 'install-plugins' - ) - ? true - : false; - - const { updateMigrationStatus } = useUpdateMigrationStatus(); - - const handleClick = ( how: string ) => { - const destination = canInstallPlugins ? 'migrate' : 'upgrade'; - if ( site?.ID ) { - const parsedHow = how === HOW_TO_MIGRATE_OPTIONS.DO_IT_MYSELF ? 'diy' : how; - updateMigrationStatus( site.ID, `migration-pending-${ parsedHow }` ); - } - return navigation.submit?.( { how, destination } ); - }; - const stepContent = ( <>
@@ -95,7 +117,7 @@ const SiteMigrationHowToMigrate: FC< Props > = ( props ) => { key={ i } title={ option.label } text={ option.description } - onClick={ () => handleClick( option.value ) } + onClick={ () => onOptionClick( option.value ) } /> ) ) }
From 7023a652b91b4516f28f45c1e672f96ad63448eb Mon Sep 17 00:00:00 2001 From: Renatho De Carli Rosa Date: Tue, 15 Oct 2024 17:08:17 -0300 Subject: [PATCH 2/4] Extract pending migration status hook --- .../site-migration-how-to-migrate/index.tsx | 45 ++----------------- .../use-pending-migration-status.ts | 45 +++++++++++++++++++ 2 files changed, 48 insertions(+), 42 deletions(-) create mode 100644 client/landing/stepper/declarative-flow/internals/steps-repository/site-migration-how-to-migrate/use-pending-migration-status.ts diff --git a/client/landing/stepper/declarative-flow/internals/steps-repository/site-migration-how-to-migrate/index.tsx b/client/landing/stepper/declarative-flow/internals/steps-repository/site-migration-how-to-migrate/index.tsx index fc86aa80912bb..39eb888eadf1a 100644 --- a/client/landing/stepper/declarative-flow/internals/steps-repository/site-migration-how-to-migrate/index.tsx +++ b/client/landing/stepper/declarative-flow/internals/steps-repository/site-migration-how-to-migrate/index.tsx @@ -1,60 +1,21 @@ import { StepContainer } from '@automattic/onboarding'; import { useTranslate } from 'i18n-calypso'; -import { FC, useMemo, useEffect } from 'react'; +import { FC, useMemo } from 'react'; import DocumentHead from 'calypso/components/data/document-head'; import FormattedHeader from 'calypso/components/formatted-header'; -import { useUpdateMigrationStatus } from 'calypso/data/site-migration/use-update-migration-status'; import { useAnalyzeUrlQuery } from 'calypso/data/site-profiler/use-analyze-url-query'; import { useHostingProviderQuery } from 'calypso/data/site-profiler/use-hosting-provider-query'; import { HOW_TO_MIGRATE_OPTIONS } from 'calypso/landing/stepper/constants'; import { useQuery } from 'calypso/landing/stepper/hooks/use-query'; -import { useSite } from 'calypso/landing/stepper/hooks/use-site'; import { recordTracksEvent } from 'calypso/lib/analytics/tracks'; import { usePresalesChat } from 'calypso/lib/presales-chat'; import useHostingProviderName from 'calypso/site-profiler/hooks/use-hosting-provider-name'; import FlowCard from '../components/flow-card'; -import type { NavigationControls, StepProps } from '../../types'; +import usePendingMigrationStatus from './use-pending-migration-status'; +import type { StepProps } from '../../types'; import './style.scss'; -interface PendingMigrationStatusProps { - onSubmit?: Pick< NavigationControls, 'submit' >[ 'submit' ]; -} - -const usePendingMigrationStatus = ( { onSubmit }: PendingMigrationStatusProps ) => { - const site = useSite(); - const siteId = site?.ID; - - const canInstallPlugins = site?.plan?.features?.active.find( - ( feature ) => feature === 'install-plugins' - ) - ? true - : false; - - const { updateMigrationStatus } = useUpdateMigrationStatus(); - - // Register pending migration status when loading the step. - useEffect( () => { - if ( siteId ) { - updateMigrationStatus( siteId, 'migration-pending' ); - } - }, [ siteId, updateMigrationStatus ] ); - - const onOptionClick = ( how: string ) => { - const destination = canInstallPlugins ? 'migrate' : 'upgrade'; - if ( siteId ) { - const parsedHow = how === HOW_TO_MIGRATE_OPTIONS.DO_IT_MYSELF ? 'diy' : how; - updateMigrationStatus( siteId, `migration-pending-${ parsedHow }` ); - } - - if ( onSubmit ) { - return onSubmit( { how, destination } ); - } - }; - - return { onOptionClick }; -}; - interface Props extends StepProps { headerText?: string; subHeaderText?: string; diff --git a/client/landing/stepper/declarative-flow/internals/steps-repository/site-migration-how-to-migrate/use-pending-migration-status.ts b/client/landing/stepper/declarative-flow/internals/steps-repository/site-migration-how-to-migrate/use-pending-migration-status.ts new file mode 100644 index 0000000000000..e54d96a9f5f6b --- /dev/null +++ b/client/landing/stepper/declarative-flow/internals/steps-repository/site-migration-how-to-migrate/use-pending-migration-status.ts @@ -0,0 +1,45 @@ +import { useEffect } from 'react'; +import { useUpdateMigrationStatus } from 'calypso/data/site-migration/use-update-migration-status'; +import { HOW_TO_MIGRATE_OPTIONS } from 'calypso/landing/stepper/constants'; +import { useSite } from 'calypso/landing/stepper/hooks/use-site'; +import type { NavigationControls } from '../../types'; + +interface PendingMigrationStatusProps { + onSubmit?: Pick< NavigationControls, 'submit' >[ 'submit' ]; +} + +const usePendingMigrationStatus = ( { onSubmit }: PendingMigrationStatusProps ) => { + const site = useSite(); + const siteId = site?.ID; + + const canInstallPlugins = site?.plan?.features?.active.find( + ( feature ) => feature === 'install-plugins' + ) + ? true + : false; + + const { updateMigrationStatus } = useUpdateMigrationStatus(); + + // Register pending migration status when loading the step. + useEffect( () => { + if ( siteId ) { + updateMigrationStatus( siteId, 'migration-pending' ); + } + }, [ siteId, updateMigrationStatus ] ); + + const onOptionClick = ( how: string ) => { + const destination = canInstallPlugins ? 'migrate' : 'upgrade'; + if ( siteId ) { + const parsedHow = how === HOW_TO_MIGRATE_OPTIONS.DO_IT_MYSELF ? 'diy' : how; + updateMigrationStatus( siteId, `migration-pending-${ parsedHow }` ); + } + + if ( onSubmit ) { + return onSubmit( { how, destination } ); + } + }; + + return { onOptionClick }; +}; + +export default usePendingMigrationStatus; From 970ce0c32ff92724e13fb053e4b95a0541663194 Mon Sep 17 00:00:00 2001 From: Renatho De Carli Rosa Date: Mon, 21 Oct 2024 16:26:44 -0300 Subject: [PATCH 3/4] Add tests --- .../test/index.tsx | 100 ++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 client/landing/stepper/declarative-flow/internals/steps-repository/site-migration-how-to-migrate/test/index.tsx diff --git a/client/landing/stepper/declarative-flow/internals/steps-repository/site-migration-how-to-migrate/test/index.tsx b/client/landing/stepper/declarative-flow/internals/steps-repository/site-migration-how-to-migrate/test/index.tsx new file mode 100644 index 0000000000000..462bb5a70898c --- /dev/null +++ b/client/landing/stepper/declarative-flow/internals/steps-repository/site-migration-how-to-migrate/test/index.tsx @@ -0,0 +1,100 @@ +/** + * @jest-environment jsdom + */ +import { fireEvent } from '@testing-library/react'; +import React from 'react'; +import { useUpdateMigrationStatus } from 'calypso/data/site-migration/use-update-migration-status'; +import { RenderStepOptions, mockStepProps, renderStep } from '../../test/helpers'; +import SiteMigrationHowToMigrate from '../index'; +import type { StepProps } from '../../../types'; + +const siteId = 1; + +jest.mock( 'calypso/data/site-migration/use-update-migration-status', () => ( { + useUpdateMigrationStatus: jest.fn(), +} ) ); + +jest.mock( 'calypso/lib/presales-chat', () => ( { + usePresalesChat: jest.fn(), +} ) ); + +jest.mock( 'calypso/data/site-profiler/use-analyze-url-query', () => ( { + useAnalyzeUrlQuery: () => ( { data: {} } ), +} ) ); + +jest.mock( 'calypso/data/site-profiler/use-hosting-provider-query', () => ( { + useHostingProviderQuery: () => ( { data: {} } ), +} ) ); + +jest.mock( 'calypso/site-profiler/hooks/use-hosting-provider-name', () => jest.fn() ); + +jest.mock( 'calypso/landing/stepper/hooks/use-site', () => ( { + useSite: jest.fn( () => ( { + ID: siteId, + } ) ), +} ) ); + +const render = ( props?: Partial< StepProps >, renderOptions?: RenderStepOptions ) => { + const combinedProps = { ...mockStepProps( props ) }; + return renderStep( , renderOptions ); +}; + +describe( 'SiteMigrationHowToMigrate', () => { + const mockSubmit = jest.fn(); + let mockUpdateMigrationStatus; + + beforeEach( () => { + mockUpdateMigrationStatus = jest.fn(); + ( useUpdateMigrationStatus as jest.Mock ).mockReturnValue( { + updateMigrationStatus: mockUpdateMigrationStatus, + } ); + } ); + + it( 'should register pending migration status when the component is loaded', () => { + render( { navigation: { submit: mockSubmit } } ); + + expect( mockUpdateMigrationStatus ).toHaveBeenCalledWith( siteId, 'migration-pending' ); + } ); + + it( 'should call updateMigrationStatus with correct value for DIFM option', () => { + const { getByText } = render( { navigation: { submit: mockSubmit } } ); + + const optionButton = getByText( 'Do it for me' ); + fireEvent.click( optionButton ); + + // Check the last call value + const lastCallValue = + mockUpdateMigrationStatus.mock.calls[ mockUpdateMigrationStatus.mock.calls.length - 1 ][ 1 ]; + expect( lastCallValue ).toBe( 'migration-pending-difm' ); + } ); + + it( 'should call updateMigrationStatus with correct value for DIY option', () => { + const { getByText } = render( { navigation: { submit: mockSubmit } } ); + + const optionButton = getByText( "I'll do it myself" ); + fireEvent.click( optionButton ); + + // Check the last call value + const lastCallValue = + mockUpdateMigrationStatus.mock.calls[ mockUpdateMigrationStatus.mock.calls.length - 1 ][ 1 ]; + expect( lastCallValue ).toBe( 'migration-pending-diy' ); + } ); + + it( 'should call submit with correct value when DIFM option is clicked', () => { + const { getByText } = render( { navigation: { submit: mockSubmit } } ); + + const optionButton = getByText( 'Do it for me' ); + fireEvent.click( optionButton ); + + expect( mockSubmit ).toHaveBeenCalledWith( { destination: 'upgrade', how: 'difm' } ); + } ); + + it( 'should call submit with correct value for DIY option', () => { + const { getByText } = render( { navigation: { submit: mockSubmit } } ); + + const optionButton = getByText( "I'll do it myself" ); + fireEvent.click( optionButton ); + + expect( mockSubmit ).toHaveBeenCalledWith( { destination: 'upgrade', how: 'myself' } ); + } ); +} ); From 4c8171449b01715a2e91a6cc8babf13f67410718 Mon Sep 17 00:00:00 2001 From: Renatho De Carli Rosa Date: Wed, 23 Oct 2024 11:50:38 -0300 Subject: [PATCH 4/4] Update function name to not be opinionated Co-authored-by: Gabriel Caires --- .../steps-repository/site-migration-how-to-migrate/index.tsx | 4 ++-- .../use-pending-migration-status.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/client/landing/stepper/declarative-flow/internals/steps-repository/site-migration-how-to-migrate/index.tsx b/client/landing/stepper/declarative-flow/internals/steps-repository/site-migration-how-to-migrate/index.tsx index 39eb888eadf1a..f0ae72294280c 100644 --- a/client/landing/stepper/declarative-flow/internals/steps-repository/site-migration-how-to-migrate/index.tsx +++ b/client/landing/stepper/declarative-flow/internals/steps-repository/site-migration-how-to-migrate/index.tsx @@ -62,7 +62,7 @@ const SiteMigrationHowToMigrate: FC< Props > = ( props ) => { urlData ); - const { onOptionClick } = usePendingMigrationStatus( { onSubmit: navigation.submit } ); + const { setPendingMigration } = usePendingMigrationStatus( { onSubmit: navigation.submit } ); const hostingProviderSlug = hostingProviderData?.hosting_provider?.slug; const shouldDisplayHostIdentificationMessage = @@ -78,7 +78,7 @@ const SiteMigrationHowToMigrate: FC< Props > = ( props ) => { key={ i } title={ option.label } text={ option.description } - onClick={ () => onOptionClick( option.value ) } + onClick={ () => setPendingMigration( option.value ) } /> ) ) } diff --git a/client/landing/stepper/declarative-flow/internals/steps-repository/site-migration-how-to-migrate/use-pending-migration-status.ts b/client/landing/stepper/declarative-flow/internals/steps-repository/site-migration-how-to-migrate/use-pending-migration-status.ts index e54d96a9f5f6b..8298129f1898d 100644 --- a/client/landing/stepper/declarative-flow/internals/steps-repository/site-migration-how-to-migrate/use-pending-migration-status.ts +++ b/client/landing/stepper/declarative-flow/internals/steps-repository/site-migration-how-to-migrate/use-pending-migration-status.ts @@ -27,7 +27,7 @@ const usePendingMigrationStatus = ( { onSubmit }: PendingMigrationStatusProps ) } }, [ siteId, updateMigrationStatus ] ); - const onOptionClick = ( how: string ) => { + const setPendingMigration = ( how: string ) => { const destination = canInstallPlugins ? 'migrate' : 'upgrade'; if ( siteId ) { const parsedHow = how === HOW_TO_MIGRATE_OPTIONS.DO_IT_MYSELF ? 'diy' : how; @@ -39,7 +39,7 @@ const usePendingMigrationStatus = ( { onSubmit }: PendingMigrationStatusProps ) } }; - return { onOptionClick }; + return { setPendingMigration }; }; export default usePendingMigrationStatus;