Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom Fields option: Add confirmation step #15688

Merged
merged 12 commits into from
Aug 6, 2019
4 changes: 3 additions & 1 deletion packages/e2e-tests/specs/preview.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,10 @@ async function toggleCustomFieldsOption( shouldBeChecked ) {
);

if ( isChecked !== shouldBeChecked ) {
const navigationCompleted = page.waitForNavigation();
await checkboxHandle.click();
const [ saveButton ] = await page.$x( shouldBeChecked ? '//button[text()="Enable & Reload"]' : '//button[text()="Disable & Reload"]' );
const navigationCompleted = page.waitForNavigation();
saveButton.click();
await navigationCompleted;
return;
}
Expand Down
16 changes: 9 additions & 7 deletions packages/edit-post/src/components/options-modal/options/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@
*/
import { CheckboxControl } from '@wordpress/components';

function BaseOption( { label, isChecked, onChange } ) {
function BaseOption( { label, isChecked, onChange, children } ) {
return (
<CheckboxControl
className="edit-post-options-modal__option"
label={ label }
checked={ isChecked }
onChange={ onChange }
/>
<div className="edit-post-options-modal__option">
<CheckboxControl
label={ label }
checked={ isChecked }
onChange={ onChange }
/>
{ children }
</div>
);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,47 +1,54 @@
/**
* WordPress dependencies
*/
import { Component } from '@wordpress/element';
import { useState } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import { Button } from '@wordpress/components';
import { withSelect } from '@wordpress/data';

/**
* Internal dependencies
*/
import BaseOption from './base';

export class EnableCustomFieldsOption extends Component {
constructor( { isChecked } ) {
super( ...arguments );

this.toggleCustomFields = this.toggleCustomFields.bind( this );

this.state = { isChecked };
}

toggleCustomFields() {
// Submit a hidden form which triggers the toggle_custom_fields admin action.
// This action will toggle the setting and reload the editor with the meta box
// assets included on the page.
document.getElementById( 'toggle-custom-fields-form' ).submit();

// Make it look like something happened while the page reloads.
this.setState( { isChecked: ! this.props.isChecked } );
}

render() {
const { label } = this.props;
const { isChecked } = this.state;
export function CustomFieldsConfirmation( { willEnable } ) {
const [ isReloading, setIsReloading ] = useState( false );

return (
<>
<p className="edit-post-options-modal__custom-fields-confirmation-message">
{ __( 'A page reload is required for this change. Make sure your content is saved before reloading.' ) }
</p>
<Button
className="edit-post-options-modal__custom-fields-confirmation-button"
isDefault
isBusy={ isReloading }
disabled={ isReloading }
onClick={ () => {
setIsReloading( true );
document.getElementById( 'toggle-custom-fields-form' ).submit();
} }
>
{ willEnable ? __( 'Enable & Reload' ) : __( 'Disable & Reload' ) }
</Button>
</>
);
}

return (
<BaseOption
label={ label }
isChecked={ isChecked }
onChange={ this.toggleCustomFields }
/>
);
}
export function EnableCustomFieldsOption( { label, areCustomFieldsEnabled } ) {
const [ isChecked, setIsChecked ] = useState( areCustomFieldsEnabled );

return (
<BaseOption
label={ label }
isChecked={ isChecked }
onChange={ setIsChecked }
>
{ isChecked !== areCustomFieldsEnabled && <CustomFieldsConfirmation willEnable={ isChecked } /> }
</BaseOption>
);
}

export default withSelect( ( select ) => ( {
isChecked: !! select( 'core/editor' ).getEditorSettings().enableCustomFields,
areCustomFieldsEnabled: !! select( 'core/editor' ).getEditorSettings().enableCustomFields,
} ) )( EnableCustomFieldsOption );
Original file line number Diff line number Diff line change
@@ -1,17 +1,135 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`EnableCustomFieldsOption renders properly when checked 1`] = `
<BaseOption
isChecked={true}
label="Custom Fields"
onChange={[Function]}
/>
exports[`EnableCustomFieldsOption renders a checked checkbox and a confirmation message when toggled on 1`] = `
<div
className="edit-post-options-modal__option"
>
<div
className="components-base-control"
>
<div
className="components-base-control__field"
>
<input
checked={true}
className="components-checkbox-control__input"
id="inspector-checkbox-control-3"
onChange={[Function]}
type="checkbox"
value="1"
/>
<label
className="components-checkbox-control__label"
htmlFor="inspector-checkbox-control-3"
/>
</div>
</div>
<p
className="edit-post-options-modal__custom-fields-confirmation-message"
>
A page reload is required for this change. Make sure your content is saved before reloading.
</p>
<button
className="components-button edit-post-options-modal__custom-fields-confirmation-button is-button is-default"
disabled={false}
onClick={[Function]}
type="button"
>
Enable & Reload
</button>
</div>
`;

exports[`EnableCustomFieldsOption renders properly when unchecked 1`] = `
<BaseOption
isChecked={false}
label="Custom Fields"
onChange={[Function]}
/>
exports[`EnableCustomFieldsOption renders a checked checkbox when custom fields are enabled 1`] = `
<div
className="edit-post-options-modal__option"
>
<div
className="components-base-control"
>
<div
className="components-base-control__field"
>
<input
checked={true}
className="components-checkbox-control__input"
id="inspector-checkbox-control-0"
onChange={[Function]}
type="checkbox"
value="1"
/>
<label
className="components-checkbox-control__label"
htmlFor="inspector-checkbox-control-0"
/>
</div>
</div>
</div>
`;

exports[`EnableCustomFieldsOption renders an unchecked checkbox and a confirmation message when toggled off 1`] = `
<div
className="edit-post-options-modal__option"
>
<div
className="components-base-control"
>
<div
className="components-base-control__field"
>
<input
checked={false}
className="components-checkbox-control__input"
id="inspector-checkbox-control-2"
onChange={[Function]}
type="checkbox"
value="1"
/>
<label
className="components-checkbox-control__label"
htmlFor="inspector-checkbox-control-2"
/>
</div>
</div>
<p
className="edit-post-options-modal__custom-fields-confirmation-message"
>
A page reload is required for this change. Make sure your content is saved before reloading.
</p>
<button
className="components-button edit-post-options-modal__custom-fields-confirmation-button is-button is-default"
disabled={false}
onClick={[Function]}
type="button"
>
Disable & Reload
</button>
</div>
`;

exports[`EnableCustomFieldsOption renders an unchecked checkbox when custom fields are disabled 1`] = `
<div
className="edit-post-options-modal__option"
>
<div
className="components-base-control"
>
<div
className="components-base-control__field"
>
<input
checked={false}
className="components-checkbox-control__input"
id="inspector-checkbox-control-1"
onChange={[Function]}
type="checkbox"
value="1"
/>
<label
className="components-checkbox-control__label"
htmlFor="inspector-checkbox-control-1"
/>
</div>
</div>
</div>
`;
Original file line number Diff line number Diff line change
@@ -1,62 +1,63 @@
/**
* External dependencies
*/
import { shallow } from 'enzyme';
import { default as TestRenderer, act } from 'react-test-renderer';

/**
* WordPress dependencies
*/
import { Button } from '@wordpress/components';

/**
* Internal dependencies
*/
import { EnableCustomFieldsOption } from '../enable-custom-fields';
import { EnableCustomFieldsOption, CustomFieldsConfirmation } from '../enable-custom-fields';
import BaseOption from '../base';

describe( 'EnableCustomFieldsOption', () => {
it( 'renders properly when checked', () => {
const wrapper = shallow( <EnableCustomFieldsOption label="Custom Fields" isChecked /> );
expect( wrapper ).toMatchSnapshot();
it( 'renders a checked checkbox when custom fields are enabled', () => {
const renderer = TestRenderer.create( <EnableCustomFieldsOption areCustomFieldsEnabled /> );
expect( renderer ).toMatchSnapshot();
} );

it( 'can be unchecked', () => {
const submit = jest.fn();
const getElementById = jest.spyOn( document, 'getElementById' ).mockImplementation( () => ( {
submit,
} ) );

const wrapper = shallow( <EnableCustomFieldsOption label="Custom Fields" isChecked /> );

expect( wrapper.prop( 'isChecked' ) ).toBe( true );

wrapper.prop( 'onChange' )();
wrapper.update();

expect( wrapper.prop( 'isChecked' ) ).toBe( false );
expect( getElementById ).toHaveBeenCalledWith( 'toggle-custom-fields-form' );
expect( submit ).toHaveBeenCalled();
it( 'renders an unchecked checkbox when custom fields are disabled', () => {
const renderer = TestRenderer.create(
<EnableCustomFieldsOption areCustomFieldsEnabled={ false } />
);
expect( renderer ).toMatchSnapshot();
} );

getElementById.mockRestore();
it( 'renders an unchecked checkbox and a confirmation message when toggled off', () => {
const renderer = new TestRenderer.create( <EnableCustomFieldsOption areCustomFieldsEnabled /> );
act( () => {
renderer.root.findByType( BaseOption ).props.onChange( false );
} );
expect( renderer ).toMatchSnapshot();
} );

it( 'renders properly when unchecked', () => {
const wrapper = shallow(
<EnableCustomFieldsOption label="Custom Fields" isChecked={ false } />
it( 'renders a checked checkbox and a confirmation message when toggled on', () => {
const renderer = new TestRenderer.create(
<EnableCustomFieldsOption areCustomFieldsEnabled={ false } />
);
expect( wrapper ).toMatchSnapshot();
act( () => {
renderer.root.findByType( BaseOption ).props.onChange( true );
} );
expect( renderer ).toMatchSnapshot();
} );
} );

it( 'can be checked', () => {
describe( 'CustomFieldsConfirmation', () => {
it( 'submits the toggle-custom-fields-form', () => {
const submit = jest.fn();
const getElementById = jest.spyOn( document, 'getElementById' ).mockImplementation( () => ( {
submit,
} ) );

const wrapper = shallow(
<EnableCustomFieldsOption label="Custom Fields" isChecked={ false } />
);

expect( wrapper.prop( 'isChecked' ) ).toBe( false );

wrapper.prop( 'onChange' )();
wrapper.update();
const renderer = new TestRenderer.create( <CustomFieldsConfirmation /> );
act( () => {
renderer.root.findByType( Button ).props.onClick();
} );

expect( wrapper.prop( 'isChecked' ) ).toBe( true );
expect( getElementById ).toHaveBeenCalledWith( 'toggle-custom-fields-form' );
expect( submit ).toHaveBeenCalled();

Expand Down
16 changes: 12 additions & 4 deletions packages/edit-post/src/components/options-modal/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,21 @@
margin: 0;
}

&.components-base-control + &.components-base-control {
margin-bottom: 0;
}

.components-checkbox-control__label {
flex-grow: 1;
padding: 0.6rem 0 0.6rem 10px;
}
}

&__custom-fields-confirmation-message,
&__custom-fields-confirmation-button {
margin: 0 0 0.6rem 48px;

@include break-medium() {
margin-left: 38px;
}
@include break-small() {
max-width: 300px;
}
}
}