Skip to content

Commit

Permalink
(5P) SPT add JS Functional tests to the plugin (#35379)
Browse files Browse the repository at this point in the history
* Adds unit test framework via @wordpress/wp-scripts

* Adds tests for TemplateSelectorControl

* Adds and update tests

* Fix tests following rebase

* Refactor components and tests to pass following rebase

* Include Jest EsLint Plugin

We will enable this when we get lint-staged running. Configuring now.

* Adds static preview and event handler tests

* Removes redunant aria prop

* Adds tests for Dynamic Preview mode

* Refactor to DRY up test fixture data into helper file

* Update snapshot

* Move dev deps to correct location in package json

* Adds tests for TemplateSelectorPreview component

* Add tests and improve fixture data

* Updates to remove @wordpress/scripts dep and utilise npx for tests instead

This is required because of the Calypso monorepo relying on root dependencies. We don’t want to install @wordpress/scripts in Calypso root so npx is the best interim soluton. See #35379 (comment)

* Restore @wordpress/scripts to devDeps as npx doesn’t cover all dependencies and causes test runner errors

* Refactor to React Testing Library as Enzyme is not being prefered by Gutenberg Core

Rewrote tests using RTL and it is much nicer and avoids testing implementation details. I have much more confident in my tests.

* Rewrite Template Preview tests using RTL

* Update to local usage of queryByText to avoid unecessary ref to container

* Remove unecessary test

* Update to use custom Jest config to enable one line test setup imports

* Update to remove need to manually import test setup

* Include only necessary deps

@wordpress/jest-preset-default is required in order to extend the @wordpress/scripts jest config

* Resolve errors introduced due to rebase

* Fix broken tests by creating proxy for BlockPreview component

Exists as a pass through component to simplying testing components which consume `BlockPreview` from
`@wordpress/block-editor`. This is because jest cannot mock node modules that are not part of the root node modules. Due to the way this projects dependencies are defined
`@wordpress/block-editor` does not exist within `node_modules` and it is there impossible to mock it without providing a wrapping
component to act as a pass though. See https://jestjs.io/docs/en/manual-mocks

* Fix to ensure Blank mode is preserved

Previously adding conditionals in tests had removed the ability to provide a “blank” value in the Templates. Now add this as an explicit assertion across multiple tests to ensure it isn’t lost again.

* Reinstate missing default value

Whilst it is important to test for the presence of `blocks` it does not hurt to provide a default value as this ensures the “blank” state can be provided when in dynamic mode.
  • Loading branch information
getdave authored Sep 20, 2019
1 parent 1ddf352 commit 61d4c56
Show file tree
Hide file tree
Showing 15 changed files with 23,289 additions and 26 deletions.
2 changes: 2 additions & 0 deletions apps/full-site-editing/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
module.exports = {
plugins: [ 'jest' ],
extends: [ 'plugin:jest/recommended' ],
rules: {
'import/no-extraneous-dependencies': [ 'error', { packageDir: __dirname } ],
'react/react-in-jsx-scope': 0,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
* External dependencies
*/

/**
* Internal dependencies
*/

/**
* WordPress dependencies
*/
/* eslint-disable import/no-extraneous-dependencies */
import { BlockPreview } from '@wordpress/block-editor';
/* eslint-enable import/no-extraneous-dependencies */

// Exists as a pass through component to simplying testing
// components which consume `BlockPreview` from
// `@wordpress/block-editor`. This is because jest cannot mock
// node modules that are not part of the root node modules.
// Due to the way this projects dependencies are defined
// `@wordpress/block-editor` does not exist within `node_modules`
// and it is there impossible to mock it without providing a wrapping
// component to act as a pass though.
// See https://jestjs.io/docs/en/manual-mocks
export default function( props ) {
return <BlockPreview { ...props } />;
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@
/**
* WordPress dependencies
*/
/* eslint-disable import/no-extraneous-dependencies */
import { BlockPreview } from '@wordpress/block-editor';
/* eslint-enable import/no-extraneous-dependencies */

const BlockTemplatePreview = ( { blocks, viewportWidth } ) => {
const BlockTemplatePreview = ( { blocks = [], viewportWidth } ) => {
if ( ! blocks || ! blocks.length ) {
return null;
}
Expand All @@ -21,7 +23,7 @@ const BlockTemplatePreview = ( { blocks, viewportWidth } ) => {
<div className="edit-post-visual-editor">
<div className="editor-styles-wrapper">
<div className="editor-writing-flow">
{ blocks && <BlockPreview blocks={ blocks } viewportWidth={ viewportWidth } /> }
<BlockPreview blocks={ blocks } viewportWidth={ viewportWidth } />
</div>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { isEmpty, noop, map } from 'lodash';
import { isEmpty, isArray, noop, map } from 'lodash';
import classnames from 'classnames';

/**
Expand All @@ -17,19 +17,23 @@ import { memo } from '@wordpress/element';
import TemplateSelectorItem from './template-selector-item';
import replacePlaceholders from '../utils/replace-placeholders';

const TemplateSelectorControl = ( {
export const TemplateSelectorControl = ( {
label,
className,
help,
instanceId,
templates = {},
templates = [],
blocksByTemplates = {},
useDynamicPreview = false,
onTemplateSelect = noop,
onTemplateFocus = noop,
siteInformation = {},
} ) => {
if ( isEmpty( templates ) ) {
if ( isEmpty( templates ) || ! isArray( templates ) ) {
return null;
}

if ( true === useDynamicPreview && isEmpty( blocksByTemplates ) ) {
return null;
}

Expand All @@ -42,7 +46,10 @@ const TemplateSelectorControl = ( {
help={ help }
className={ classnames( className, 'template-selector-control' ) }
>
<ul className="template-selector-control__options">
<ul
className="template-selector-control__options"
data-testid="template-selector-control-options"
>
{ map( templates, ( { slug, title, preview, previewAlt } ) => (
<li key={ `${ id }-${ slug }` } className="template-selector-control__template">
<TemplateSelectorItem
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
/**
* External dependencies
*/

/**
* Internal dependencies
*/
/* eslint-disable import/no-extraneous-dependencies */
import { isNil, isEmpty } from 'lodash';
/* eslint-enable import/no-extraneous-dependencies */

/**
* WordPress dependencies
*/
import BlockPreview from './block-template-preview';
/* eslint-disable import/no-extraneous-dependencies */
import { Disabled } from '@wordpress/components';
/* eslint-enable import/no-extraneous-dependencies */

const TemplateSelectorItem = props => {
const {
id,
value,
help,
onFocus,
onSelect,
label,
Expand All @@ -26,6 +26,14 @@ const TemplateSelectorItem = props => {
blocks = [],
} = props;

if ( isNil( id ) || isNil( label ) || isNil( value ) ) {
return null;
}

if ( useDynamicPreview && ( isNil( blocks ) || isEmpty( blocks ) ) ) {
return null;
}

// Define static or dynamic preview.
const innerPreview = useDynamicPreview ? (
<Disabled>
Expand All @@ -39,18 +47,19 @@ const TemplateSelectorItem = props => {
/>
);

const labelId = `label-${ id }-${ value }`;

return (
<button
type="button"
id={ `${ id }-${ value }` }
className="template-selector-item__label"
value={ value }
onMouseEnter={ () => onFocus( value, label ) }
onClick={ () => onSelect( value, label ) }
aria-describedby={ help ? `${ id }__help` : undefined }
aria-labelledby={ `${ id } ${ labelId }` }
>
<div className="template-selector-item__preview-wrap">{ innerPreview }</div>
{ label }
<span id={ labelId }>{ label }</span>
</button>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,24 @@
* External dependencies
*/
import classnames from 'classnames';
import { isEmpty, debounce } from 'lodash';
/* eslint-disable import/no-extraneous-dependencies */
import { isEmpty, isArray, debounce } from 'lodash';
/* eslint-enable import/no-extraneous-dependencies */

/**
* WordPress dependencies
*/
/* eslint-disable import/no-extraneous-dependencies */
import { __ } from '@wordpress/i18n';
import { BlockPreview } from '@wordpress/block-editor';
import { Disabled } from '@wordpress/components';
import { useState, useEffect, useLayoutEffect, useRef, useReducer } from '@wordpress/element';
/* eslint-enable import/no-extraneous-dependencies */

/**
* Internal dependencies
*/
import PreviewTemplateTitle from './preview-template-title';
import BlockPreview from './block-preview';

const TemplateSelectorPreview = ( { blocks, viewportWidth, title } ) => {
const THRESHOLD_RESIZE = 300;
Expand All @@ -42,7 +46,9 @@ const TemplateSelectorPreview = ( { blocks, viewportWidth, title } ) => {
}

// Try to get the preview content element.
const previewContainerEl = ref.current.querySelector( '.block-editor-block-preview__content' );
const previewContainerEl = ref.current.querySelector(
'.block-editor-block-preview__content'
);
if ( ! previewContainerEl ) {
return;
}
Expand All @@ -63,7 +69,7 @@ const TemplateSelectorPreview = ( { blocks, viewportWidth, title } ) => {
}, [ blocks ] );

useEffect( () => {
if ( ! blocks.length ) {
if ( ! blocks || ! blocks.length ) {
return;
}

Expand All @@ -80,7 +86,7 @@ const TemplateSelectorPreview = ( { blocks, viewportWidth, title } ) => {
};
}, [ blocks ] );

if ( isEmpty( blocks ) ) {
if ( isEmpty( blocks ) || ! isArray( blocks ) ) {
return (
<div className={ previewElClasses }>
<div className="template-selector-preview__placeholder">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`TemplateSelectorControl Basic rendering renders with required props 1`] = `
<div>
<div
class="components-base-control template-selector-control"
>
<div
class="components-base-control__field"
>
<label
class="components-base-control__label"
for="template-selector-control-17"
>
Select a Template...
</label>
<ul
class="template-selector-control__options"
data-testid="template-selector-control-options"
>
<li
class="template-selector-control__template"
>
<button
aria-labelledby="template-selector-control-17 label-template-selector-control-17-blank"
class="template-selector-item__label"
type="button"
value="blank"
>
<div
class="template-selector-item__preview-wrap"
>
<img
alt=""
class="template-selector-item__media"
/>
</div>
<span
id="label-template-selector-control-17-blank"
>
Blank
</span>
</button>
</li>
<li
class="template-selector-control__template"
>
<button
aria-labelledby="template-selector-control-17 label-template-selector-control-17-template-1"
class="template-selector-item__label"
type="button"
value="template-1"
>
<div
class="template-selector-item__preview-wrap"
>
<img
alt="Testing alt"
class="template-selector-item__media"
src="https://via.placeholder.com/350x150"
/>
</div>
<span
id="label-template-selector-control-17-template-1"
>
Template 1
</span>
</button>
</li>
<li
class="template-selector-control__template"
>
<button
aria-labelledby="template-selector-control-17 label-template-selector-control-17-template-2"
class="template-selector-item__label"
type="button"
value="template-2"
>
<div
class="template-selector-item__preview-wrap"
>
<img
alt="Testing alt 2"
class="template-selector-item__media"
src="https://via.placeholder.com/300x250"
/>
</div>
<span
id="label-template-selector-control-17-template-2"
>
Template 2
</span>
</button>
</li>
<li
class="template-selector-control__template"
>
<button
aria-labelledby="template-selector-control-17 label-template-selector-control-17-template-3"
class="template-selector-item__label"
type="button"
value="template-3"
>
<div
class="template-selector-item__preview-wrap"
>
<img
alt="Testing alt 3"
class="template-selector-item__media"
src="https://via.placeholder.com/500x200"
/>
</div>
<span
id="label-template-selector-control-17-template-3"
>
Template 3
</span>
</button>
</li>
</ul>
</div>
</div>
</div>
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`TemplateSelectorPreview Basic rendering renders the preview when blocks are provided 1`] = `
<div>
<div
class="template-selector-preview editor-styles-wrapper"
>
<div
class="components-disabled"
>
<div
class="edit-post-visual-editor"
>
<div
class="editor-styles-wrapper"
style="visibility: hidden;"
>
<div
class="editor-writing-flow"
>
<div
class="editor-post-title"
style="transform: none;"
>
<div
class="editor-post-title__block"
>
<textarea
class="editor-post-title__input"
/>
</div>
</div>
<div
data-testid="block-template-preview"
>
MockedBlockPreview
</div>
</div>
</div>
</div>
</div>
</div>
</div>
`;
Loading

0 comments on commit 61d4c56

Please sign in to comment.