-
+exports[`Search modal should open 1`] = `
+
+
+
+
+
+
+
+
+
+
+ Search
+
+
+ Please enter a search term with at least 3 characters.
+
-
-
- Please enter a search term with at least 3 characters.
-
-
-
-
-
-"
+
+
+
+
+`;
+
+exports[`Search modal should show search results 1`] = `
+
+`;
+
+exports[`Search should have a search button 1`] = `
+
`;
diff --git a/packages/js/tests/settings/search.test.js b/packages/js/tests/settings/search.test.js
index 58a030f8b9a..188a4b7ef67 100644
--- a/packages/js/tests/settings/search.test.js
+++ b/packages/js/tests/settings/search.test.js
@@ -1,47 +1,84 @@
import Search from "../../src/settings/components/search";
-import { shallow } from "enzyme";
+import "../__mocks__/intersection-observer";
+import "../__mocks__/navigator";
+import { fireEvent, render, screen, waitFor } from "../test-utils";
-jest.mock( "react-router-dom" );
+jest.mock( "@wordpress/data", () => ( {
+ useSelect: select => select( () => ( {
+ selectQueryableSearchIndex: () => ( {
+ test: {
+ fieldId: "id",
+ fieldLabel: "Item",
+ keywords: "test",
+ route: "/group",
+ routeLabel: "Group",
+ },
+ } ),
+ } ) ),
+} ) );
-describe( "Search test", () => {
- let wrapper;
+describe( "Search", () => {
beforeEach( () => {
- wrapper = shallow(
);
+ global.navigator.userAgent = "Mozilla/5.0 (Macintosh)";
+ render(
);
} );
- it( "Should have 'Quick Search' text on search button", () => {
- expect( wrapper.find( "button" ).first().text() ).toContain( "Quick search..." );
+ it( "should have a search button", () => {
+ const button = screen.getByRole( "button" );
+ expect( button ).toHaveTextContent( "Quick search..." );
+ expect( button ).toMatchSnapshot();
} );
- it( "should open Modal", () => {
- wrapper.find( "button" ).at( 0 ).simulate( "click" );
- expect( wrapper.find( "Modal" ).prop( "isOpen" ) ).toBe( true );
- } );
+ describe( "modal", () => {
+ beforeEach( async() => {
+ fireEvent.click( screen.getByRole( "button" ) );
+ await screen.findByRole( "dialog" );
+ } );
- it( "Input should have placeholder", () => {
- wrapper.find( "button" ).at( 0 ).simulate( "click" );
- expect( wrapper.find( "#input-search" ).prop( "placeholder" ) ).toContain( "Search..." );
- } );
+ it( "should open", () => {
+ const modal = screen.getByRole( "dialog" );
+ expect( modal ).toBeTruthy();
+ expect( modal ).toMatchSnapshot();
+ } );
- it( "Should not search under 3 characters", () => {
- wrapper.find( "button" ).at( 0 ).simulate( "click" );
- wrapper.find( "#input-search" ).at( 0 ).simulate( "change", { target: { value: "se" } } );
- expect( wrapper.find( "SearchNoResultsContent" ).find( "p" ).text() ).toContain( "Please enter a search term with at least 3 characters." );
- } );
+ it( "should contain a combobox", () => {
+ const input = screen.getByRole( "combobox" );
+ expect( input.placeholder ).toBe( "Search..." );
+ expect( input ).toHaveFocus();
+ } );
- it( "should match button text to input value", () => {
- wrapper.find( "button" ).at( 0 ).simulate( "click" );
- wrapper.find( "#input-search" ).at( 0 ).simulate( "change", { target: { value: "seo title" } } );
- expect( wrapper.find( "button" ).first().text() ).toContain( "seo title" );
- } );
+ describe( "close button", () => {
+ it( "should be present", () => {
+ expect( screen.getByRole( "button", { name: "Close" } ) ).toBeTruthy();
+ } );
- it( "Results not found", () => {
- wrapper.find( "button" ).at( 0 ).simulate( "click" );
- wrapper.find( "#input-search" ).at( 0 ).simulate( "change", { target: { value: "random" } } );
- expect( wrapper.find( "SearchNoResultsContent" ).find( "p" ).text() ).toContain( "We couldn’t find anything with that term." );
- } );
+ it( "should close on click", async() => {
+ expect( screen.getByRole( "dialog" ) ).toBeTruthy();
+ fireEvent.click( screen.getByRole( "button", { name: "Close" } ) );
+ expect( screen.queryByRole( "dialog" ) ).toBe( null );
+ } );
+ } );
+
+ it( "should contain title and description", () => {
+ expect( screen.getByText( "Search" ) ).toBeTruthy();
+ expect( screen.getByText( "Please enter a search term with at least 3 characters." ) ).toBeTruthy();
+ } );
+
+ it( "should show search results", async() => {
+ fireEvent.change( screen.getByRole( "combobox" ), { target: { value: "test" } } );
+ await waitFor( () => {
+ const items = screen.getAllByRole( "presentation" );
+ expect( items.length ).toBe( 2 );
+ expect( items[ 0 ] ).toHaveTextContent( "Group" );
+ expect( items[ 1 ] ).toHaveTextContent( "Item" );
+ expect( screen.getByRole( "listbox" ) ).toMatchSnapshot();
+ }, { timeout: 1000 } );
+ } );
- it( "should match search snapshot", () => {
- expect( wrapper.debug() ).toMatchSnapshot();
+ it( "should show no results found", async() => {
+ fireEvent.change( screen.getByRole( "combobox" ), { target: { value: "somethingthatisnotfound" } } );
+ expect( screen.getByText( "No results found" ) ).toBeTruthy();
+ expect( screen.getByText( "We couldn’t find anything with that term." ) ).toBeTruthy();
+ } );
} );
} );
diff --git a/packages/js/tests/setupTests.js b/packages/js/tests/setupTests.js
index da72a5749df..7192d03a116 100644
--- a/packages/js/tests/setupTests.js
+++ b/packages/js/tests/setupTests.js
@@ -1,12 +1,9 @@
-import "raf/polyfill";
+import "@testing-library/jest-dom";
+import { createElement } from "@wordpress/element";
+import { setLocaleData } from "@wordpress/i18n";
import "jest-styled-components";
+import "raf/polyfill";
import React from "react";
-import Enzyme from "enzyme";
-import EnzymeAdapter from "enzyme-adapter-react-16";
-import { setLocaleData } from "@wordpress/i18n";
-import { createElement } from "@wordpress/element";
-
-Enzyme.configure( { adapter: new EnzymeAdapter() } );
setLocaleData( {
"": {
diff --git a/packages/js/tests/test-utils.js b/packages/js/tests/test-utils.js
new file mode 100644
index 00000000000..9c7f86fb46f
--- /dev/null
+++ b/packages/js/tests/test-utils.js
@@ -0,0 +1 @@
+export * from "@testing-library/react";
diff --git a/packages/replacement-variable-editor/.eslintrc.js b/packages/replacement-variable-editor/.eslintrc.js
new file mode 100644
index 00000000000..32fd510f329
--- /dev/null
+++ b/packages/replacement-variable-editor/.eslintrc.js
@@ -0,0 +1,51 @@
+module.exports = {
+ root: true,
+ "extends": [
+ "yoast",
+ ],
+ settings: {
+ react: {
+ version: "detect",
+ },
+ },
+ parserOptions: {
+ ecmaVersion: 2020,
+ sourceType: "module",
+ },
+ ignorePatterns: [
+ "/build/",
+ "/coverage/",
+ "/dist/",
+ ],
+ rules: {
+ "no-prototype-builtins": 0,
+ "comma-dangle": [
+ "error",
+ {
+ arrays: "always-multiline",
+ objects: "always-multiline",
+ imports: "always-multiline",
+ exports: "always-multiline",
+ functions: "never",
+ },
+ ],
+ },
+ overrides: [
+ {
+ files: [ "tests/**/*.js" ],
+ env: {
+ jest: true,
+ },
+ rules: {
+ "no-restricted-imports": 0,
+ },
+ },
+ {
+ files: [ "**/*.js" ],
+ rules: {
+ "react/jsx-no-bind": 1,
+ "react/require-default-props": 1,
+ },
+ },
+ ],
+};
diff --git a/packages/replacement-variable-editor/package.json b/packages/replacement-variable-editor/package.json
index 8422499086e..5531911471b 100644
--- a/packages/replacement-variable-editor/package.json
+++ b/packages/replacement-variable-editor/package.json
@@ -18,9 +18,6 @@
"jest": {
"testURL": "http://localhost",
"testRegex": ".*Test.js$",
- "snapshotSerializers": [
- "enzyme-to-json/serializer"
- ],
"transform": {
"^.+\\.jsx?$": "babel-jest"
},
@@ -38,7 +35,7 @@
"dependencies": {
"@draft-js-plugins/editor": "^4.1.0",
"@wordpress/a11y": "^1.1.3",
- "@wordpress/components": "^13.0.3",
+ "@wordpress/components": "^20.0.0",
"@wordpress/hooks": "^2.12.3",
"@wordpress/i18n": "^1.2.3",
"@yoast/components": "^2.19.0",
@@ -48,17 +45,24 @@
"draft-js-single-line-plugin": "^2.0.5",
"lodash": "^4.17.11",
"prop-types": "^15.7.2",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
"styled-components": "^5.3.6"
},
"devDependencies": {
- "enzyme": "^3.11.0",
- "enzyme-adapter-react-16": "^1.15.6",
- "jest-styled-components": "^7.0.3"
+ "@testing-library/jest-dom": "^6.1.3",
+ "@testing-library/react": "^14.0.0",
+ "@testing-library/react-hooks": "^8.0.1",
+ "eslint": "^7.32.0",
+ "eslint-config-yoast": "^6.0.0",
+ "eslint-plugin-import": "^2.27.5",
+ "eslint-plugin-jsx-a11y": "^6.5.1",
+ "eslint-plugin-react": "^7.29.4",
+ "jest-styled-components": "^7.0.3",
+ "react-test-renderer": "^18.2.0"
},
"peerDependencies": {
"@draft-js-plugins/mention": "^5.0.0",
- "draft-js": "^0.11.7",
- "react": "^16.14.0",
- "react-dom": "^16.14.0"
+ "draft-js": "^0.11.7"
}
}
diff --git a/packages/replacement-variable-editor/src/ReplacementVariableEditorStandalone.js b/packages/replacement-variable-editor/src/ReplacementVariableEditorStandalone.js
index 9d5fff2dbef..a53d30f6386 100644
--- a/packages/replacement-variable-editor/src/ReplacementVariableEditorStandalone.js
+++ b/packages/replacement-variable-editor/src/ReplacementVariableEditorStandalone.js
@@ -1,3 +1,4 @@
+/* eslint-disable camelcase */
// External dependencies.
import React from "react";
import Editor from "@draft-js-plugins/editor";
@@ -511,30 +512,33 @@ class ReplacementVariableEditorStandalone extends React.Component {
/**
* Sets the state of this editor when the incoming content changes.
*
- * @param {Object} nextProps The props this component receives.
+ * @param {Object} prevProps The previous props this component has received.
+ * @param {Object} prevState The previous state this component has been in.
*
* @returns {void}
*/
- componentWillReceiveProps( nextProps ) {
- const { content, replacementVariables, recommendedReplacementVariables } = this.props;
+ componentDidUpdate( prevProps, prevState ) {
+ const { content, replacementVariables, recommendedReplacementVariables } = prevProps;
const { searchValue } = this.state;
const nextState = {};
+ const nextProps = this.props;
+ const isContentChanged = nextProps.content !== this._serializedContent && nextProps.content !== content;
+ const isReplacementVariablesChanged = nextProps.replacementVariables !== replacementVariables;
+ const newReplacementVariableNames = nextProps.replacementVariables.map( rv => rv.name )
+ .filter( rvName => ! replacementVariables.map( rv => rv.name ).includes( rvName ) );
+ const isNewReplacementVariableNames = newReplacementVariableNames.some( rvName => content.includes( "%%" + rvName + "%%" ) );
+
+ if ( isContentChanged ) {
+ this._serializedContent = nextProps.content;
+ nextState.editorState = unserializeEditor( nextProps.content, nextProps.replacementVariables );
+ }
- if ( nextProps.content !== this._serializedContent && nextProps.content !== content ) {
+ if ( ! isContentChanged && isReplacementVariablesChanged && isNewReplacementVariableNames ) {
this._serializedContent = nextProps.content;
nextState.editorState = unserializeEditor( nextProps.content, nextProps.replacementVariables );
- } else if ( nextProps.replacementVariables !== replacementVariables ) {
- const newReplacementVariableNames = nextProps.replacementVariables
- .map( rv => rv.name )
- .filter( rvName => ! replacementVariables.map( rv => rv.name ).includes( rvName ) );
-
- if ( newReplacementVariableNames.some( rvName => content.includes( "%%" + rvName + "%%" ) ) ) {
- this._serializedContent = nextProps.content;
- nextState.editorState = unserializeEditor( nextProps.content, nextProps.replacementVariables );
- }
}
- if ( nextProps.replacementVariables !== replacementVariables ) {
+ if ( isReplacementVariablesChanged ) {
const currentReplacementVariables = this.determineCurrentReplacementVariables(
nextProps.replacementVariables,
recommendedReplacementVariables,
@@ -545,8 +549,9 @@ class ReplacementVariableEditorStandalone extends React.Component {
this.mapReplacementVariablesToSuggestions( currentReplacementVariables )
);
}
-
- this.setState( nextState );
+ if ( isReplacementVariablesChanged || isContentChanged ) {
+ this.setState( { ...prevState, ...nextState } );
+ }
}
/**
diff --git a/packages/replacement-variable-editor/tests/ReplacementVariableEditorTest.js b/packages/replacement-variable-editor/tests/ReplacementVariableEditorTest.js
index 3bb8a5c33bd..c6cd4e657ad 100644
--- a/packages/replacement-variable-editor/tests/ReplacementVariableEditorTest.js
+++ b/packages/replacement-variable-editor/tests/ReplacementVariableEditorTest.js
@@ -1,8 +1,7 @@
-/* eslint-disable react/jsx-no-bind */
-import { shallow } from "enzyme";
+import React from "react";
+import { render } from "./test-utils";
import ReplacementVariableEditorStandalone, { ReplacementVariableEditorStandaloneInnerComponent }
from "../src/ReplacementVariableEditorStandalone";
-import React from "react";
jest.mock( "draft-js/lib/generateRandomKey", () => () => {
let randomKey = global._testDraftJSRandomNumber;
@@ -17,19 +16,21 @@ jest.mock( "draft-js/lib/generateRandomKey", () => () => {
return randomKey + "";
} );
-describe( "ReplacementVariableEditor", () => {
+describe( "ReplacementVariableEditorStandalone", () => {
it( "wraps a Draft.js editor instance", () => {
- const editor = shallow(
+ const { container } = render(
{} }
ariaLabelledBy="id"
+ fieldId="test-field-id"
theme={ { isRtl: "false" } }
/>
);
- expect( editor ).toMatchSnapshot();
+ expect( container ).toMatchSnapshot();
} );
} );
@@ -68,11 +69,11 @@ describe( "suggestionsFilter", () => {
ariaLabelledBy: "id",
theme: { isRtl: false },
};
-
+ suggestions = [
+ { name: "cat", value: "meow" },
+ ];
replacementVariablesEditor = new ReplacementVariableEditorStandaloneInnerComponent( props );
-
suggestions = replacementVariablesEditor.mapReplacementVariablesToSuggestions( props.replacementVariables );
-
expected = [
{
replaceName: "category",
diff --git a/packages/replacement-variable-editor/tests/__snapshots__/ReplacementVariableEditorTest.js.snap b/packages/replacement-variable-editor/tests/__snapshots__/ReplacementVariableEditorTest.js.snap
index 793f10bab25..c6d2e7dded9 100644
--- a/packages/replacement-variable-editor/tests/__snapshots__/ReplacementVariableEditorTest.js.snap
+++ b/packages/replacement-variable-editor/tests/__snapshots__/ReplacementVariableEditorTest.js.snap
@@ -1,21 +1,63 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`ReplacementVariableEditor wraps a Draft.js editor instance 1`] = `
-
+exports[`ReplacementVariableEditorStandalone wraps a Draft.js editor instance 1`] = `
+.c0 div {
+ z-index: 10995;
+}
+
+.c0 > div {
+ max-height: 450px;
+ overflow-y: auto;
+}
+
+
+
+
+
+
+
+
+
+
+ Dummy content
+
+
+
+
+
+
+
+
+
+
`;
diff --git a/packages/replacement-variable-editor/tests/setupTests.js b/packages/replacement-variable-editor/tests/setupTests.js
index 5cd2e56ea46..d6301c14fff 100644
--- a/packages/replacement-variable-editor/tests/setupTests.js
+++ b/packages/replacement-variable-editor/tests/setupTests.js
@@ -1,5 +1,2 @@
import "jest-styled-components";
-import Enzyme from "enzyme";
-import EnzymeAdapter from "enzyme-adapter-react-16";
-
-Enzyme.configure( { adapter: new EnzymeAdapter() } );
+import "@testing-library/jest-dom";
diff --git a/packages/replacement-variable-editor/tests/test-utils.js b/packages/replacement-variable-editor/tests/test-utils.js
new file mode 100644
index 00000000000..9c7f86fb46f
--- /dev/null
+++ b/packages/replacement-variable-editor/tests/test-utils.js
@@ -0,0 +1 @@
+export * from "@testing-library/react";
diff --git a/packages/search-metadata-previews/.eslintrc.js b/packages/search-metadata-previews/.eslintrc.js
new file mode 100644
index 00000000000..bef58582e45
--- /dev/null
+++ b/packages/search-metadata-previews/.eslintrc.js
@@ -0,0 +1,56 @@
+module.exports = {
+ root: true,
+ "extends": [
+ "yoast",
+ ],
+ settings: {
+ react: {
+ version: "detect",
+ },
+ },
+ parserOptions: {
+ ecmaVersion: 2020,
+ sourceType: "module",
+ },
+ ignorePatterns: [
+ "/build/",
+ "/coverage/",
+ "/dist/",
+ ],
+ rules: {
+ "no-prototype-builtins": 0,
+ "comma-dangle": [
+ "error",
+ {
+ arrays: "always-multiline",
+ objects: "always-multiline",
+ imports: "always-multiline",
+ exports: "always-multiline",
+ functions: "never",
+ },
+ ],
+ },
+ overrides: [
+ {
+ files: [ "tests/**/*.js" ],
+ env: {
+ jest: true,
+ },
+ rules: {
+ "no-restricted-imports": 0,
+ },
+ },
+ {
+ files: [ "**/*.js" ],
+ rules: {
+ // A wrapping label is not necessary when there already is an htmlFor attribute.
+ "react/default-props-match-prop-types": 1,
+ "react/no-unused-prop-types": 1,
+ "react/no-access-state-in-setstate": 1,
+ "react/no-unused-state": 1,
+ "react/jsx-no-bind": 1,
+ "react/require-default-props": 1,
+ },
+ },
+ ],
+};
diff --git a/packages/search-metadata-previews/package.json b/packages/search-metadata-previews/package.json
index 16952cb849f..982074f67a0 100644
--- a/packages/search-metadata-previews/package.json
+++ b/packages/search-metadata-previews/package.json
@@ -25,28 +25,30 @@
"interpolate-components": "^1.1.1",
"lodash": "^4.17.11",
"prop-types": "^15.6.0",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
"react-transition-group": "^2.7.1",
"styled-components": "^5.3.6",
"yoastseo": "^1.91.2"
},
"devDependencies": {
+ "@testing-library/jest-dom": "^6.1.3",
+ "@testing-library/react": "^14.0.0",
+ "@testing-library/react-hooks": "^8.0.1",
"@yoast/browserslist-config": "^1.2.2",
+ "eslint": "^7.32.0",
+ "eslint-config-yoast": "^6.0.0",
+ "eslint-plugin-import": "^2.27.5",
+ "eslint-plugin-jsx-a11y": "^6.5.1",
+ "eslint-plugin-react": "^7.29.4",
"browserslist": "^4.7.3",
- "enzyme": "^3.11.0",
- "enzyme-adapter-react-16": "^1.15.6",
- "jest-styled-components": "^7.0.3",
- "react-test-renderer": "^16.14.0"
- },
- "peerDependencies": {
- "react": "^16.14.0",
- "react-dom": "^16.14.0"
+ "jest-styled-components": "^7.0.3"
},
+ "peerDependencies": {},
"jest": {
+ "testEnvironment": "jest-environment-jsdom",
"testURL": "http://localhost",
"testRegex": ".*Test.js$",
- "snapshotSerializers": [
- "enzyme-to-json/serializer"
- ],
"transform": {
"^.+\\.jsx?$": "babel-jest"
},
diff --git a/packages/search-metadata-previews/src/snippet-editor/SnippetEditor.js b/packages/search-metadata-previews/src/snippet-editor/SnippetEditor.js
index 56bbc90eab7..003264a5448 100644
--- a/packages/search-metadata-previews/src/snippet-editor/SnippetEditor.js
+++ b/packages/search-metadata-previews/src/snippet-editor/SnippetEditor.js
@@ -1,3 +1,4 @@
+/* eslint-disable camelcase */
// External dependencies.
import styled from "styled-components";
import React from "react";
@@ -165,30 +166,30 @@ class SnippetEditor extends React.Component {
/**
* Updates the state when the component receives new props.
*
- * @param {Object} nextProps The new props.
+ * @param {Object} prevProps The previous props.
* @returns {void}
*/
- componentWillReceiveProps( nextProps ) {
+ componentDidUpdate( prevProps ) {
// Only set a new state when the data is dirty.
- if ( this.shallowCompareData( this.props, nextProps ) ) {
- const data = this.mapDataToMeasurements( nextProps.data, nextProps.replacementVariables );
+ if ( this.shallowCompareData( this.props, prevProps ) ) {
+ const data = this.mapDataToMeasurements( this.props.data, this.props.replacementVariables );
this.setState(
{
// Here we use the filtered SEO title for the SEO title progress calculation.
titleLengthProgress: getTitleProgress( data.filteredSEOTitle ),
descriptionLengthProgress: getDescriptionProgress(
data.description,
- nextProps.date,
- nextProps.isCornerstone,
- nextProps.isTaxonomy,
- nextProps.locale ),
+ this.props.date,
+ this.props.isCornerstone,
+ this.props.isTaxonomy,
+ this.props.locale ),
}
);
/*
- * Make sure that any changes get reflected on the analysis data on the store (used in, among other things, the SEO analysis).
- * Including changes to the replacement vars (e.g. title, category, tags).
- */
+ * Make sure that any changes get reflected on the analysis data on the store (used in, among other things, the SEO analysis).
+ * Including changes to the replacement vars (e.g. title, category, tags).
+ */
this.props.onChangeAnalysisData( data );
}
}
diff --git a/packages/search-metadata-previews/src/snippet-preview/SnippetPreview.js b/packages/search-metadata-previews/src/snippet-preview/SnippetPreview.js
index 5ff0fe77da8..24368cb26c4 100644
--- a/packages/search-metadata-previews/src/snippet-preview/SnippetPreview.js
+++ b/packages/search-metadata-previews/src/snippet-preview/SnippetPreview.js
@@ -1,3 +1,4 @@
+/* eslint-disable camelcase */
// External dependencies.
import React, { PureComponent } from "react";
import styled from "styled-components";
@@ -692,35 +693,28 @@ export default class SnippetPreview extends PureComponent {
/* eslint-enable jsx-a11y/mouse-events-have-key-events */
}
+
/**
- * Before we receive props we need to set the title and description in the
- * state.
+ * After a component updates we need to fit the title.
+ * Before we receive props we need to set the title and description in the state.
*
- * @param {Object} nextProps The props this component will receive.
+ * @param {Object} prevProps The previous props this component has received.
*
* @returns {void}
*/
- componentWillReceiveProps( nextProps ) {
+ componentDidUpdate( prevProps ) {
const nextState = {};
- if ( this.props.title !== nextProps.title ) {
- nextState.title = nextProps.title;
+ if ( this.props.title !== prevProps.title ) {
+ nextState.title = this.props.title;
}
- if ( this.props.description !== nextProps.description ) {
- nextState.description = nextProps.description;
+ if ( this.props.description !== prevProps.description ) {
+ nextState.description = this.props.description;
}
- this.setState( nextState );
- }
-
- /**
- * After a component updates we need to fit the title.
- *
- * @returns {void}
- */
- componentDidUpdate() {
this.setState( {
+ ...nextState,
isDescriptionPlaceholder: ( ! this.props.description ),
} );
diff --git a/packages/search-metadata-previews/tests/HelpTextWrapperTest.js b/packages/search-metadata-previews/tests/HelpTextWrapperTest.js
index 8a74cbb823e..c4b331c2161 100644
--- a/packages/search-metadata-previews/tests/HelpTextWrapperTest.js
+++ b/packages/search-metadata-previews/tests/HelpTextWrapperTest.js
@@ -1,33 +1,21 @@
/* External dependencies */
import React from "react";
-import renderer from "react-test-renderer";
-import EnzymeAdapter from "enzyme-adapter-react-16";
-import Enzyme from "enzyme/build/index";
+import { fireEvent, render, screen } from "./test-utils";
/* Internal dependencies */
import HelpTextWrapper from "../src/snippet-preview/HelpTextWrapper";
-Enzyme.configure( { adapter: new EnzymeAdapter() } );
describe( "HelpTextWrapper", () => {
it( "matches the snapshot by default", () => {
- const component = renderer.create(
-
- );
-
- const tree = component.toJSON();
- expect( tree ).toMatchSnapshot();
+ const { container } = render( );
+ expect( container ).toMatchSnapshot();
} );
- it( "matches the snapshot when the help text button is focused", () => {
- const wrapper = Enzyme.mount(
-
- );
- wrapper.find( "button" ).simulate( "click", {
- state: {
- isExpanded: false,
- },
- } );
- expect( wrapper.state().isExpanded ).toEqual( true );
+ it( "matches the snapshot when the help text button is focused", async() => {
+ const { container } = render( );
+
+ fireEvent.click( screen.getByLabelText( "Open help" ) );
+ expect( container ).toMatchSnapshot();
} );
} );
diff --git a/packages/search-metadata-previews/tests/SnippetEditorTest.js b/packages/search-metadata-previews/tests/SnippetEditorTest.js
index 9be72144a8e..a39a9632b3c 100644
--- a/packages/search-metadata-previews/tests/SnippetEditorTest.js
+++ b/packages/search-metadata-previews/tests/SnippetEditorTest.js
@@ -1,8 +1,6 @@
-import SnippetEditor from "../src/snippet-editor/SnippetEditor";
import React from "react";
-import { mount } from "enzyme";
-// eslint-disable-next-line import/named -- this concerns a mock
-import { focus } from "@yoast/replacement-variable-editor";
+import SnippetEditor from "../src/snippet-editor/SnippetEditor";
+import { fireEvent, render, screen } from "./test-utils";
const defaultData = {
title: "Test title",
@@ -12,267 +10,56 @@ const defaultData = {
const defaultArgs = {
baseUrl: "http://example.org/",
+ siteName: "Test site name",
data: defaultData,
- onChange: () => {},
-};
-
-/**
- * Mounts the snippet editor component with changed arguments.
- *
- * @param {Object} changedArgs The changed arguments.
- *
- * @returns {ReactElement} The SnippetEditor component.
- */
-const mountWithArgs = ( changedArgs ) => {
- const args = { ...defaultArgs, ...changedArgs };
- return mount( );
+ isOpen: true,
+ onChange: jest.fn(),
};
describe( "SnippetEditor", () => {
- it( "closes when calling close()", () => {
- focus.mockClear();
- const editor = mountWithArgs( {} );
-
- editor.instance().open();
- editor.update();
-
- editor.instance().setFieldFocus( "title" );
- expect( focus ).toHaveBeenCalledTimes( 1 );
+ it( "Mobile mode", async() => {
+ const { container } = render( );
+ const desktopRadioInput = screen.getByLabelText( "Desktop result" );
+ const mobileRadioInput = screen.getByLabelText( "Mobile result" );
+ expect( desktopRadioInput ).not.toBeChecked();
+ expect( mobileRadioInput ).toBeChecked();
+ expect( container ).toMatchSnapshot();
} );
-
- it( "highlights the active ReplacementVariableEditor when calling setFieldFocus", () => {
- focus.mockClear();
-
- const editor = mountWithArgs( {} );
-
- editor.instance().open();
- editor.instance().setFieldFocus( "title" );
- editor.instance().setFieldFocus( "description" );
- editor.update();
-
- expect( focus ).toHaveBeenCalledTimes( 2 );
+ it( "Desktop mode and should switch to mobile", async() => {
+ const { container } = render( );
+ const desktopRadioInput = screen.getByLabelText( "Desktop result" );
+ const mobileRadioInput = screen.getByLabelText( "Mobile result" );
+ expect( desktopRadioInput ).toBeChecked();
+ expect( mobileRadioInput ).not.toBeChecked();
+ expect( container ).toMatchSnapshot();
+
+ fireEvent.click( mobileRadioInput );
+ expect( defaultArgs.onChange ).toHaveBeenCalledWith( "mode", "mobile" );
} );
- it( "switches modes when changing mode switcher input", () => {
- const onChange = jest.fn();
- const editor = mountWithArgs( { onChange } );
-
- // Click the mobile button.
- editor.find( "ModeSwitcher__Switcher" ).find( "input" ).at( 0 ).simulate( "change" );
-
- expect( onChange ).toBeCalledWith( "mode", "mobile" );
-
- // Click the desktop button.
- editor.find( "ModeSwitcher__Switcher" ).find( "input" ).at( 1 ).simulate( "change" );
-
- expect( onChange ).toBeCalledWith( "mode", "desktop" );
+ it( "Without close snippet editor button", async() => {
+ render( );
+ expect( screen.queryByText( "Edit snippet" ) ).not.toBeInTheDocument();
} );
- describe( "shallowCompareData", () => {
- it( "returns false when there is no new data", () => {
- const editor = mountWithArgs( {} );
-
- const data = {
- data: {
- title: "old title",
- description: "old description",
- slug: "old slug",
- },
- replacementVariables: [
- {
- name: "test1",
- label: "Test1",
- value: "first",
- description: "First",
- },
- {
- name: "test2",
- label: "Test2",
- value: "second",
- description: "Second",
- },
- ],
- };
-
- const isDirty = editor.instance().shallowCompareData( data, data );
-
- expect( isDirty ).toBe( false );
- } );
-
- it( "returns true when one data point has changed", () => {
- const editor = mountWithArgs( {} );
-
- const prev = {
- data: {
- title: "old title",
- description: "old description",
- slug: "old slug",
- },
- replacementVariables: [
- {
- name: "test1",
- label: "Test1",
- value: "first",
- description: "First",
- },
- {
- name: "test2",
- label: "Test2",
- value: "second",
- description: "Second",
- },
- ],
- };
- const next = {
- data: {
- title: "new title",
- description: "old description",
- slug: "old slug",
- },
- replacementVariables: [
- {
- name: "test1",
- label: "Test1",
- value: "first",
- description: "First",
- },
- {
- name: "test2",
- label: "Test2",
- value: "second",
- description: "Second",
- },
- ],
- };
-
- const isDirty = editor.instance().shallowCompareData( prev, next );
-
- expect( isDirty ).toBe( true );
- } );
-
- it( "returns true when one replacement variable has changed", () => {
- const editor = mountWithArgs( {} );
-
- const prev = {
- data: {
- title: "old title",
- description: "old description",
- slug: "old slug",
- },
- replacementVariables: [
- {
- name: "test1",
- label: "Test1",
- value: "first",
- description: "First",
- },
- {
- name: "test2",
- label: "Test2",
- value: "second",
- description: "Second",
- },
- ],
- };
- const next = {
- data: {
- title: "new title",
- description: "old description",
- slug: "old slug",
- },
- replacementVariables: [
- {
- name: "test1",
- label: "Test1",
- value: "first to change",
- description: "First",
- },
- {
- name: "test2",
- label: "Test2",
- value: "second",
- description: "Second",
- },
- ],
- };
-
- const isDirty = editor.instance().shallowCompareData( prev, next );
-
- expect( isDirty ).toBe( true );
- } );
-
- it( "returns true when multiple data points have changed", () => {
- const editor = mountWithArgs( {} );
-
- const prev = {
- data: {
- title: "old title",
- description: "old description",
- slug: "old slug",
- },
- replacementVariables: [
- {
- name: "test1",
- label: "Test1",
- value: "first",
- description: "First",
- },
- {
- name: "test2",
- label: "Test2",
- value: "second",
- description: "Second",
- },
- ],
- };
- const next = {
- data: {
- title: "new title",
- description: "new description",
- slug: "old slug",
- },
- replacementVariables: [
- {
- name: "test1",
- label: "Test1",
- value: "first",
- description: "First",
- },
- {
- name: "test2",
- label: "Test2",
- value: "second but now third",
- description: "Second",
- },
- ],
- };
-
- const isDirty = editor.instance().shallowCompareData( prev, next );
-
- expect( isDirty ).toBe( true );
- } );
- } );
- describe( "mapDataToMeasurements", () => {
- let editor, data;
+ describe( "Snippet editor defaults", () => {
beforeEach( () => {
- editor = mountWithArgs( {} );
- data = {
- title: "Tortoiseshell cats %%sep%% %%sitename%%",
- description: " The cool tortie everyone loves! ",
- slug: "tortie-cats",
- };
+ render( );
} );
- it( "returns the filtered SEO title without separator and site title", () => {
- expect( editor.instance().mapDataToMeasurements( data ).filteredSEOTitle ).toBe( "Tortoiseshell cats " );
- editor.unmount();
+ it( "Close snippet editor with button", async() => {
+ const openSnippetEditorButton = screen.getByText( "Edit snippet" );
+ expect( openSnippetEditorButton ).toBeInTheDocument();
+ fireEvent.click( openSnippetEditorButton );
+ const closeSnippetEditorButton = screen.getByText( "Close snippet editor" );
+ expect( closeSnippetEditorButton ).toBeInTheDocument();
+ fireEvent.click( closeSnippetEditorButton );
+ expect( closeSnippetEditorButton ).not.toBeInTheDocument();
} );
- it( "returns the correct url: baseURL + slug", () => {
- expect( editor.instance().mapDataToMeasurements( data ).url ).toBe( "http://example.org/tortie-cats" );
- editor.unmount();
- } );
- it( "returns the description with multiple spaces stripped", () => {
- expect( editor.instance().mapDataToMeasurements( data ).description ).toBe( "The cool tortie everyone loves!" );
- editor.unmount();
+
+ it( "should switch to desktop mode", () => {
+ const desktopRadioInput = screen.getByLabelText( "Desktop result" );
+ fireEvent.click( desktopRadioInput );
+ expect( defaultArgs.onChange ).toHaveBeenCalledWith( "mode", "desktop" );
} );
} );
} );
diff --git a/packages/search-metadata-previews/tests/SnippetPreviewTest.js b/packages/search-metadata-previews/tests/SnippetPreviewTest.js
index 1f0910e608c..b901f14fa76 100644
--- a/packages/search-metadata-previews/tests/SnippetPreviewTest.js
+++ b/packages/search-metadata-previews/tests/SnippetPreviewTest.js
@@ -1,80 +1,89 @@
-import { mount } from "enzyme";
import React from "react";
import { MODE_DESKTOP, MODE_MOBILE } from "../src/snippet-preview/constants";
import SnippetPreview from "../src/snippet-preview/SnippetPreview";
+import { render, screen } from "./test-utils";
-const defaultArgs = {
+const baseArgs = {
description: "Description",
+ siteName: "Test site name",
title: "Title",
- url: "https://example.org",
- mode: MODE_DESKTOP,
onMouseUp: jest.fn(),
};
-/**
- * Mounts a snippet preview component with changed arguments.
- *
- * @param {object} props The component's props.
- *
- * @returns {ReactElement} The SnippetPreview component.
- */
-const mountWithArgs = ( props ) => {
- return mount(
-
- );
-};
-
describe( "SnippetPreview", () => {
describe( "breadcrumbs", () => {
it( "properly renders multiple breadcrumbs in mobile view", () => {
- const wrapper = mountWithArgs( { mode: MODE_MOBILE, url: "http://www.google.nl/about" } );
-
- expect( wrapper.find( "SnippetPreview__BaseUrlOverflowContainer" ).text() ).toBe( "www.google.nl › about" );
+ render( );
+ const baseURL = screen.getByText( "www.google.nl" );
+ const subFolder = screen.getByText( "› about" );
+ expect( baseURL ).toBeInTheDocument();
+ expect( subFolder ).toBeInTheDocument();
} );
it( "doesn't percent encode characters that are percent encoded by node's url.parse in mobile view", () => {
- const wrapper = mountWithArgs( { mode: MODE_MOBILE, url: "http://www.google.nl/`^ {}" } );
-
- expect( wrapper.find( "SnippetPreview__BaseUrlOverflowContainer" ).text() ).toBe( "www.google.nl › `^ {}" );
+ render( );
+ const baseURL = screen.getByText( "www.google.nl" );
+ const subFolder = screen.getByText( "› `^ {}" );
+ expect( baseURL ).toBeInTheDocument();
+ expect( subFolder ).toBeInTheDocument();
} );
it( "properly renders multiple breadcrumbs in desktop view", () => {
- const wrapper = mountWithArgs( { mode: MODE_DESKTOP, url: "http://example.org/this-url" } );
-
- expect( wrapper.find( "SnippetPreview__BaseUrlOverflowContainer" ).text() ).toBe( "example.org › this-url" );
+ render( );
+ const baseURL = screen.getByText( "www.google.nl" );
+ const subFolder = screen.getByText( "› about" );
+ expect( baseURL ).toBeInTheDocument();
+ expect( subFolder ).toBeInTheDocument();
} );
it( "properly renders multiple breadcrumbs in desktop view without a trailing slash", () => {
- const wrapper = mountWithArgs( { mode: MODE_DESKTOP, url: "http://example.org/this-url/" } );
-
- expect( wrapper.find( "SnippetPreview__BaseUrlOverflowContainer" ).text() ).toBe( "example.org › this-url" );
+ render( );
+ const baseURL = screen.getByText( "www.google.nl" );
+ const subFolder = screen.getByText( "› about" );
+ const subFolderWithTrailingSlash = screen.queryByText( "› about/" );
+ expect( baseURL ).toBeInTheDocument();
+ expect( subFolder ).toBeInTheDocument();
+ expect( subFolderWithTrailingSlash ).not.toBeInTheDocument();
} );
it( "strips http protocol in mobile view", () => {
- const wrapper = mountWithArgs( { mode: MODE_MOBILE, url: "http://www.google.nl/about" } );
-
- expect( wrapper.find( "SnippetPreview__BaseUrlOverflowContainer" ).text() ).toBe( "www.google.nl › about" );
+ render( );
+ const baseURL = screen.getByText( "www.google.nl" );
+ const baseUrlWithProtocol = screen.queryByText( "http://www.google.nl" );
+ const subFolder = screen.getByText( "› subdir" );
+ expect( baseURL ).toBeInTheDocument();
+ expect( baseUrlWithProtocol ).not.toBeInTheDocument();
+ expect( subFolder ).toBeInTheDocument();
} );
it( "strips https protocol in mobile view", () => {
- const wrapper = mountWithArgs( { mode: MODE_MOBILE, url: "https://www.google.nl/about" } );
-
- expect( wrapper.find( "SnippetPreview__BaseUrlOverflowContainer" ).text() ).toBe( "www.google.nl › about" );
+ render( );
+ const baseURL = screen.getByText( "www.google.nl" );
+ const baseUrlWithProtocol = screen.queryByText( "https://www.google.nl" );
+ const subFolder = screen.getByText( "› subdir" );
+ expect( baseURL ).toBeInTheDocument();
+ expect( baseUrlWithProtocol ).not.toBeInTheDocument();
+ expect( subFolder ).toBeInTheDocument();
} );
it( "strips http protocol in desktop view", () => {
- const wrapper = mountWithArgs( { mode: MODE_DESKTOP, url: "http://www.google.nl/about" } );
-
- expect( wrapper.find( "SnippetPreview__BaseUrlOverflowContainer" ).text() ).toBe( "www.google.nl › about" );
+ render( );
+ const baseURL = screen.getByText( "www.google.nl" );
+ const baseUrlWithProtocol = screen.queryByText( "http://www.google.nl" );
+ const subFolder = screen.getByText( "› subdir" );
+ expect( baseURL ).toBeInTheDocument();
+ expect( baseUrlWithProtocol ).not.toBeInTheDocument();
+ expect( subFolder ).toBeInTheDocument();
} );
it( "strips https protocol in desktop view", () => {
- const wrapper = mountWithArgs( { mode: MODE_DESKTOP, url: "https://www.google.nl/about" } );
-
- expect( wrapper.find( "SnippetPreview__BaseUrlOverflowContainer" ).text() ).toBe( "www.google.nl › about" );
+ render( );
+ const baseURL = screen.getByText( "www.google.nl" );
+ const baseUrlWithProtocol = screen.queryByText( "https://www.google.nl" );
+ const subFolder = screen.getByText( "› subdir" );
+ expect( baseURL ).toBeInTheDocument();
+ expect( baseUrlWithProtocol ).not.toBeInTheDocument();
+ expect( subFolder ).toBeInTheDocument();
} );
} );
} );
diff --git a/packages/search-metadata-previews/tests/__snapshots__/HelpTextWrapperTest.js.snap b/packages/search-metadata-previews/tests/__snapshots__/HelpTextWrapperTest.js.snap
index 8da119780de..99c0168e6c4 100644
--- a/packages/search-metadata-previews/tests/__snapshots__/HelpTextWrapperTest.js.snap
+++ b/packages/search-metadata-previews/tests/__snapshots__/HelpTextWrapperTest.js.snap
@@ -135,34 +135,215 @@ exports[`HelpTextWrapper matches the snapshot by default 1`] = `
}
}
-
+`;
+
+exports[`HelpTextWrapper matches the snapshot when the help text button is focused 1`] = `
+.c7 {
+ width: 16px;
+ height: 16px;
+ -webkit-flex: none;
+ -ms-flex: none;
+ flex: none;
+}
+
+.c1 {
+ color: #555;
+ border-color: #ccc;
+ background: #f7f7f7;
+ box-shadow: 0 1px 0 rgba( 204,204,204,1 );
+}
+
+.c2:active {
+ color: #000;
+ background-color: #f7f7f7;
+ box-shadow: inset 0 2px 5px -3px rgba( 0,0,0,0.5 );
+}
+
+.c3::-moz-focus-inner {
+ border-width: 0;
+}
+
+.c3:focus {
+ outline: none;
+ border-color: #0066cd;
+ color: #000;
+ background-color: #fff;
+ box-shadow: 0 0 3px rgba( 8,74,103,0.8 );
+}
+
+.c4:hover {
+ color: #000;
+ background-color: #fff;
+ border-color: var(--yoast-color-border--default);
+}
+
+.c5 {
+ display: -webkit-inline-box;
+ display: -webkit-inline-flex;
+ display: -ms-inline-flexbox;
+ display: inline-flex;
+ -webkit-align-items: center;
+ -webkit-box-align: center;
+ -ms-flex-align: center;
+ align-items: center;
+ -webkit-box-pack: center;
+ -webkit-justify-content: center;
+ -ms-flex-pack: center;
+ justify-content: center;
+ vertical-align: middle;
+ border-width: 1px;
+ border-style: solid;
+ margin: 0;
+ padding: 4px 10px;
+ border-radius: 3px;
+ cursor: pointer;
+ box-sizing: border-box;
+ font-size: inherit;
+ font-family: inherit;
+ font-weight: inherit;
+ text-align: left;
+ overflow: visible;
+ min-height: 32px;
+ -webkit-transition: var(--yoast-transition-default);
+ transition: var(--yoast-transition-default);
+}
+
+.c5 svg {
+ -webkit-align-self: center;
+ -ms-flex-item-align: center;
+ align-self: center;
+}
+
+.c10 {
+ color: #767676;
+ margin-top: 0;
+}
+
+.c9 >:first-child {
+ overflow: hidden;
+ -webkit-transition: height 300ms ease-out;
+ transition: height 300ms ease-out;
+}
+
+.c0 {
+ max-width: 600px;
+ font-weight: normal;
+ margin: 0 20px 0 25px;
+}
+
+.c6 {
+ min-width: 14px;
+ min-height: 14px;
+ width: 30px;
+ height: 30px;
+ border-radius: 50%;
+ border: 1px solid transparent;
+ box-shadow: none;
+ display: block;
+ margin: -44px -10px 10px 0;
+ background-color: transparent;
+ float: right;
+ padding: 3px 0 0 6px;
+}
+
+.c6:hover {
+ color: #0066cd;
+}
+
+.c6:focus {
+ border: 1px solid #0066cd;
+ outline: none;
+ box-shadow: 0 0 3px rgba( 8,74,103,0.8 );
+}
+
+.c6:focus svg {
+ fill: #0066cd;
+ color: #0066cd;
+}
+
+.c6:active {
+ box-shadow: none;
+}
+
+.c8:hover {
+ fill: #0066cd;
+}
+
+@media all and (-ms-high-contrast:none),(-ms-high-contrast:active) {
+ .c5::after {
+ display: inline-block;
+ content: "";
+ min-height: 22px;
+ }
+}
+
+
+ class="c0 yoast-help"
+ >
+
+
+
`;
diff --git a/packages/search-metadata-previews/tests/__snapshots__/SnippetEditorTest.js.snap b/packages/search-metadata-previews/tests/__snapshots__/SnippetEditorTest.js.snap
new file mode 100644
index 00000000000..fbfb1a025d3
--- /dev/null
+++ b/packages/search-metadata-previews/tests/__snapshots__/SnippetEditorTest.js.snap
@@ -0,0 +1,935 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`SnippetEditor Desktop mode and should switch to mobile 1`] = `
+.c29 {
+ width: 16px;
+ height: 16px;
+ -webkit-flex: none;
+ -ms-flex: none;
+ flex: none;
+}
+
+.c22 {
+ color: #555;
+ border-color: #ccc;
+ background: #f7f7f7;
+ box-shadow: 0 1px 0 rgba( 204,204,204,1 );
+}
+
+.c23:active {
+ color: #000;
+ background-color: #f7f7f7;
+ box-shadow: inset 0 2px 5px -3px rgba( 0,0,0,0.5 );
+}
+
+.c24::-moz-focus-inner {
+ border-width: 0;
+}
+
+.c24:focus {
+ outline: none;
+ border-color: #0066cd;
+ color: #000;
+ background-color: #fff;
+ box-shadow: 0 0 3px rgba( 8,74,103,0.8 );
+}
+
+.c25:hover {
+ color: #000;
+ background-color: #fff;
+ border-color: var(--yoast-color-border--default);
+}
+
+.c26 {
+ display: -webkit-inline-box;
+ display: -webkit-inline-flex;
+ display: -ms-inline-flexbox;
+ display: inline-flex;
+ -webkit-align-items: center;
+ -webkit-box-align: center;
+ -ms-flex-align: center;
+ align-items: center;
+ -webkit-box-pack: center;
+ -webkit-justify-content: center;
+ -ms-flex-pack: center;
+ justify-content: center;
+ vertical-align: middle;
+ border-width: 1px;
+ border-style: solid;
+ margin: 0;
+ padding: 4px 10px;
+ border-radius: 3px;
+ cursor: pointer;
+ box-sizing: border-box;
+ font-size: inherit;
+ font-family: inherit;
+ font-weight: inherit;
+ text-align: left;
+ overflow: visible;
+ min-height: 32px;
+ -webkit-transition: var(--yoast-transition-default);
+ transition: var(--yoast-transition-default);
+}
+
+.c26 svg {
+ -webkit-align-self: center;
+ -ms-flex-item-align: center;
+ align-self: center;
+}
+
+.c5 {
+ overflow: auto;
+ width: 640px;
+ padding: 0 20px;
+ max-width: 100%;
+ box-sizing: border-box;
+}
+
+.c7 {
+ width: 600px;
+}
+
+.c6 {
+ background-color: #fff;
+ font-family: arial,sans-serif;
+ box-sizing: border-box;
+}
+
+.c17 {
+ cursor: pointer;
+ position: relative;
+}
+
+.c18 {
+ color: #1a0dab;
+ -webkit-text-decoration: none;
+ text-decoration: none;
+ font-size: 20px;
+ line-height: 1.3;
+ font-weight: normal;
+ margin: 0;
+ display: inline-block;
+ overflow: hidden;
+ max-width: 600px;
+ vertical-align: top;
+ text-overflow: ellipsis;
+}
+
+.c19 {
+ max-width: 600px;
+ vertical-align: top;
+ text-overflow: ellipsis;
+}
+
+.c15 {
+ display: inline-block;
+ max-width: 240px;
+ overflow: hidden;
+ vertical-align: top;
+ text-overflow: ellipsis;
+ margin-left: 4px;
+}
+
+.c20 {
+ white-space: nowrap;
+}
+
+.c8 {
+ display: inline-block;
+ cursor: pointer;
+ position: relative;
+ width: calc( 100% + 7px );
+ white-space: nowrap;
+ font-size: 14px;
+ line-height: 16px;
+ vertical-align: top;
+}
+
+.c9 {
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-align-items: center;
+ -webkit-box-align: center;
+ -ms-flex-align: center;
+ align-items: center;
+ overflow: hidden;
+ -webkit-box-pack: justify;
+ -webkit-justify-content: space-between;
+ -ms-flex-pack: justify;
+ justify-content: space-between;
+ text-overflow: ellipsis;
+ max-width: 100%;
+ margin-bottom: 12px;
+ padding-top: 1px;
+ line-height: 20px;
+ vertical-align: bottom;
+}
+
+.c12 {
+ font-size: 14px;
+ line-height: 1.3;
+ color: #4d5156;
+ -webkit-box-flex: 1;
+ -webkit-flex-grow: 1;
+ -ms-flex-positive: 1;
+ flex-grow: 1;
+}
+
+.c14 {
+ color: #4d5156;
+}
+
+.c10 {
+ width: 28px;
+ height: 28px;
+ margin-right: 12px;
+ border-radius: 50px;
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-align-items: center;
+ -webkit-box-align: center;
+ -ms-flex-align: center;
+ align-items: center;
+ -webkit-box-pack: center;
+ -webkit-justify-content: center;
+ -ms-flex-pack: center;
+ justify-content: center;
+ background: #f1f3f4;
+ min-width: 28px;
+}
+
+.c21 {
+ color: #4d5156;
+ cursor: pointer;
+ position: relative;
+ max-width: 600px;
+ padding-top: 1px;
+ font-size: 14px;
+ line-height: 1.58;
+}
+
+.c13 {
+ line-height: 18x;
+ font-size: 14px;
+ color: black;
+ max-width: 100%;
+ overflow: hidden;
+}
+
+.c16 {
+ display: inline-block;
+ height: 18px;
+ line-height: 18px;
+ padding-left: 8px;
+ vertical-align: bottom;
+}
+
+.c11 {
+ width: 18px;
+ height: 18px;
+ margin: 0 5px;
+ vertical-align: middle;
+}
+
+.c1 {
+ border: 0;
+ padding: 0;
+ margin: 0 0 16px;
+}
+
+.c2 {
+ margin: 8px 0;
+ padding: 0;
+ color: #555;
+ font-size: 14px;
+ font-weight: 600;
+}
+
+.c4 {
+ margin-right: 16px;
+ color: inherit;
+ font-size: 14px;
+ line-height: 1.71428571;
+ cursor: pointer;
+ display: inline-block;
+}
+
+.c3.c3 {
+ margin: 0 8px 0 0;
+ cursor: pointer;
+}
+
+.c0 {
+ margin: 0 0 16px;
+ padding: 0;
+ color: #555;
+ font-size: 12px;
+ font-weight: 300;
+}
+
+.c27 {
+ height: 33px;
+ border: 1px solid #dbdbdb;
+ box-shadow: none;
+ font-family: Arial,Roboto-Regular,HelveticaNeue,sans-serif;
+}
+
+.c28 {
+ margin: 10px 0 0 4px;
+ fill: #555;
+ padding-left: 8px;
+}
+
+.c28 svg {
+ margin-right: 7px;
+}
+
+@media all and (-ms-high-contrast:none),(-ms-high-contrast:active) {
+ .c26::after {
+ display: inline-block;
+ content: "";
+ min-height: 22px;
+ }
+}
+
+
+`;
+
+exports[`SnippetEditor Mobile mode 1`] = `
+.c27 {
+ width: 16px;
+ height: 16px;
+ -webkit-flex: none;
+ -ms-flex: none;
+ flex: none;
+}
+
+.c20 {
+ color: #555;
+ border-color: #ccc;
+ background: #f7f7f7;
+ box-shadow: 0 1px 0 rgba( 204,204,204,1 );
+}
+
+.c21:active {
+ color: #000;
+ background-color: #f7f7f7;
+ box-shadow: inset 0 2px 5px -3px rgba( 0,0,0,0.5 );
+}
+
+.c22::-moz-focus-inner {
+ border-width: 0;
+}
+
+.c22:focus {
+ outline: none;
+ border-color: #0066cd;
+ color: #000;
+ background-color: #fff;
+ box-shadow: 0 0 3px rgba( 8,74,103,0.8 );
+}
+
+.c23:hover {
+ color: #000;
+ background-color: #fff;
+ border-color: var(--yoast-color-border--default);
+}
+
+.c24 {
+ display: -webkit-inline-box;
+ display: -webkit-inline-flex;
+ display: -ms-inline-flexbox;
+ display: inline-flex;
+ -webkit-align-items: center;
+ -webkit-box-align: center;
+ -ms-flex-align: center;
+ align-items: center;
+ -webkit-box-pack: center;
+ -webkit-justify-content: center;
+ -ms-flex-pack: center;
+ justify-content: center;
+ vertical-align: middle;
+ border-width: 1px;
+ border-style: solid;
+ margin: 0;
+ padding: 4px 10px;
+ border-radius: 3px;
+ cursor: pointer;
+ box-sizing: border-box;
+ font-size: inherit;
+ font-family: inherit;
+ font-weight: inherit;
+ text-align: left;
+ overflow: visible;
+ min-height: 32px;
+ -webkit-transition: var(--yoast-transition-default);
+ transition: var(--yoast-transition-default);
+}
+
+.c24 svg {
+ -webkit-align-self: center;
+ -ms-flex-item-align: center;
+ align-self: center;
+}
+
+.c5 {
+ border-bottom: 1px hidden #fff;
+ border-radius: 8px;
+ box-shadow: 0 1px 6px rgba(32,33,36,0.28);
+ font-family: Arial,Roboto-Regular,HelveticaNeue,sans-serif;
+ max-width: 400px;
+ box-sizing: border-box;
+ font-size: 14px;
+}
+
+.c15 {
+ cursor: pointer;
+ position: relative;
+}
+
+.c16 {
+ color: #1558d6;
+ -webkit-text-decoration: none;
+ text-decoration: none;
+ font-size: 20px;
+ line-height: 26px;
+ font-weight: normal;
+ margin: 0;
+ display: inline-block;
+ overflow: hidden;
+ max-width: 600px;
+ vertical-align: top;
+ text-overflow: ellipsis;
+}
+
+.c17 {
+ max-width: 600px;
+ vertical-align: top;
+ text-overflow: ellipsis;
+}
+
+.c14 {
+ display: inline-block;
+ max-width: 100px;
+ overflow: hidden;
+ vertical-align: top;
+ text-overflow: ellipsis;
+ margin-left: 4px;
+}
+
+.c18 {
+ display: inline-block;
+ max-height: 52px;
+ padding-top: 1px;
+ vertical-align: top;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+.c7 {
+ display: inline-block;
+ cursor: pointer;
+ position: relative;
+ width: calc( 100% + 7px );
+ white-space: nowrap;
+ font-size: 14px;
+ line-height: 16px;
+ vertical-align: top;
+}
+
+.c8 {
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-align-items: center;
+ -webkit-box-align: center;
+ -ms-flex-align: center;
+ align-items: center;
+ overflow: hidden;
+ -webkit-box-pack: justify;
+ -webkit-justify-content: space-between;
+ -ms-flex-pack: justify;
+ justify-content: space-between;
+ text-overflow: ellipsis;
+ max-width: 100%;
+ margin-bottom: 12px;
+ padding-top: 1px;
+ line-height: 20px;
+ vertical-align: bottom;
+}
+
+.c11 {
+ font-size: 12px;
+ line-height: 20px;
+ color: #3c4043;
+ -webkit-box-flex: 1;
+ -webkit-flex-grow: 1;
+ -ms-flex-positive: 1;
+ flex-grow: 1;
+}
+
+.c13 {
+ color: #70757a;
+}
+
+.c9 {
+ width: 28px;
+ height: 28px;
+ margin-right: 12px;
+ border-radius: 50px;
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-align-items: center;
+ -webkit-box-align: center;
+ -ms-flex-align: center;
+ align-items: center;
+ -webkit-box-pack: center;
+ -webkit-justify-content: center;
+ -ms-flex-pack: center;
+ justify-content: center;
+ background: #f1f3f4;
+ min-width: 28px;
+}
+
+.c19 {
+ color: #3c4043;
+ font-size: 14px;
+ cursor: pointer;
+ position: relative;
+ line-height: 1.4;
+ max-width: 600px;
+}
+
+.c19:after {
+ display: table;
+ content: "";
+ clear: both;
+}
+
+.c6 {
+ padding: 12px 16px;
+}
+
+.c6:first-child {
+ margin-bottom: -16px;
+}
+
+.c12 {
+ line-height: 18x;
+ font-size: 14px;
+ color: black;
+ max-width: 300px;
+ overflow: hidden;
+}
+
+.c10 {
+ width: 18px;
+ height: 18px;
+ margin: 0 5px;
+ vertical-align: middle;
+}
+
+.c1 {
+ border: 0;
+ padding: 0;
+ margin: 0 0 16px;
+}
+
+.c2 {
+ margin: 8px 0;
+ padding: 0;
+ color: #555;
+ font-size: 14px;
+ font-weight: 600;
+}
+
+.c4 {
+ margin-right: 16px;
+ color: inherit;
+ font-size: 14px;
+ line-height: 1.71428571;
+ cursor: pointer;
+ display: inline-block;
+}
+
+.c3.c3 {
+ margin: 0 8px 0 0;
+ cursor: pointer;
+}
+
+.c0 {
+ margin: 0 0 16px;
+ padding: 0;
+ color: #555;
+ font-size: 12px;
+ font-weight: 300;
+}
+
+.c25 {
+ height: 33px;
+ border: 1px solid #dbdbdb;
+ box-shadow: none;
+ font-family: Arial,Roboto-Regular,HelveticaNeue,sans-serif;
+}
+
+.c26 {
+ margin: 10px 0 0 4px;
+ fill: #555;
+ padding-left: 8px;
+}
+
+.c26 svg {
+ margin-right: 7px;
+}
+
+@media all and (-ms-high-contrast:none),(-ms-high-contrast:active) {
+ .c24::after {
+ display: inline-block;
+ content: "";
+ min-height: 22px;
+ }
+}
+
+
+`;
diff --git a/packages/search-metadata-previews/tests/setupTests.js b/packages/search-metadata-previews/tests/setupTests.js
index 5cd2e56ea46..d6301c14fff 100644
--- a/packages/search-metadata-previews/tests/setupTests.js
+++ b/packages/search-metadata-previews/tests/setupTests.js
@@ -1,5 +1,2 @@
import "jest-styled-components";
-import Enzyme from "enzyme";
-import EnzymeAdapter from "enzyme-adapter-react-16";
-
-Enzyme.configure( { adapter: new EnzymeAdapter() } );
+import "@testing-library/jest-dom";
diff --git a/packages/search-metadata-previews/tests/test-utils.js b/packages/search-metadata-previews/tests/test-utils.js
new file mode 100644
index 00000000000..9c7f86fb46f
--- /dev/null
+++ b/packages/search-metadata-previews/tests/test-utils.js
@@ -0,0 +1 @@
+export * from "@testing-library/react";
diff --git a/packages/social-metadata-forms/jest/setupTests.js b/packages/social-metadata-forms/jest/setupTests.js
index ae2c5706e15..c2212b57c11 100644
--- a/packages/social-metadata-forms/jest/setupTests.js
+++ b/packages/social-metadata-forms/jest/setupTests.js
@@ -1,6 +1,2 @@
import "raf/polyfill";
import "jest-styled-components";
-import Enzyme from "enzyme";
-import EnzymeAdapter from "enzyme-adapter-react-16";
-
-Enzyme.configure( { adapter: new EnzymeAdapter() } );
diff --git a/packages/social-metadata-forms/package.json b/packages/social-metadata-forms/package.json
index 6e4989b62b7..9e2e34bdcb1 100644
--- a/packages/social-metadata-forms/package.json
+++ b/packages/social-metadata-forms/package.json
@@ -16,16 +16,14 @@
"lint": "eslint . --max-warnings=0"
},
"jest": {
+ "testEnvironment": "jest-environment-jsdom",
"testURL": "http://localhost",
"testRegex": ".*Test.js$",
- "snapshotSerializers": [
- "enzyme-to-json/serializer"
- ],
"transform": {
"^.+\\.jsx?$": "babel-jest"
},
"transformIgnorePatterns": [
- "/node_modules/(?!yoastseo|lodash-es).+\\.js$"
+ "/node_modules/(?!yoastseo|lodash-es|memize).+\\.js$"
],
"setupTestFrameworkScriptFile": "