/** * External dependencies */ import { render, screen, fireEvent, act, createEvent, } from '@testing-library/react'; import { useSelect } from '@wordpress/data'; import { useUser, useUserPreferences } from '@woocommerce/data'; import { useState } from '@wordpress/element'; /** * Internal dependencies */ import { ActivityPanel } from '../activity-panel'; import { Panel } from '../panel'; jest.mock( '@woocommerce/admin-layout', () => { const mockContext = { layoutPath: [ 'home' ], layoutString: 'home', extendLayout: () => {}, isDescendantOf: () => false, }; return { ...jest.requireActual( '@woocommerce/admin-layout' ), useLayoutContext: jest.fn().mockReturnValue( mockContext ), useExtendLayout: jest.fn().mockReturnValue( mockContext ), }; } ); jest.mock( '@woocommerce/data', () => ( { ...jest.requireActual( '@woocommerce/data' ), useUser: jest.fn().mockReturnValue( { currentUserCan: () => true } ), useUserPreferences: jest.fn().mockReturnValue( { updateUserPreferences: () => {}, } ), } ) ); // We aren't testing the component here. jest.mock( '../display-options', () => ( { DisplayOptions: jest.fn().mockReturnValue( '[DisplayOptions]' ), } ) ); jest.mock( '../highlight-tooltip', () => ( { HighlightTooltip: jest.fn().mockReturnValue( '[HighlightTooltip]' ), } ) ); jest.mock( '@wordpress/data', () => { // Require the original module to not be mocked... const originalModule = jest.requireActual( '@wordpress/data' ); return { __esModule: true, // Use it when dealing with esModules ...originalModule, useSelect: jest.fn().mockReturnValue( {} ), }; } ); jest.mock( '../panel', () => { const originalModule = jest.requireActual( '../panel' ); return { __esModule: true, ...originalModule, Panel: jest.fn(), }; } ); describe( 'Activity Panel', () => { beforeEach( () => { useSelect.mockImplementation( () => ( { hasUnreadNotifications: false, requestingTaskListOptions: false, setupTaskListComplete: false, setupTaskListHidden: false, trackedCompletedTasks: [], } ) ); Panel.mockImplementation( jest.requireActual( '../panel' ).Panel ); useUser.mockImplementation( () => ( { currentUserCan: () => true, } ) ); } ); it( 'should render inbox tab on embedded pages', () => { render( ); expect( screen.getByText( 'Activity' ) ).toBeDefined(); } ); it( 'should render inbox tab if not on home screen', () => { render( ); expect( screen.getByText( 'Activity' ) ).toBeDefined(); } ); it( 'should not render inbox tab on home screen', () => { render( ); expect( screen.queryByText( 'Inbox' ) ).toBeNull(); } ); it( 'should render preview store tab on home screen', () => { render( ); expect( screen.getByText( 'Preview store' ) ).toBeDefined(); } ); it( 'should not render help tab if not on home screen', () => { render( ); expect( screen.queryByTestId( 'activity-panel-tab-help' ) ).toBeNull(); } ); it( 'should render help tab if on home screen', () => { render( ); expect( screen.queryByTestId( 'activity-panel-tab-help' ) ).toBeDefined(); } ); it( 'should render help tab before options load', async () => { useSelect.mockImplementation( () => ( { requestingTaskListOptions: true, } ) ); render( ); const tabs = await screen.findAllByRole( 'tab' ); // Expect that the only tab is "Help". expect( tabs ).toHaveLength( 1 ); expect( screen.queryByTestId( 'activity-panel-tab-help' ) ).toBeDefined(); } ); it( 'should not render help tab when not on main route', () => { render( ); // Expect that "Help" tab is absent. expect( screen.queryByText( 'Help' ) ).toBeNull(); } ); it( 'should render display options if on home screen', () => { render( ); expect( screen.getByText( '[DisplayOptions]' ) ).toBeDefined(); } ); it( 'should only render the finish setup link when TaskList is not complete', () => { const { queryByText, rerender } = render( ); expect( queryByText( 'Finish setup' ) ).toBeDefined(); useSelect.mockImplementation( () => ( { requestingTaskListOptions: false, setupTaskListComplete: true, setupTaskListHidden: false, } ) ); rerender( ); expect( queryByText( 'Finish setup' ) ).toBeNull(); } ); it( 'should not render the finish setup link when on the home screen and TaskList is not complete', () => { const { queryByText } = render( ); expect( queryByText( 'Finish setup' ) ).toBeNull(); } ); it( 'should render the finish setup link when on embedded pages and TaskList is not complete', () => { const { getByText } = render( ); expect( getByText( 'Finish setup' ) ).toBeInTheDocument(); } ); it( 'should not render the finish setup link when a user does not have capabilities', () => { useUser.mockImplementation( () => ( { currentUserCan: () => false, } ) ); const { queryByText } = render( ); expect( queryByText( 'Finish setup' ) ).toBeDefined(); } ); describe( 'help panel tooltip', () => { it( 'should render highlight tooltip when task count is at-least 2, task is not completed, and tooltip not shown yet', () => { useUserPreferences.mockReturnValue( { updateUserPreferences: () => {}, task_list_tracked_started_tasks: { payment: 2 }, } ); const { getByText } = render( ); expect( getByText( '[HighlightTooltip]' ) ).toBeInTheDocument(); } ); it( 'should not render highlight tooltip when task is not visited more then once', () => { useSelect.mockImplementation( () => ( { requestingTaskListOptions: false, setupTaskListComplete: false, setupTaskListHidden: false, trackedCompletedTasks: [], } ) ); useUserPreferences.mockReturnValue( { updateUserPreferences: () => {}, task_list_tracked_started_tasks: { payment: 1 }, } ); render( ); expect( screen.queryByText( '[HighlightTooltip]' ) ).toBeNull(); useUserPreferences.mockReturnValue( { updateUserPreferences: () => {}, task_list_tracked_started_tasks: {}, } ); render( ); expect( screen.queryByText( '[HighlightTooltip]' ) ).toBeNull(); } ); it( 'should not render highlight tooltip when task is visited twice, but completed already', () => { useSelect.mockImplementation( () => ( { requestingTaskListOptions: false, setupTaskListComplete: false, setupTaskListHidden: false, isCompletedTask: true, } ) ); useUserPreferences.mockReturnValue( { updateUserPreferences: () => {}, task_list_tracked_started_tasks: { payment: 2 }, } ); const { queryByText } = render( ); expect( queryByText( '[HighlightTooltip]' ) ).toBeNull(); } ); it( 'should not render highlight tooltip when task is visited twice, not completed, but already shown', () => { useUserPreferences.mockReturnValue( { task_list_tracked_started_tasks: { payment: 2 }, help_panel_highlight_shown: 'yes', } ); const { queryByText } = render( ); expect( queryByText( '[HighlightTooltip]' ) ).toBeNull(); } ); } ); describe( 'panel', () => { it( 'should set focus when panel opened/closed without removing element when onTransitionEnd is triggered', () => { const content = 'test'; const TestComponent = () => { const [ panelOpen, setPanelOpen ] = useState( true ); return (
{} } />
); }; const { container, queryByText, getByRole } = render( ); expect( queryByText( 'test' ) ).toBeInTheDocument(); expect( document.activeElement ).toEqual( container.getElementsByClassName( 'woocommerce-layout__activity-panel-wrapper' )[ 0 ] ); getByRole( 'button' ).focus(); expect( document.activeElement ).not.toEqual( container.getElementsByClassName( 'woocommerce-layout__activity-panel-wrapper' )[ 0 ] ); fireEvent.click( getByRole( 'button' ) ); fireEvent.click( getByRole( 'button' ) ); const event = createEvent.transitionEnd( container.getElementsByClassName( 'woocommerce-layout__activity-panel-wrapper' )[ 0 ] ); Object.defineProperty( event, 'propertyName', { value: 'transform', } ); fireEvent( container.getElementsByClassName( 'woocommerce-layout__activity-panel-wrapper' )[ 0 ], event ); expect( document.activeElement ).toEqual( container.getElementsByClassName( 'woocommerce-layout__activity-panel-wrapper' )[ 0 ] ); } ); } ); describe( 'panel open and closing', () => { let clearPanel; beforeEach( () => { Panel.mockImplementation( ( { isPanelOpen, isPanelSwitching, tab, ...props } ) => { clearPanel = props.clearPanel; return (
[panel] [panelOpen={ isPanelOpen.toString() }] [panelSwitching={ isPanelSwitching.toString() }] [hasTab={ tab ? 'true' : 'false' }]
); } ); } ); it( 'should have panel open and panel switching as false by default', () => { const { queryByText } = render( ); expect( queryByText( '[panel]' ) ).toBeInTheDocument(); expect( queryByText( '[panelOpen=false]' ) ).toBeInTheDocument(); expect( queryByText( '[panelSwitching=false]' ) ).toBeInTheDocument(); fireEvent.click( screen.queryByTestId( 'activity-panel-tab-help' ) ); } ); it( 'should allow user to toggle, an individual panel without setting panelSwitching to true', () => { const { queryByText } = render( ); expect( queryByText( '[panel]' ) ).toBeInTheDocument(); expect( queryByText( '[panelOpen=false]' ) ).toBeInTheDocument(); expect( queryByText( '[panelSwitching=false]' ) ).toBeInTheDocument(); // toggle open fireEvent.click( screen.queryByTestId( 'activity-panel-tab-help' ) ); expect( queryByText( '[panelOpen=true]' ) ).toBeInTheDocument(); expect( queryByText( '[panelSwitching=false]' ) ).toBeInTheDocument(); // toggle close fireEvent.click( screen.queryByTestId( 'activity-panel-tab-help' ) ); expect( queryByText( '[panelOpen=false]' ) ).toBeInTheDocument(); expect( queryByText( '[panelSwitching=false]' ) ).toBeInTheDocument(); } ); it( 'should remove panel element after clearPanel is triggered', () => { const { queryByText } = render( ); // toggle open fireEvent.click( screen.queryByTestId( 'activity-panel-tab-help' ) ); expect( queryByText( '[panelOpen=true]' ) ).toBeInTheDocument(); expect( queryByText( '[panelSwitching=false]' ) ).toBeInTheDocument(); // toggle close fireEvent.click( screen.queryByTestId( 'activity-panel-tab-help' ) ); expect( queryByText( '[panelOpen=false]' ) ).toBeInTheDocument(); expect( queryByText( '[hasTab=true]' ) ).toBeInTheDocument(); expect( queryByText( '[panelSwitching=false]' ) ).toBeInTheDocument(); act( () => { clearPanel(); } ); expect( queryByText( '[hasTab=false]' ) ).toBeInTheDocument(); } ); } ); } );