Skip to content

Commit cb82853

Browse files
committed
Add tests for overlay-bootstrap initial-load URL trigger
1 parent ec3131e commit cb82853

1 file changed

Lines changed: 121 additions & 0 deletions

File tree

  • projects/packages/search/src/search-blocks/overlay-bootstrap/test
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
/**
2+
* Tests for the Search blocks overlay bootstrap's initial-load URL trigger.
3+
*
4+
* The module runs side effects at import time (registers listeners and syncs
5+
* the overlay to the current URL), so each case sets up the DOM + URL +
6+
* `document.readyState`, then imports the module fresh via `jest.resetModules`.
7+
*/
8+
9+
// `ensureHydrated()` dynamically imports this; stub it so the hydration branch
10+
// no-ops instead of reaching for the real Interactivity runtime in jsdom.
11+
jest.mock( '@wordpress/interactivity', () => ( {} ), { virtual: true } );
12+
13+
const OVERLAY_ID = 'jetpack-search-block-overlay';
14+
15+
/**
16+
* Render the server-side overlay shell (closed) into the document body.
17+
*/
18+
function renderOverlayShell() {
19+
document.body.innerHTML = `
20+
<div id="${ OVERLAY_ID }" hidden>
21+
<div class="jetpack-search-block-overlay__content"></div>
22+
</div>
23+
<template id="jetpack-search-block-overlay-template"></template>
24+
`;
25+
}
26+
27+
/**
28+
* Point `window.location` at the given path+query without a real navigation.
29+
*
30+
* @param {string} url - Path with optional query string, e.g. `/?s=foo`.
31+
*/
32+
function setUrl( url ) {
33+
window.history.replaceState( {}, '', url );
34+
}
35+
36+
/**
37+
* Override `document.readyState` for the duration of a test.
38+
*
39+
* @param {string} value - `'loading'`, `'interactive'`, or `'complete'`.
40+
*/
41+
function setReadyState( value ) {
42+
Object.defineProperty( document, 'readyState', {
43+
configurable: true,
44+
get: () => value,
45+
} );
46+
}
47+
48+
/**
49+
* Import the bootstrap fresh and let the fire-and-forget `openOverlay` settle.
50+
*/
51+
async function loadBootstrap() {
52+
jest.resetModules();
53+
await import( '../index.js' );
54+
// `handlePopState` → `openOverlay` awaits hydration before toggling `hidden`;
55+
// flush the microtask queue so the attribute change has landed.
56+
await new Promise( resolve => setTimeout( resolve, 0 ) );
57+
}
58+
59+
const isOpen = () => ! document.getElementById( OVERLAY_ID ).hasAttribute( 'hidden' );
60+
61+
afterEach( () => {
62+
setReadyState( 'complete' );
63+
setUrl( '/' );
64+
document.body.innerHTML = '';
65+
} );
66+
67+
describe( 'overlay-bootstrap initial-load URL trigger', () => {
68+
it( 'opens the overlay on initial load when the URL has ?s=', async () => {
69+
setReadyState( 'complete' );
70+
renderOverlayShell();
71+
setUrl( '/?s=hello' );
72+
73+
await loadBootstrap();
74+
75+
expect( isOpen() ).toBe( true );
76+
} );
77+
78+
it( 'opens the overlay on initial load when the URL has ?q=', async () => {
79+
setReadyState( 'complete' );
80+
renderOverlayShell();
81+
setUrl( '/?q=hello' );
82+
83+
await loadBootstrap();
84+
85+
expect( isOpen() ).toBe( true );
86+
} );
87+
88+
it( 'leaves the overlay closed when the URL has no search param', async () => {
89+
setReadyState( 'complete' );
90+
renderOverlayShell();
91+
setUrl( '/' );
92+
93+
await loadBootstrap();
94+
95+
expect( isOpen() ).toBe( false );
96+
} );
97+
98+
it( 'waits for DOMContentLoaded when the document is still loading', async () => {
99+
setReadyState( 'loading' );
100+
renderOverlayShell();
101+
setUrl( '/?s=hello' );
102+
103+
await loadBootstrap();
104+
// Still parsing — the overlay must not open yet.
105+
expect( isOpen() ).toBe( false );
106+
107+
document.dispatchEvent( new Event( 'DOMContentLoaded' ) );
108+
await new Promise( resolve => setTimeout( resolve, 0 ) );
109+
110+
expect( isOpen() ).toBe( true );
111+
} );
112+
113+
it( 'is a no-op when the overlay shell is not rendered', async () => {
114+
setReadyState( 'complete' );
115+
document.body.innerHTML = '';
116+
setUrl( '/?s=hello' );
117+
118+
await expect( loadBootstrap() ).resolves.toBeUndefined();
119+
expect( document.getElementById( OVERLAY_ID ) ).toBeNull();
120+
} );
121+
} );

0 commit comments

Comments
 (0)