/** * External dependencies */ import { render, screen, act } from '@testing-library/react'; import { addFilter, removeFilter } from '@wordpress/hooks'; import { recordPageView } from '@woocommerce/tracks'; import * as navigation from '@woocommerce/navigation'; /** * Internal dependencies */ import { updateLinkHref, PAGES_FILTER } from '../controller'; import { EmbedLayout, PageLayout } from '../index'; jest.mock( '@wordpress/data', () => ( { ...jest.requireActual( '@wordpress/data' ), useSelect: jest.fn().mockReturnValue( {} ), } ) ); jest.mock( '@woocommerce/data', () => ( { ...jest.requireActual( '@woocommerce/data' ), useUser: jest.fn().mockReturnValue( { currentUserCan: () => true } ), } ) ); jest.mock( '@woocommerce/customer-effort-score', () => ( { CustomerEffortScoreModalContainer: () => null, triggerExitPageCesSurvey: jest.fn(), } ) ); jest.mock( '@woocommerce/components', () => ( { ...jest.requireActual( '@woocommerce/components' ), Spinner: jest.fn( () =>
spinner
), } ) ); jest.mock( '~/activity-panel', () => null ); jest.mock( '~/utils/admin-settings', () => { const adminSetting = jest.requireActual( '~/utils/admin-settings' ); return { ...adminSetting, getAdminSetting: jest.fn().mockImplementation( ( name, ...args ) => { if ( name === 'woocommerceTranslation' ) { return 'WooCommerce'; } return adminSetting.getAdminSetting( name, ...args ); } ), }; } ); jest.mock( '@woocommerce/navigation', () => ( { ...jest.requireActual( '@woocommerce/navigation' ), getHistory: jest.fn(), } ) ); const mockedGetHistory = navigation.getHistory; describe( 'updateLinkHref', () => { const timeExcludedScreens = [ 'stock', 'settings', 'customers' ]; const REPORT_URL = 'http://example.com/wp-admin/admin.php?page=wc-admin&path=/analytics/orders'; const DASHBOARD_URL = 'http://example.com/wp-admin/admin.php?page=wc-admin'; const REPORT_URL_TIME_EXCLUDED = 'http://example.com/wp-admin/admin.php?page=wc-admin&path=/analytics/settings'; const WOO_URL = 'http://example.com/wp-admin/edit.php?post_type=shop_coupon'; const WP_ADMIN_URL = 'http://example.com/wp-admin/edit-comments.php'; const nextQuery = { fruit: 'apple', dish: 'cobbler', }; it( 'should update report urls', () => { const item = { href: REPORT_URL }; updateLinkHref( item, nextQuery, timeExcludedScreens ); const encodedPath = encodeURIComponent( '/analytics/orders' ); expect( item.href ).toBe( `admin.php?page=wc-admin&path=${ encodedPath }&fruit=apple&dish=cobbler` ); } ); it( 'should update dashboard urls', () => { const item = { href: DASHBOARD_URL }; updateLinkHref( item, nextQuery, timeExcludedScreens ); expect( item.href ).toBe( 'admin.php?page=wc-admin&fruit=apple&dish=cobbler' ); } ); it( 'should not add the nextQuery to a time excluded screen', () => { const item = { href: REPORT_URL_TIME_EXCLUDED }; updateLinkHref( item, nextQuery, timeExcludedScreens ); const encodedPath = encodeURIComponent( '/analytics/settings' ); expect( item.href ).toBe( `admin.php?page=wc-admin&path=${ encodedPath }` ); } ); it( 'should not update WooCommerce urls', () => { const item = { href: WOO_URL }; updateLinkHref( item, nextQuery, timeExcludedScreens ); expect( item.href ).toBe( WOO_URL ); } ); it( 'should not update wp-admin urls', () => { const item = { href: WP_ADMIN_URL }; updateLinkHref( item, nextQuery, timeExcludedScreens ); expect( item.href ).toBe( WP_ADMIN_URL ); } ); it( 'should filter out undefined query values', () => { const item = { href: REPORT_URL }; updateLinkHref( item, { ...nextQuery, test: undefined, anotherParam: undefined }, timeExcludedScreens ); const encodedPath = encodeURIComponent( '/analytics/orders' ); expect( item.href ).toBe( `admin.php?page=wc-admin&path=${ encodedPath }&fruit=apple&dish=cobbler` ); } ); } ); describe( 'EmbedLayout', () => { it( 'should call recordPageView with correct parameters', () => { window.history.pushState( {}, 'Page Title', '/url?search' ); render( ); expect( recordPageView ).toHaveBeenCalledWith( '/url?search', { is_embedded: true, } ); } ); } ); describe( 'PageLayout', () => { beforeEach( () => { jest.spyOn( window, 'wpNavMenuClassChange' ).mockImplementation( jest.fn() ); jest.useFakeTimers(); jest.clearAllMocks(); } ); afterEach( () => { jest.useRealTimers(); jest.clearAllTimers(); } ); function mockPath( pathname ) { const historyMock = { listen: jest.fn().mockImplementation( () => jest.fn() ), location: { pathname }, }; mockedGetHistory.mockReturnValue( historyMock ); } it( 'should call recordPageView with correct parameters', () => { mockPath( '/analytics/overview' ); render( ); expect( recordPageView ).toHaveBeenCalledWith( 'analytics_overview', { jetpack_active: false, jetpack_connected: false, jetpack_installed: false, } ); } ); describe( 'NoMatch', () => { const message = 'Sorry, you are not allowed to access this page.'; it( 'should render a loading spinner first and then the error message after the delay', () => { mockPath( '/incorrect-path' ); render( ); expect( screen.getByText( 'spinner' ) ).toBeInTheDocument(); expect( screen.queryByText( message ) ).not.toBeInTheDocument(); act( () => { jest.runOnlyPendingTimers(); } ); expect( screen.queryByText( 'spinner' ) ).not.toBeInTheDocument(); expect( screen.getByText( message ) ).toBeInTheDocument(); } ); it( 'should render the page added after the initial filter has been run, not show the error message', () => { const namespace = `woocommerce/woocommerce/test_${ PAGES_FILTER }`; const path = '/test/greeting'; mockPath( path ); render( ); expect( screen.getByText( 'spinner' ) ).toBeInTheDocument(); expect( screen.queryByText( message ) ).not.toBeInTheDocument(); expect( screen.queryByRole( 'button', { name: 'Greet' } ) ).not.toBeInTheDocument(); act( () => { addFilter( PAGES_FILTER, namespace, ( pages ) => { return [ ...pages, { breadcrumbs: [ 'Greeting' ], container: () => , path, }, ]; } ); } ); expect( screen.queryByText( 'spinner' ) ).not.toBeInTheDocument(); expect( screen.queryByText( message ) ).not.toBeInTheDocument(); expect( screen.getByRole( 'button', { name: 'Greet' } ) ).toBeInTheDocument(); // Clean up the filter as filters are working globally. removeFilter( PAGES_FILTER, namespace ); } ); } ); } );