Add checkbox custom field
[MAILPOET-2453]
This commit is contained in:
committed by
Rostislav Wolný
parent
712ea07d17
commit
81c75fafc2
@@ -14,6 +14,7 @@ import * as html from './html/html.jsx';
|
|||||||
import * as customText from './custom_text/custom_text.jsx';
|
import * as customText from './custom_text/custom_text.jsx';
|
||||||
import * as customTextArea from './custom_textarea/custom_textarea.jsx';
|
import * as customTextArea from './custom_textarea/custom_textarea.jsx';
|
||||||
import * as customRadio from './custom_radio/custom_radio.jsx';
|
import * as customRadio from './custom_radio/custom_radio.jsx';
|
||||||
|
import * as customCheckbox from './custom_checkbox/custom_checkbox.jsx';
|
||||||
|
|
||||||
const registerCustomFieldBlock = (customField) => {
|
const registerCustomFieldBlock = (customField) => {
|
||||||
const namesMap = {
|
const namesMap = {
|
||||||
@@ -29,6 +30,10 @@ const registerCustomFieldBlock = (customField) => {
|
|||||||
name: customRadio.name,
|
name: customRadio.name,
|
||||||
settings: customRadio.getSettings(customField),
|
settings: customRadio.getSettings(customField),
|
||||||
},
|
},
|
||||||
|
checkbox: {
|
||||||
|
name: customCheckbox.name,
|
||||||
|
settings: customCheckbox.getSettings(customField),
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!namesMap[customField.type]) return;
|
if (!namesMap[customField.type]) return;
|
||||||
|
@@ -0,0 +1,44 @@
|
|||||||
|
import Icon from '../custom_text/icon.jsx';
|
||||||
|
import Edit from './edit.jsx';
|
||||||
|
|
||||||
|
export const name = 'mailpoet-form/custom-checkbox';
|
||||||
|
|
||||||
|
export function getSettings(customField) {
|
||||||
|
return {
|
||||||
|
title: customField.name,
|
||||||
|
description: '',
|
||||||
|
icon: Icon,
|
||||||
|
category: 'custom-fields',
|
||||||
|
attributes: {
|
||||||
|
label: {
|
||||||
|
type: 'string',
|
||||||
|
default: customField.name,
|
||||||
|
},
|
||||||
|
hideLabel: {
|
||||||
|
type: 'boolean',
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
values: {
|
||||||
|
type: 'array',
|
||||||
|
default: [],
|
||||||
|
},
|
||||||
|
mandatory: {
|
||||||
|
type: 'boolean',
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
customFieldId: {
|
||||||
|
type: 'string',
|
||||||
|
default: customField.id,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
supports: {
|
||||||
|
html: false,
|
||||||
|
customClassName: false,
|
||||||
|
multiple: false,
|
||||||
|
},
|
||||||
|
edit: Edit,
|
||||||
|
save() {
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
@@ -0,0 +1,50 @@
|
|||||||
|
import React, { useState } from 'react';
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
ToggleControl,
|
||||||
|
} from '@wordpress/components';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import MailPoet from 'mailpoet';
|
||||||
|
|
||||||
|
const CustomFieldSettings = ({
|
||||||
|
mandatory,
|
||||||
|
isSaving,
|
||||||
|
onSave,
|
||||||
|
}) => {
|
||||||
|
const [localMandatory, setLocalMandatory] = useState(mandatory);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="custom-field-settings">
|
||||||
|
<Button
|
||||||
|
isPrimary
|
||||||
|
isDefault
|
||||||
|
onClick={() => onSave({
|
||||||
|
mandatory: localMandatory,
|
||||||
|
})}
|
||||||
|
isBusy={isSaving}
|
||||||
|
disabled={isSaving}
|
||||||
|
className="button-on-top"
|
||||||
|
>
|
||||||
|
{MailPoet.I18n.t('customFieldSaveCTA')}
|
||||||
|
</Button>
|
||||||
|
<ToggleControl
|
||||||
|
label={MailPoet.I18n.t('blockMandatory')}
|
||||||
|
checked={localMandatory}
|
||||||
|
onChange={setLocalMandatory}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
CustomFieldSettings.propTypes = {
|
||||||
|
mandatory: PropTypes.bool,
|
||||||
|
onSave: PropTypes.func.isRequired,
|
||||||
|
isSaving: PropTypes.bool,
|
||||||
|
};
|
||||||
|
|
||||||
|
CustomFieldSettings.defaultProps = {
|
||||||
|
mandatory: false,
|
||||||
|
isSaving: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CustomFieldSettings;
|
142
assets/js/src/form_editor/blocks/custom_checkbox/edit.jsx
Normal file
142
assets/js/src/form_editor/blocks/custom_checkbox/edit.jsx
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import {
|
||||||
|
Panel,
|
||||||
|
PanelBody,
|
||||||
|
TextControl,
|
||||||
|
ToggleControl,
|
||||||
|
} from '@wordpress/components';
|
||||||
|
import { InspectorControls } from '@wordpress/block-editor';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import MailPoet from 'mailpoet';
|
||||||
|
import { useDispatch, useSelect } from '@wordpress/data';
|
||||||
|
|
||||||
|
import CustomFieldSettings from './custom_field_settings.jsx';
|
||||||
|
|
||||||
|
const CustomCheckboxEdit = ({ attributes, setAttributes }) => {
|
||||||
|
const isSaving = useSelect(
|
||||||
|
(sel) => sel('mailpoet-form-editor').getIsCustomFieldSaving(),
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
const { saveCustomField } = useDispatch('mailpoet-form-editor');
|
||||||
|
|
||||||
|
const getCheckboxLabel = () => {
|
||||||
|
if (Array.isArray(attributes.values)) {
|
||||||
|
const value = attributes.values[0];
|
||||||
|
if (value) {
|
||||||
|
return value.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
};
|
||||||
|
|
||||||
|
const isChecked = () => {
|
||||||
|
let checked = false;
|
||||||
|
if (Array.isArray(attributes.values)) {
|
||||||
|
const value = attributes.values[0];
|
||||||
|
if (value && value.isChecked) {
|
||||||
|
checked = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return checked;
|
||||||
|
};
|
||||||
|
|
||||||
|
const inspectorControls = (
|
||||||
|
<InspectorControls>
|
||||||
|
<Panel>
|
||||||
|
<PanelBody title={MailPoet.I18n.t('customFieldSettings')} initialOpen>
|
||||||
|
<CustomFieldSettings
|
||||||
|
mandatory={attributes.mandatory}
|
||||||
|
isSaving={isSaving}
|
||||||
|
onSave={(params) => saveCustomField({
|
||||||
|
customFieldId: attributes.customFieldId,
|
||||||
|
data: {
|
||||||
|
params: {
|
||||||
|
required: params.mandatory ? '1' : undefined,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
onFinish: () => setAttributes({
|
||||||
|
mandatory: params.mandatory,
|
||||||
|
}),
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
</PanelBody>
|
||||||
|
</Panel>
|
||||||
|
<Panel>
|
||||||
|
<PanelBody title={MailPoet.I18n.t('formSettings')} initialOpen>
|
||||||
|
<TextControl
|
||||||
|
label={MailPoet.I18n.t('label')}
|
||||||
|
value={attributes.label}
|
||||||
|
data-automation-id="settings_custom_text_label_input"
|
||||||
|
onChange={(label) => (setAttributes({ label }))}
|
||||||
|
/>
|
||||||
|
<ToggleControl
|
||||||
|
label={MailPoet.I18n.t('displayLabel')}
|
||||||
|
checked={!attributes.hideLabel}
|
||||||
|
onChange={(hideLabel) => (setAttributes({ hideLabel: !hideLabel }))}
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={isChecked()}
|
||||||
|
onChange={(event) => setAttributes({
|
||||||
|
values: [{
|
||||||
|
name: getCheckboxLabel(),
|
||||||
|
checked: !!event.target.checked,
|
||||||
|
}],
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
value={getCheckboxLabel()}
|
||||||
|
onChange={(event) => setAttributes({
|
||||||
|
values: [{
|
||||||
|
name: event.target.value,
|
||||||
|
checked: isChecked(),
|
||||||
|
}],
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
</PanelBody>
|
||||||
|
</Panel>
|
||||||
|
</InspectorControls>
|
||||||
|
);
|
||||||
|
|
||||||
|
const getLabel = () => {
|
||||||
|
if (attributes.hideLabel) return null;
|
||||||
|
return attributes.label;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
let checkboxLabel = getCheckboxLabel();
|
||||||
|
if (attributes.mandatory) {
|
||||||
|
checkboxLabel += ' *';
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{inspectorControls}
|
||||||
|
<p>{getLabel()}</p>
|
||||||
|
<div>
|
||||||
|
<label>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
disabled
|
||||||
|
checked={isChecked()}
|
||||||
|
/>
|
||||||
|
{checkboxLabel}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
CustomCheckboxEdit.propTypes = {
|
||||||
|
attributes: PropTypes.shape({
|
||||||
|
label: PropTypes.string.isRequired,
|
||||||
|
mandatory: PropTypes.bool.isRequired,
|
||||||
|
hideLabel: PropTypes.bool,
|
||||||
|
values: PropTypes.arrayOf(PropTypes.shape({
|
||||||
|
name: PropTypes.string.isRequired,
|
||||||
|
isChecked: PropTypes.bool,
|
||||||
|
})),
|
||||||
|
}).isRequired,
|
||||||
|
setAttributes: PropTypes.func.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CustomCheckboxEdit;
|
@@ -1,3 +1,4 @@
|
|||||||
|
import { has } from 'lodash';
|
||||||
|
|
||||||
const mapCustomField = (block, customFields, mappedCommonProperties) => {
|
const mapCustomField = (block, customFields, mappedCommonProperties) => {
|
||||||
const customField = customFields.find((cf) => cf.id === block.attributes.customFieldId);
|
const customField = customFields.find((cf) => cf.id === block.attributes.customFieldId);
|
||||||
@@ -16,16 +17,25 @@ const mapCustomField = (block, customFields, mappedCommonProperties) => {
|
|||||||
if (block.name.startsWith('mailpoet-form/custom-radio')) {
|
if (block.name.startsWith('mailpoet-form/custom-radio')) {
|
||||||
mapped.type = 'radio';
|
mapped.type = 'radio';
|
||||||
}
|
}
|
||||||
if (Object.prototype.hasOwnProperty.call(block.attributes, 'validate')) {
|
if (block.name.startsWith('mailpoet-form/custom-checkbox')) {
|
||||||
|
mapped.type = 'checkbox';
|
||||||
|
}
|
||||||
|
if (has(block.attributes, 'validate')) {
|
||||||
mapped.params.validate = block.attributes.validate;
|
mapped.params.validate = block.attributes.validate;
|
||||||
}
|
}
|
||||||
if (Object.prototype.hasOwnProperty.call(block.attributes, 'hideLabel') && block.attributes.hideLabel) {
|
if (has(block.attributes, 'hideLabel') && block.attributes.hideLabel) {
|
||||||
mapped.params.hide_label = '1';
|
mapped.params.hide_label = '1';
|
||||||
}
|
}
|
||||||
if (Object.prototype.hasOwnProperty.call(block.attributes, 'values')) {
|
if (has(block.attributes, 'values')) {
|
||||||
mapped.params.values = block.attributes.values.map((value) => ({
|
mapped.params.values = block.attributes.values.map((value) => {
|
||||||
value: value.name,
|
const mappedValue = {
|
||||||
}));
|
value: value.name,
|
||||||
|
};
|
||||||
|
if (has(value, 'isChecked') && value.isChecked) {
|
||||||
|
mappedValue.is_checked = '1';
|
||||||
|
}
|
||||||
|
return mappedValue;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return mapped;
|
return mapped;
|
||||||
};
|
};
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
import { has } from 'lodash';
|
||||||
import formatCustomFieldBlockName from '../blocks/format_custom_field_block_name.jsx';
|
import formatCustomFieldBlockName from '../blocks/format_custom_field_block_name.jsx';
|
||||||
|
|
||||||
const mapCustomField = (item, customFields, mappedCommonProperties) => {
|
const mapCustomField = (item, customFields, mappedCommonProperties) => {
|
||||||
@@ -8,6 +9,7 @@ const mapCustomField = (item, customFields, mappedCommonProperties) => {
|
|||||||
text: 'mailpoet-form/custom-text',
|
text: 'mailpoet-form/custom-text',
|
||||||
textarea: 'mailpoet-form/custom-textarea',
|
textarea: 'mailpoet-form/custom-textarea',
|
||||||
radio: 'mailpoet-form/custom-radio',
|
radio: 'mailpoet-form/custom-radio',
|
||||||
|
checkbox: 'mailpoet-form/custom-checkbox',
|
||||||
};
|
};
|
||||||
const mapped = {
|
const mapped = {
|
||||||
...mappedCommonProperties,
|
...mappedCommonProperties,
|
||||||
@@ -15,17 +17,23 @@ const mapCustomField = (item, customFields, mappedCommonProperties) => {
|
|||||||
};
|
};
|
||||||
mapped.attributes.customFieldId = customField.id;
|
mapped.attributes.customFieldId = customField.id;
|
||||||
if (item.params) {
|
if (item.params) {
|
||||||
if (Object.prototype.hasOwnProperty.call(item.params, 'validate') && !!item.params.validate) {
|
if (has(item.params, 'validate') && !!item.params.validate) {
|
||||||
mapped.attributes.validate = item.params.validate;
|
mapped.attributes.validate = item.params.validate;
|
||||||
}
|
}
|
||||||
if (Object.prototype.hasOwnProperty.call(item.params, 'hide_label')) {
|
if (has(item.params, 'hide_label')) {
|
||||||
mapped.attributes.hideLabel = !!item.params.hide_label;
|
mapped.attributes.hideLabel = !!item.params.hide_label;
|
||||||
}
|
}
|
||||||
if (Object.prototype.hasOwnProperty.call(item.params, 'values') && Array.isArray(item.params.values)) {
|
if (has(item.params, 'values') && Array.isArray(item.params.values)) {
|
||||||
mapped.attributes.values = item.params.values.map((value) => ({
|
mapped.attributes.values = item.params.values.map((value) => {
|
||||||
name: value.value,
|
const mappedValue = {
|
||||||
id: `${Math.random().toString()}-${Date.now()}`,
|
name: value.value,
|
||||||
}));
|
id: `${Math.random().toString()}-${Date.now()}`,
|
||||||
|
};
|
||||||
|
if (has(value, 'is_checked') && value.is_checked) {
|
||||||
|
mappedValue.isChecked = true;
|
||||||
|
}
|
||||||
|
return mappedValue;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return mapped;
|
return mapped;
|
||||||
@@ -53,13 +61,13 @@ export default (data, customFields = []) => {
|
|||||||
mandatory: false,
|
mandatory: false,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
if (item.params && Object.prototype.hasOwnProperty.call(item.params, 'required')) {
|
if (item.params && has(item.params, 'required')) {
|
||||||
mapped.attributes.mandatory = !!item.params.required;
|
mapped.attributes.mandatory = !!item.params.required;
|
||||||
}
|
}
|
||||||
if (item.params && Object.prototype.hasOwnProperty.call(item.params, 'label_within')) {
|
if (item.params && has(item.params, 'label_within')) {
|
||||||
mapped.attributes.labelWithinInput = !!item.params.label_within;
|
mapped.attributes.labelWithinInput = !!item.params.label_within;
|
||||||
}
|
}
|
||||||
if (item.params && Object.prototype.hasOwnProperty.call(item.params, 'label')) {
|
if (item.params && has(item.params, 'label')) {
|
||||||
mapped.attributes.label = item.params.label;
|
mapped.attributes.label = item.params.label;
|
||||||
}
|
}
|
||||||
switch (item.id) {
|
switch (item.id) {
|
||||||
@@ -81,7 +89,7 @@ export default (data, customFields = []) => {
|
|||||||
case 'segments':
|
case 'segments':
|
||||||
if (
|
if (
|
||||||
item.params
|
item.params
|
||||||
&& Object.prototype.hasOwnProperty.call(item.params, 'values')
|
&& has(item.params, 'values')
|
||||||
&& Array.isArray(item.params.values)
|
&& Array.isArray(item.params.values)
|
||||||
) {
|
) {
|
||||||
mapped.attributes.values = item.params.values.map((value) => ({
|
mapped.attributes.values = item.params.values.map((value) => ({
|
||||||
|
@@ -88,6 +88,26 @@ const customRadioBlock = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const customCheckBox = {
|
||||||
|
clientId: '5',
|
||||||
|
isValid: true,
|
||||||
|
innerBlocks: [],
|
||||||
|
name: 'mailpoet-form/custom-checkbox',
|
||||||
|
attributes: {
|
||||||
|
label: 'Checkbox',
|
||||||
|
hideLabel: false,
|
||||||
|
mandatory: false,
|
||||||
|
customFieldId: 3,
|
||||||
|
values: [
|
||||||
|
{
|
||||||
|
name: 'Check this',
|
||||||
|
isChecked: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
const dividerBlock = {
|
const dividerBlock = {
|
||||||
clientId: 'some_random_123',
|
clientId: 'some_random_123',
|
||||||
isValid: true,
|
isValid: true,
|
||||||
@@ -306,6 +326,35 @@ describe('Blocks to Form Body', () => {
|
|||||||
expect(input.params.values[1]).to.have.property('value', 'option 2');
|
expect(input.params.values[1]).to.have.property('value', 'option 2');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Should map custom checkbox field', () => {
|
||||||
|
const customField = {
|
||||||
|
created_at: '2019-12-13T15:22:07+00:00',
|
||||||
|
id: 3,
|
||||||
|
name: 'Custom Checkbox',
|
||||||
|
params: {
|
||||||
|
label: 'Check',
|
||||||
|
required: '1',
|
||||||
|
values: [
|
||||||
|
{ value: 'option 1' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
type: 'checkbox',
|
||||||
|
updated_at: '2019-12-13T15:22:07+00:00',
|
||||||
|
};
|
||||||
|
const [input] = formBlocksToBody([customCheckBox], [customField]);
|
||||||
|
checkBodyInputBasics(input);
|
||||||
|
expect(input.id).to.be.equal('3');
|
||||||
|
expect(input.name).to.be.equal('Custom Checkbox');
|
||||||
|
expect(input.type).to.be.equal('checkbox');
|
||||||
|
expect(input.position).to.be.equal('1');
|
||||||
|
expect(input.params.label).to.be.equal('Checkbox');
|
||||||
|
expect(input.params.required).to.be.be.undefined;
|
||||||
|
expect(input.params.hide_label).to.be.undefined;
|
||||||
|
expect(input.params.values).to.be.an('Array').that.has.length(1);
|
||||||
|
expect(input.params.values[0]).to.have.property('value', 'Check this');
|
||||||
|
expect(input.params.values[0]).to.have.property('is_checked', '1');
|
||||||
|
});
|
||||||
|
|
||||||
it('Should map multiple blocks at once', () => {
|
it('Should map multiple blocks at once', () => {
|
||||||
const unknownBlock = {
|
const unknownBlock = {
|
||||||
name: 'unknown',
|
name: 'unknown',
|
||||||
|
@@ -103,6 +103,25 @@ const customRadioInput = {
|
|||||||
},
|
},
|
||||||
position: null,
|
position: null,
|
||||||
};
|
};
|
||||||
|
const customCheckboxInput = {
|
||||||
|
type: 'checkbox',
|
||||||
|
name: 'Custom check',
|
||||||
|
id: '4',
|
||||||
|
unique: '1',
|
||||||
|
static: '0',
|
||||||
|
params: {
|
||||||
|
required: '',
|
||||||
|
label: 'Check this',
|
||||||
|
hide_label: '',
|
||||||
|
values: [
|
||||||
|
{
|
||||||
|
value: 'Check',
|
||||||
|
is_checked: '1',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
position: null,
|
||||||
|
};
|
||||||
const divider = {
|
const divider = {
|
||||||
type: 'divider',
|
type: 'divider',
|
||||||
name: 'Divider',
|
name: 'Divider',
|
||||||
@@ -316,6 +335,36 @@ describe('Form Body To Blocks', () => {
|
|||||||
expect(block.attributes.values[0]).to.have.property('name', 'option 1');
|
expect(block.attributes.values[0]).to.have.property('name', 'option 1');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Should map custom checkbox input to block', () => {
|
||||||
|
const customField = {
|
||||||
|
type: 'checkbox',
|
||||||
|
name: 'Custom check',
|
||||||
|
id: 4,
|
||||||
|
params: {
|
||||||
|
required: '',
|
||||||
|
label: 'Check this',
|
||||||
|
hide_label: '',
|
||||||
|
values: [
|
||||||
|
{
|
||||||
|
value: 'Check',
|
||||||
|
is_checked: '1',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
position: null,
|
||||||
|
};
|
||||||
|
const [block] = formBodyToBlocks([{ ...customCheckboxInput, position: '1' }], [customField]);
|
||||||
|
checkBlockBasics(block);
|
||||||
|
expect(block.clientId).to.be.equal('4_0');
|
||||||
|
expect(block.name).to.be.equal('mailpoet-form/custom-checkbox-customcheck');
|
||||||
|
expect(block.attributes.label).to.be.equal('Check this');
|
||||||
|
expect(block.attributes.mandatory).to.be.equal(false);
|
||||||
|
expect(block.attributes.hideLabel).to.be.equal(false);
|
||||||
|
expect(block.attributes.values).to.be.an('Array').that.has.length(1);
|
||||||
|
expect(block.attributes.values[0]).to.have.property('name', 'Check');
|
||||||
|
expect(block.attributes.values[0]).to.have.property('isChecked', true);
|
||||||
|
});
|
||||||
|
|
||||||
it('Should ignore unknown input type', () => {
|
it('Should ignore unknown input type', () => {
|
||||||
const blocks = formBodyToBlocks([{ ...submitInput, id: 'some-nonsense' }]);
|
const blocks = formBodyToBlocks([{ ...submitInput, id: 'some-nonsense' }]);
|
||||||
expect(blocks).to.be.empty;
|
expect(blocks).to.be.empty;
|
||||||
|
Reference in New Issue
Block a user