Skip to content

Commit

Permalink
Interactivity API: Add missing tests for body, init and on dire…
Browse files Browse the repository at this point in the history
…ctives (#52952)

* Add tests for wp-body

* Simplify wp-body directive

* Add tests for wp-init

* Add tests for `wp-on` directive

* Rename fakeshow to show-mock in init tests

* Remove unnecessary part of `wp-show-mock`

* Subscribe to context changes inside `initOne`

---------

Co-authored-by: Luis Herranz <luisherranz@gmail.com>
  • Loading branch information
DAreRodz and luisherranz committed Aug 9, 2023
1 parent fffaab7 commit a473122
Show file tree
Hide file tree
Showing 13 changed files with 439 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"apiVersion": 2,
"name": "test/directive-body",
"title": "E2E Interactivity tests - directive body",
"category": "text",
"icon": "heart",
"description": "",
"supports": {
"interactivity": true
},
"textdomain": "e2e-interactivity",
"viewScript": "directive-body-view",
"render": "file:./render.php"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php
/**
* HTML for testing the directive `data-wp-body`.
*
* @package gutenberg-test-interactive-blocks
*/

?>
<div
data-wp-interactive
data-wp-context='{"text":"text-1"}'
>
<div data-testid="container">
<aside data-wp-body data-testid="element with data-wp-body">
<p data-wp-text="context.text" data-testid="text">initial</p>
</aside>
</div>
<button
data-wp-on--click="actions.toggleText"
data-testid="toggle text"
>toggle text</button>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
( ( { wp } ) => {
const { store } = wp.interactivity;

store( {
actions: {
toggleText: ( { context } ) => {
context.text = context.text === 'text-1' ? 'text-2' : 'text-1';
},
},
} );
} )( window );
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"apiVersion": 2,
"name": "test/directive-init",
"title": "E2E Interactivity tests - directive init",
"category": "text",
"icon": "heart",
"description": "",
"supports": {
"interactivity": true
},
"textdomain": "e2e-interactivity",
"viewScript": "directive-init-view",
"render": "file:./render.php"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php
/**
* HTML for testing the directive `data-wp-init`.
*
* @package gutenberg-test-interactive-blocks
*/

?>
<div data-wp-interactive>
<div
data-testid="single init"
data-wp-context='{"isReady":[false],"calls":[0]}'
data-wp-init="actions.initOne"
>
<p data-wp-text="selector.isReady" data-testid="isReady">false</p>
<p data-wp-text="selector.calls" data-testid="calls">0</p>
<button data-wp-on--click="actions.reset">reset</button>
</div>
<div
data-testid="multiple inits"
data-wp-context='{"isReady":[false,false],"calls":[0,0]}'
data-wp-init--one="actions.initOne"
data-wp-init--two="actions.initTwo"
>
<p data-wp-text="selector.isReady" data-testid="isReady">false,false</p>
<p data-wp-text="selector.calls" data-testid="calls">0,0</p>
</div>
<div
data-testid="init show"
data-wp-context='{"isVisible":true,"isMounted":false}'
>
<div data-wp-show-mock="context.isVisible" data-testid="show">
<span data-wp-init="actions.initMount">Initially visible</span>
</div>
<button data-wp-on--click="actions.toggle" data-testid="toggle">
toggle
</button>
<p data-wp-text="selector.isMounted" data-testid="isMounted">
true
</p>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
( ( { wp } ) => {
const { store, directive, useContext } = wp.interactivity;

// Mock `data-wp-show` directive to test when things are removed from the
// DOM. Replace with `data-wp-show` when it's ready.
directive(
'show-mock',
( {
directives: {
'show-mock': { default: showMock },
},
element,
evaluate,
context,
} ) => {
const contextValue = useContext( context );
if ( ! evaluate( showMock, { context: contextValue } ) ) {
return null;
}
return element;
}
);


store( {
selector: {
isReady: ({ context: { isReady } }) => {
return isReady
.map(v => v ? 'true': 'false')
.join(',');
},
calls: ({ context: { calls } }) => {
return calls.join(',');
},
isMounted: ({ context }) => {
return context.isMounted ? 'true' : 'false';
},
},
actions: {
initOne: ( { context: { isReady, calls } } ) => {
isReady[0] = true;
// Subscribe to changes in that prop.
isReady[0] = isReady[0];
calls[0]++;
},
initTwo: ( { context: { isReady, calls } } ) => {
isReady[1] = true;
calls[1]++;
},
initMount: ( { context } ) => {
context.isMounted = true;
return () => {
context.isMounted = false;
}
},
reset: ( { context: { isReady } } ) => {
isReady.fill(false);
},
toggle: ( { context } ) => {
context.isVisible = ! context.isVisible;
},
},
} );
} )( window );
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"apiVersion": 2,
"name": "test/directive-on",
"title": "E2E Interactivity tests - directive on",
"category": "text",
"icon": "heart",
"description": "",
"supports": {
"interactivity": true
},
"textdomain": "e2e-interactivity",
"viewScript": "directive-on-view",
"render": "file:./render.php"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php
/**
* HTML for testing the directive `data-wp-on`.
*
* @package gutenberg-test-interactive-blocks
*/

?>
<div data-wp-interactive>
<div>
<p data-wp-text="state.counter" data-testid="counter">0</p>
<button
data-testid="button"
data-wp-on--click="actions.clickHandler"
>Click me!</button>
</div>
<div>
<p data-wp-text="state.text" data-testid="text">initial</p>
<input
type="text"
value="initial"
data-testid="input"
data-wp-on--input="actions.inputHandler"
>
</div>
<div data-wp-context='{"option":"undefined"}'>
<p data-wp-text="context.option" data-testid="option">0</p>
<select
name="pets"
value="undefined"
data-testid="select"
data-wp-on--change="actions.selectHandler"
>
<option value="undefined">Choose an option...</option>
<option value="dog">Dog</option>
<option value="cat">Cat</option>
</select>
</div>
<div
data-wp-on--customevent="actions.customEventHandler"
data-wp-context='{"customEvents":0}'
>
<p
data-wp-text="context.customEvents"
data-testid="custom events counter"
>0</p>
<button
data-testid="custom events button"
data-wp-on--click="actions.clickHandler"
>Click me!</button>
</div>
</div>
27 changes: 27 additions & 0 deletions packages/e2e-tests/plugins/interactive-blocks/directive-on/view.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
( ( { wp } ) => {
const { store } = wp.interactivity;

store( {
state: {
counter: 0,
text: ''
},
actions: {
clickHandler: ( { state, event } ) => {
state.counter += 1;
event.target.dispatchEvent(
new CustomEvent( 'customevent', { bubbles: true } )
);
},
inputHandler: ( { state, event } ) => {
state.text = event.target.value;
},
selectHandler: ( { context, event } ) => {
context.option = event.target.value;
},
customEventHandler: ({ context }) => {
context.customEvents += 1;
},
},
} );
} )( window );
9 changes: 2 additions & 7 deletions packages/interactivity/src/directives.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,8 @@ export default () => {
);

// data-wp-body
directive( 'body', ( { props: { children }, context: inherited } ) => {
const { Provider } = inherited;
const inheritedValue = useContext( inherited );
return createPortal(
<Provider value={ inheritedValue }>{ children }</Provider>,
document.body
);
directive( 'body', ( { props: { children } } ) => {
return createPortal( children, document.body );
} );

// data-wp-effect--[name]
Expand Down
76 changes: 76 additions & 0 deletions test/e2e/specs/interactivity/directive-init.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/**
* Internal dependencies
*/
import { test, expect } from './fixtures';

test.describe( 'data-wp-init', () => {
test.beforeAll( async ( { interactivityUtils: utils } ) => {
await utils.activatePlugins();
await utils.addPostWithBlock( 'test/directive-init' );
} );

test.beforeEach( async ( { interactivityUtils: utils, page } ) => {
await page.goto( utils.getLink( 'test/directive-init' ) );
} );

test.afterAll( async ( { interactivityUtils: utils } ) => {
await utils.deactivatePlugins();
await utils.deleteAllPosts();
} );

test( 'should run when the block renders', async ( { page } ) => {
const el = page.getByTestId( 'single init' );
await expect( el.getByTestId( 'isReady' ) ).toHaveText( 'true' );
await expect( el.getByTestId( 'calls' ) ).toHaveText( '1' );
} );

test( 'should not run again if accessed signals change', async ( {
page,
} ) => {
const el = page.getByTestId( 'single init' );
await expect( el.getByTestId( 'isReady' ) ).toHaveText( 'true' );
await el.getByRole( 'button' ).click();
await expect( el.getByTestId( 'isReady' ) ).toHaveText( 'false' );
await expect( el.getByTestId( 'calls' ) ).toHaveText( '1' );
} );

test( 'should run multiple inits if defined', async ( { page } ) => {
const el = page.getByTestId( 'multiple inits' );
await expect( el.getByTestId( 'isReady' ) ).toHaveText( 'true,true' );
await expect( el.getByTestId( 'calls' ) ).toHaveText( '1,1' );
} );

test( 'should run the init callback when the element is unmounted', async ( {
page,
} ) => {
const container = page.getByTestId( 'init show' );
const show = container.getByTestId( 'show' );
const toggle = container.getByTestId( 'toggle' );
const isMounted = container.getByTestId( 'isMounted' );

await expect( show ).toHaveText( 'Initially visible' );
await expect( isMounted ).toHaveText( 'true' );

await toggle.click();

await expect( show ).not.toBeVisible();
await expect( isMounted ).toHaveText( 'false' );
} );

test( 'should run init when the element is mounted', async ( { page } ) => {
const container = page.getByTestId( 'init show' );
const show = container.getByTestId( 'show' );
const toggle = container.getByTestId( 'toggle' );
const isMounted = container.getByTestId( 'isMounted' );

await toggle.click();

await expect( show ).not.toBeVisible();
await expect( isMounted ).toHaveText( 'false' );

await toggle.click();

await expect( show ).toHaveText( 'Initially visible' );
await expect( isMounted ).toHaveText( 'true' );
} );
} );
Loading

0 comments on commit a473122

Please sign in to comment.