165 lines
5.0 KiB
TypeScript
165 lines
5.0 KiB
TypeScript
|
/**
|
||
|
* External dependencies
|
||
|
*/
|
||
|
import * as navigation from '@woocommerce/navigation';
|
||
|
/**
|
||
|
* Internal dependencies
|
||
|
*/
|
||
|
import { updateQueryParams, createQueryParamsListener } from '../common';
|
||
|
|
||
|
jest.mock( '@woocommerce/navigation', () => ( {
|
||
|
getHistory: jest.fn(),
|
||
|
getQuery: jest.fn(),
|
||
|
updateQueryString: jest.fn(),
|
||
|
} ) );
|
||
|
|
||
|
const mockedGetQuery = navigation.getQuery as jest.Mock;
|
||
|
const mockedUpdateQueryString = navigation.updateQueryString as jest.Mock;
|
||
|
const mockedGetHistory = navigation.getHistory as jest.Mock;
|
||
|
|
||
|
describe( 'updateQueryParams', () => {
|
||
|
beforeEach( () => {
|
||
|
jest.clearAllMocks();
|
||
|
} );
|
||
|
|
||
|
it( 'calls updateQueryString with correct changes', () => {
|
||
|
mockedGetQuery.mockReturnValue( {
|
||
|
sidebar: 'oldSidebar',
|
||
|
content: 'oldContent',
|
||
|
} );
|
||
|
const changes = { sidebar: 'newSidebar', content: 'newContent' };
|
||
|
updateQueryParams( changes );
|
||
|
expect( mockedUpdateQueryString ).toHaveBeenCalledWith( changes );
|
||
|
} );
|
||
|
|
||
|
it( 'does not call updateQueryString when new values match current ones', () => {
|
||
|
mockedGetQuery.mockReturnValue( {
|
||
|
sidebar: 'sameSidebar',
|
||
|
content: 'sameContent',
|
||
|
} );
|
||
|
updateQueryParams( { sidebar: 'sameSidebar', content: 'sameContent' } );
|
||
|
expect( mockedUpdateQueryString ).not.toHaveBeenCalled();
|
||
|
} );
|
||
|
|
||
|
// note that in this test and the below tests, we use .mock.lastCall and .toStrictEqual so that
|
||
|
// we can distinguish the difference between { content: 'bar', sidebar: undefined } and { content: 'bar }
|
||
|
// this is important because calling it with sidebar: undefined will unset the sidebar query parameter,
|
||
|
// while calling it without the sidebar key will leave the existing sidebar query parameter if any
|
||
|
it( 'calls updateQueryString with both parameters as undefined if passed in', () => {
|
||
|
mockedGetQuery.mockReturnValue( {
|
||
|
sidebar: 'existingSidebar',
|
||
|
content: 'existingContent',
|
||
|
} );
|
||
|
const changes = { sidebar: undefined, content: undefined };
|
||
|
updateQueryParams( changes );
|
||
|
expect( mockedUpdateQueryString.mock.lastCall[ 0 ] ).toStrictEqual(
|
||
|
changes
|
||
|
);
|
||
|
} );
|
||
|
|
||
|
it( 'correctly updates with undefined if one parameter is undefined', () => {
|
||
|
mockedGetQuery.mockReturnValue( {
|
||
|
sidebar: 'existingSidebar',
|
||
|
content: 'existingContent',
|
||
|
} );
|
||
|
const changes = { sidebar: 'newSidebar', content: undefined };
|
||
|
updateQueryParams( changes );
|
||
|
expect( mockedUpdateQueryString.mock.lastCall[ 0 ] ).toStrictEqual(
|
||
|
changes
|
||
|
);
|
||
|
} );
|
||
|
|
||
|
it( 'only updates changes that are different', () => {
|
||
|
mockedGetQuery.mockReturnValue( {
|
||
|
sidebar: 'existingSidebar',
|
||
|
content: 'existingContent',
|
||
|
} );
|
||
|
const changes = { sidebar: 'newSidebar', content: 'existingContent' };
|
||
|
updateQueryParams( changes );
|
||
|
expect( mockedUpdateQueryString.mock.lastCall[ 0 ] ).toStrictEqual( {
|
||
|
sidebar: 'newSidebar',
|
||
|
} );
|
||
|
} );
|
||
|
|
||
|
it( 'only updates changes that are passed in', () => {
|
||
|
mockedGetQuery.mockReturnValue( {
|
||
|
sidebar: 'existingSidebar',
|
||
|
} );
|
||
|
const changes = { sidebar: 'newSidebar' };
|
||
|
updateQueryParams( changes );
|
||
|
expect( mockedUpdateQueryString.mock.lastCall[ 0 ] ).toStrictEqual(
|
||
|
changes
|
||
|
);
|
||
|
} );
|
||
|
} );
|
||
|
|
||
|
describe( 'createQueryParamsListener', () => {
|
||
|
let unlistenMock: jest.Mock;
|
||
|
let sendBackMock: jest.Mock;
|
||
|
let historyMock: { listen: jest.Mock; location: { search: string } };
|
||
|
|
||
|
beforeEach( () => {
|
||
|
sendBackMock = jest.fn();
|
||
|
unlistenMock = jest.fn();
|
||
|
historyMock = {
|
||
|
listen: jest.fn().mockImplementation( () => {
|
||
|
return unlistenMock;
|
||
|
} ),
|
||
|
location: { search: '?test=sameValue' },
|
||
|
};
|
||
|
mockedGetHistory.mockReturnValue( historyMock );
|
||
|
} );
|
||
|
|
||
|
afterEach( () => {
|
||
|
jest.clearAllMocks();
|
||
|
} );
|
||
|
|
||
|
it( 'registers and unregisters the listener', () => {
|
||
|
const unlisten = createQueryParamsListener( 'test', sendBackMock );
|
||
|
expect( historyMock.listen ).toHaveBeenCalled();
|
||
|
unlisten();
|
||
|
expect( unlistenMock ).toHaveBeenCalled();
|
||
|
} );
|
||
|
|
||
|
it( 'calls sendBack when the specified query parameter changes', () => {
|
||
|
const paramName = 'test';
|
||
|
createQueryParamsListener( paramName, sendBackMock );
|
||
|
|
||
|
// Simulate a query param change
|
||
|
historyMock.listen.mock.calls[ 0 ][ 0 ]( {
|
||
|
action: 'POP',
|
||
|
location: { search: `?${ paramName }=newValue` },
|
||
|
} );
|
||
|
|
||
|
expect( sendBackMock ).toHaveBeenCalledWith( {
|
||
|
type: 'EXTERNAL_URL_UPDATE',
|
||
|
} );
|
||
|
} );
|
||
|
|
||
|
it( "does not call sendBack when the query parameter that changes isn't what we are listening to", () => {
|
||
|
const paramName = 'test';
|
||
|
createQueryParamsListener( paramName, sendBackMock );
|
||
|
|
||
|
// Simulate a navigation that does not change the specific query param
|
||
|
historyMock.listen.mock.calls[ 0 ][ 0 ]( {
|
||
|
action: 'POP',
|
||
|
location: { search: '?test=sameValue&anotherParam=different' },
|
||
|
} );
|
||
|
|
||
|
expect( sendBackMock ).not.toHaveBeenCalled();
|
||
|
} );
|
||
|
|
||
|
it( 'does not call sendBack when action is not POP', () => {
|
||
|
const paramName = 'test';
|
||
|
createQueryParamsListener( paramName, sendBackMock );
|
||
|
|
||
|
// Simulate a PUSH action
|
||
|
historyMock.listen.mock.calls[ 0 ][ 0 ]( {
|
||
|
action: 'PUSH',
|
||
|
location: { search: `?${ paramName }=newValue` },
|
||
|
} );
|
||
|
|
||
|
expect( sendBackMock ).not.toHaveBeenCalled();
|
||
|
} );
|
||
|
} );
|