diff --git a/src/components/site-menu.tsx b/src/components/site-menu.tsx index 51432d4b17..32b94c37e8 100644 --- a/src/components/site-menu.tsx +++ b/src/components/site-menu.tsx @@ -2,6 +2,7 @@ import { speak } from '@wordpress/a11y'; import { Spinner } from '@wordpress/components'; import { __, sprintf } from '@wordpress/i18n'; import { useEffect } from 'react'; +import { useSyncSites } from '../hooks/sync-sites'; import { useImportExport } from '../hooks/use-import-export'; import { useSiteDetails } from '../hooks/use-site-details'; import { isMac } from '../lib/app-globals'; @@ -108,9 +109,24 @@ function ButtonToRun( { running, id, name }: Pick< SiteDetails, 'running' | 'id' } function SiteItem( { site }: { site: SiteDetails } ) { const { selectedSite, setSelectedSiteId } = useSiteDetails(); - const { isSiteImporting } = useImportExport(); const isSelected = site === selectedSite; + const { isSiteImporting } = useImportExport(); + const { isSiteIdPulling } = useSyncSites(); const isImporting = isSiteImporting( site.id ); + const isPulling = isSiteIdPulling( site.id ); + const showSpinner = site.isAddingSite || isImporting || isPulling; + + let tooltipText; + if ( site.isAddingSite ) { + tooltipText = __( 'Adding' ); + } else if ( isImporting ) { + tooltipText = __( 'Importing' ); + } else if ( isPulling ) { + tooltipText = __( 'Syncing' ); + } else { + tooltipText = __( 'Loading' ); + } + return (
  • { site.name } - { site.isAddingSite || isImporting ? ( - + { showSpinner ? ( + +
    + +
    +
    ) : ( ) } diff --git a/src/components/tests/main-sidebar.test.tsx b/src/components/tests/main-sidebar.test.tsx index c235fc5820..76cc662a43 100644 --- a/src/components/tests/main-sidebar.test.tsx +++ b/src/components/tests/main-sidebar.test.tsx @@ -1,5 +1,6 @@ import { render, act, screen } from '@testing-library/react'; import { userEvent } from '@testing-library/user-event'; +import { SyncSitesProvider } from '../../hooks/sync-sites'; import { useAuth } from '../../hooks/use-auth'; import MainSidebar from '../main-sidebar'; @@ -55,46 +56,50 @@ jest.mock( '../../hooks/use-site-details', () => ( { useSiteDetails: () => ( { ...siteDetailsMocked } ), } ) ); +const renderWithProvider = ( children: React.ReactElement ) => { + return render( { children } ); +}; + describe( 'MainSidebar Footer', () => { beforeEach( () => { jest.clearAllMocks(); } ); it( 'Has add site button', async () => { ( useAuth as jest.Mock ).mockReturnValue( { isAuthenticated: false } ); - await act( async () => render( ) ); + await act( async () => renderWithProvider( ) ); expect( screen.getByRole( 'button', { name: 'Add site' } ) ).toBeVisible(); } ); it( 'applies className prop', async () => { const { container } = await act( async () => - render( ) + renderWithProvider( ) ); expect( container.firstChild ).toHaveClass( 'test-class' ); } ); it( 'shows a "Stop All" button when there are running sites', async () => { - await act( async () => render( ) ); + await act( async () => renderWithProvider( ) ); expect( screen.getByRole( 'button', { name: 'Stop all' } ) ).toBeVisible(); } ); } ); describe( 'MainSidebar Site Menu', () => { it( 'renders the list of sites', async () => { - await act( async () => render( ) ); + await act( async () => renderWithProvider( ) ); expect( screen.getByRole( 'button', { name: 'test-1' } ) ).toBeVisible(); expect( screen.getByRole( 'button', { name: 'test-2' } ) ).toBeVisible(); expect( screen.getByRole( 'button', { name: 'test-3' } ) ).toBeVisible(); } ); it( 'has "start site" buttons when sites are not running', async () => { - await act( async () => render( ) ); + await act( async () => renderWithProvider( ) ); expect( screen.getByRole( 'button', { name: 'start test-1 site' } ) ).toBeVisible(); expect( screen.getByRole( 'button', { name: 'start test-2 site' } ) ).toBeVisible(); } ); it( 'starts a site', async () => { const user = userEvent.setup(); - await act( async () => render( ) ); + await act( async () => renderWithProvider( ) ); const greenDotFirstSite = screen.getByRole( 'button', { name: 'start test-1 site' } ); expect( greenDotFirstSite ).toBeVisible(); await user.click( greenDotFirstSite ); @@ -105,7 +110,7 @@ describe( 'MainSidebar Site Menu', () => { it( 'stops a site', async () => { const user = userEvent.setup(); - await act( async () => render( ) ); + await act( async () => renderWithProvider( ) ); const greenDotFirstSite = screen.getByRole( 'button', { name: 'stop test-3 site' } ); expect( greenDotFirstSite ).toBeVisible(); await user.click( greenDotFirstSite );