lodash#noop JavaScript Examples
The following examples show how to use
lodash#noop.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: index.js From holo-schedule with MIT License | 6 votes |
notification = {
async create(stringId, { title, message, iconUrl, onClick = noop }) {
await browser.notifications.create(stringId, {
type: 'basic',
title,
message,
// Icon directly from the web will not be loaded successfully in Chrome
// So we load it manually
iconUrl: await fetch(iconUrl)
.then(response => response.blob())
.then(blob => new Promise((resolve, reject) => {
const reader = new FileReader()
reader.onloadend = () => resolve(reader.result)
reader.onerror = reject
reader.readAsDataURL(blob)
}))
.catch(err => {
console.log('[background/notification]Failed to download icon', err.message)
return browser.runtime.getURL('assets/default_avatar.png')
}),
})
console.log('[background/notification]Successfully created a notification')
const handleClicked = notificationId => {
if (notificationId !== stringId) return
onClick()
browser.notifications.onClicked.removeListener(handleClicked)
}
// This callback will not be fired properly in Chrome
// See: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Chrome_incompatibilities#notifications
browser.notifications.onClicked.addListener(handleClicked)
},
}
Example #2
Source File: common.js From jafar with MIT License | 6 votes |
resources = {
components: {
inputText: {
renderer: noop,
stateChange: (props) => {
if (props.value === 'Monica') {
return { ...props.state, mock: 1 };
}
if (props.state.loading) {
return { ...props.state, loading: false };
}
},
},
},
conversions: {
addPrefix: { func: props => `${props.args.prefix}${props.value}` },
removePrefix: { func: props => props.value.replace(props.args.prefix, '') }, // remove 'Formatted ' prefix
},
dependenciesChanges: {
lastNameDependenciesChange: { func: noop },
},
validators: {
uniqueName: {
func: () => true,
message: noop,
},
},
terms: {
myCustomTerm: { func: noop },
},
hooks: {
beforeAction: noop,
afterAction: noop,
afterChangeData: () => {}, // don't convert to noop
},
}
Example #3
Source File: index.js From hzero-front with Apache License 2.0 | 6 votes |
@Bind()
handleOkBtnClick() {
const { onOk, afterOk } = this.dealProps;
let afterOkCallback = afterOk;
if (!isFunction(afterOk)) {
afterOkCallback = noop;
}
if (isFunction(onOk)) {
const onOkReturn = onOk();
if (onOkReturn === false) {
return false;
}
if (isPromise(onOkReturn)) {
onOkReturn.then(
() => {
this.setState({ visible: false });
afterOkCallback();
},
() => {
this.setState({ visible: true });
}
);
} else {
this.setState({ visible: false });
afterOkCallback();
}
} else {
this.setState({ visible: false });
afterOkCallback();
}
}
Example #4
Source File: dropdown.js From horondi_client_fe with MIT License | 6 votes |
Dropdown.defaultProps = {
mappedItems: [],
handler: noop,
defaultValue: 0,
value: 0,
fromSideBar: false,
styles: {
rootItem: '',
rootSelect: ''
}
};
Example #5
Source File: dialog-window.reducer.test.js From horondi_admin with MIT License | 6 votes |
describe('dialog window reducer tests', () => {
it('should return default state', () => {
expect(dialogWindowReducer(initialState)).toEqual(initialState);
});
it('should set isOpen to true', () => {
expect(
dialogWindowReducer(initialState, showDialog({ isOpen: true }))
).toEqual({
...initialState,
isOpen: true
});
});
it('should set isOpen to false', () => {
expect(dialogWindowReducer(initialState, closeDialog())).toEqual({
...initialState,
isOpen: false
});
});
it('should be defined', () => {
expect(initialState.dialogTitle).toBeDefined();
expect(initialState.dialogContent).toBeDefined();
expect(initialState.onClickHandler).toEqual(noop);
expect(initialState.onClickHandler).not.toBeNull();
});
});
Example #6
Source File: SettingsComponentBuilder.js From ui-data-export with Apache License 2.0 | 6 votes |
SettingsComponentBuilder = ({
children,
sendCallout = noop,
}) => {
return (
<Router>
<OverlayContainer />
<Paneset>
<CalloutContext.Provider value={{ sendCallout }}>
{children}
</CalloutContext.Provider>
</Paneset>
</Router>
);
}
Example #7
Source File: listen.js From holo-schedule with MIT License | 6 votes |
listen = (name, { onConnect = noop, onMessage = noop } = {}) => {
portByName[name] = {
onConnect,
onMessage,
postMessage: message => {
ports.forEach(port => {
port.postMessage({ isResponse: false, name, message })
})
},
}
return portByName[name]
}
Example #8
Source File: EditJobProfileRoute.test.js From ui-data-export with Apache License 2.0 | 6 votes |
setupEditJobProfileRoute = ({
matchParams = {},
location = {
search: '?location',
},
} = {}) => {
renderWithIntl(
<SettingsComponentBuilder>
<EditJobProfileRoute
mutator={{ jobProfile: { PUT: noop } }}
history={history}
resources={{
mappingProfiles: {
hasLoaded: true,
records: [],
},
}}
location={location}
match={{ params: matchParams }}
onSubmit={noop}
onCancel={noop}
/>
</SettingsComponentBuilder>,
translationsProperties
);
}
Example #9
Source File: create.js From holo-schedule with MIT License | 6 votes |
create = (name, { onMessage = noop } = {}) => {
portByName[name] = {
name,
postMessage: message => new Promise((res, rej) => {
const id = uniqueId()
setPendingMessage(id, { res, rej, name, message })
if (!port) {
connectPort()
}
port.postMessage({ isResponse: false, id, name, message })
}),
onMessage,
}
return portByName[name]
}
Example #10
Source File: CreateJobProfileRoute.test.js From ui-data-export with Apache License 2.0 | 6 votes |
setupCreateJobProfileRoute = ({
matchParams = {},
location = {
search: '?location',
},
} = {}) => {
renderWithIntl(
<SettingsComponentBuilder>
<CreateJobProfileRoute
mutator={{ jobProfile: { POST: noop } }}
history={history}
resources={{
mappingProfiles: {
hasLoaded: true,
records: [],
},
}}
location={location}
match={{ params: matchParams }}
onSubmit={noop}
onCancel={noop}
/>
</SettingsComponentBuilder>,
translationsProperties
);
}
Example #11
Source File: product-materials-container.js From horondi_admin with MIT License | 5 votes |
ProductMaterialsContainer.defaultProps = { toggleFieldsChanged: noop };
Example #12
Source File: node-details.js From ThreatMapper with Apache License 2.0 | 5 votes |
NodeDetails.defaultProps = { renderNodeDetailsExtras: noop, };
Example #13
Source File: routes.js From horondi_admin with MIT License | 5 votes |
Routes.defaultProps = { validatorMethods: PropTypes.shape({ deleteValidation: noop, toggleRerender: noop }) };
Example #14
Source File: mockReactI18next.js From covid19_scenarios with MIT License | 5 votes |
initReactI18next = {
type: '3rdParty',
init: noop,
}
Example #15
Source File: store.js From holo-schedule with MIT License | 5 votes |
createStore = () => {
const data = {}
const dataToSync = {}
const callbacks = []
console.log('[background/store]listening to store')
const port = listen('store', {
onConnect: $port => Object.entries(data).forEach(([key, value]) => {
$port.postMessage({ key, value })
}),
})
const uploadToSync = async () => {
if (data[SHOULD_SYNC_SETTINGS]) {
await storage.sync.set({ store: dataToSync })
}
}
const set = async (obj, { local = true, sync = false } = { local: true, sync: false }) => {
Object.entries(obj).forEach(([key, value]) => {
console.log(`[background/store]${key} has been stored/updated successfully.`)
const oldValue = data[key]
data[key] = value
callbacks.forEach(callback => callback(key, value, oldValue))
port.postMessage({ key, value })
})
if (local) {
await withLock(async () => storage.local.set({ store: { ...await getStorage('local'), ...obj } }))
}
if (sync) {
Object.assign(dataToSync, obj)
await uploadToSync()
}
}
const downloadFromSync = async () => {
Object.assign(dataToSync, await getStorage('sync'))
if (data[SHOULD_SYNC_SETTINGS]) {
await set(dataToSync, { local: false })
}
}
return {
data,
dataToSync,
callbacks,
downloadFromSync,
uploadToSync,
set,
async init() {
await set(await getStorage('local'), { local: false })
await downloadFromSync()
this.subscribe(SHOULD_SYNC_SETTINGS, async () => {
await uploadToSync()
})
},
get(key) {
return cloneDeep(data[key])
},
subscribe(key = '', callback = noop) {
callbacks.push(($key, ...args) => {
if (key === $key) {
callback(...args)
}
})
},
}
}
Example #16
Source File: anatomyFieldHelpers.jsx From covid19-testing with Apache License 2.0 | 5 votes |
export function withManagedFocus() {
return (Component) =>
class extends React.PureComponent {
static displayName = getDisplayName(Component, 'withManagedFocus');
static propTypes = {
/**
* This function will be called with a reference to this instance. This is useful for programmatically
* setting the underlying DOM element's focus (the element that is passed to inputRef).
*/
focusRef: PropTypes.func,
inputRef: PropTypes.func,
onBlur: PropTypes.func,
onFocus: PropTypes.func,
};
static defaultProps = {
focusRef: noop,
inputRef: noop,
onBlur: noop,
onFocus: noop,
};
state = {
isFocused: false,
};
componentDidMount() {
this.props.focusRef(this);
}
/**
* Parents (or children) of this component can use this method in conjunction with the ref passed to focusRef
* to set the browser focus to whatever element is passed to inputRef (via the children of this component).
*
* Note that this will automatically trigger onFocus as well via normal DOM behavior.
*/
focus = () => {
this.inputRef.focus();
};
onBlur = (event) => {
this.setState({
isFocused: false,
});
this.props.onBlur(event);
};
onFocus = (event) => {
this.setState({
isFocused: true,
});
this.props.onFocus(event);
};
setInputRef = (ref) => {
this.inputRef = ref;
this.props.inputRef(ref);
};
render() {
const {focusRef, ...rest} = this.props;
return (
<Component
{...this.state}
{...rest}
focus={this.focus}
inputRef={this.setInputRef}
onBlur={this.onBlur}
onFocus={this.onFocus}
/>
);
}
};
}
Example #17
Source File: Form.js From jafar with MIT License | 5 votes |
init(model, resources, settings, onUpdateForm = noop) {
this[internal] = { model, resources, settings };
this.onUpdateForm = onUpdateForm;
return safe.call(this, () => exec.call(this, Actions.INIT, [model, resources, settings]));
}
Example #18
Source File: customized-delete-icon.js From horondi_admin with MIT License | 5 votes |
CustomizedDeleteIcon.defaultProps = { onClickHandler: noop };
Example #19
Source File: JobProfilesForm.js From ui-data-export with Apache License 2.0 | 5 votes |
JobProfilesForm = props => {
const {
onCancel = noop,
hasLoaded = false,
mappingProfiles = [],
pristine,
submitting,
handleSubmit,
paneTitle,
metadata,
headLine,
} = props;
const intl = useIntl();
return (
<Layer
isOpen
contentLabel={intl.formatMessage({ id: 'ui-data-export.mappingProfiles.newProfile' })}
>
<FullScreenForm
id="job-profiles-form"
noValidate
paneTitle={paneTitle}
isSubmitButtonDisabled={pristine || submitting}
onSubmit={handleSubmit}
onCancel={onCancel}
>
{!hasLoaded && <Preloader />}
{hasLoaded && (
<div className={css.jobProfilesFormContent}>
{headLine}
<div>{metadata}</div>
<div data-test-job-profile-form-name>
<Field
label={<FormattedMessage id="stripes-data-transfer-components.name" />}
name="name"
id="job-profile-name"
component={TextField}
fullWidth
required
/>
</div>
<div data-test-job-profile-form-mapping-profile>
<Field
label={<FormattedMessage id="ui-data-export.mappingProfile" />}
name="mappingProfileId"
id="mapping-profile-id"
component={Select}
dataOptions={mappingProfiles}
placeholder={intl.formatMessage({ id: 'ui-data-export.mappingProfiles.selectProfile' })}
fullWidth
required
/>
</div>
<div data-test-job-profile-description>
<Field
label={<FormattedMessage id="ui-data-export.description" />}
name="description"
id="job-profile-description"
component={TextArea}
fullWidth
/>
</div>
</div>
)}
</FullScreenForm>
</Layer>
);
}
Example #20
Source File: delete-button.js From horondi_admin with MIT License | 5 votes |
DeleteButton.defaultProps = {
size: 'medium',
onClickHandler: noop
};
Example #21
Source File: JobProfileDetails.test.js From ui-data-export with Apache License 2.0 | 4 votes |
describe('JobProfileDetails', () => {
const stripes = {
connect: Component => props => (
<Component
{... props}
mutator={{}}
resources={{}}
/>
),
};
const renderJobProfileDetails = () => {
renderWithIntl(
<SettingsComponentBuilder>
<JobProfileDetails
stripes={stripes}
jobProfile={jobProfile}
mappingProfile={mappingProfile}
isDefaultProfile
isProfileUsed
onCancel={noop}
onDelete={noop}
/>
</SettingsComponentBuilder>,
translationsProperties
);
};
it('should display job profile details', () => {
renderJobProfileDetails();
const dialog = screen.getByRole('dialog');
expect(dialog).toBeVisible();
const headings = within(dialog).getAllByRole('heading', { name: jobProfile.name });
headings.forEach(heading => expect(heading).toBeVisible());
const summary = within(dialog).getByRole('region', { name: /summary/i });
const labelsAndValues = [
'Record created: 12/4/2018 11:22 AM',
'Record last updated: 12/4/2018 1:28 PM',
commonTranslations.name,
jobProfile.name,
translations.description,
jobProfile.description,
translations.mappingProfile,
mappingProfile.name,
];
labelsAndValues.forEach(el => expect(within(summary).getByText(el)).toBeVisible());
});
it('should display action buttons in the proper state', () => {
renderJobProfileDetails();
const actionButton = screen.getByText('Actions');
userEvent.click(actionButton);
const deleteButton = screen.getByText(commonTranslations.delete);
const duplicateButton = screen.getByText(commonTranslations.duplicate);
const editButton = screen.getByText(commonTranslations.edit);
expect(deleteButton).toBeEnabled();
expect(duplicateButton).toBeEnabled();
expect(editButton).toBeEnabled();
});
describe('rendering details without description for a job profile which is not already in use', () => {
const renderJobProfileWitoutDescription = () => {
renderWithIntl(
<SettingsComponentBuilder>
<JobProfileDetails
stripes={stripes}
jobProfile={{
...jobProfile,
description: null,
}}
mappingProfile={mappingProfile}
isDefaultProfile={false}
isProfileUsed={false}
onCancel={noop}
/>
</SettingsComponentBuilder>,
translationsProperties
);
};
it('should display no value in description', () => {
renderJobProfileWitoutDescription();
const description = document.querySelector('[data-test-job-profile-description]');
expect(within(description).getByText('-')).toBeVisible();
});
it('should display action buttons in the proper state', () => {
renderJobProfileWitoutDescription();
const actionButton = screen.getByText('Actions');
userEvent.click(actionButton);
const deleteButton = screen.getByText(commonTranslations.delete);
const duplicateButton = screen.getByText(commonTranslations.duplicate);
const editButton = screen.getByText(commonTranslations.edit);
expect(deleteButton).toBeEnabled();
expect(duplicateButton).toBeEnabled();
expect(editButton).toBeEnabled();
});
describe('clicking on delete profiles button', () => {
it('should display delete confirmation modal', async () => {
renderJobProfileWitoutDescription();
const actionButton = screen.getByText('Actions');
userEvent.click(actionButton);
const deleteButton = screen.getByText(commonTranslations.delete);
userEvent.click(deleteButton);
const modal = screen.getAllByRole('dialog').find(dialog => within(dialog).getByRole('heading', { name: /delete/i }));
expect(modal).toBeVisible();
userEvent.click(within(modal).getByRole('button', { name: /cancel/i }));
await waitForElementToBeRemoved(modal);
});
});
});
describe('rendering job profile details in loading state', () => {
const renderJobProfileWithLoading = () => {
renderWithIntl(
<SettingsComponentBuilder>
<JobProfileDetails
stripes={stripes}
isLoading
isDefaultProfile={false}
isProfileUsed
onCancel={noop}
/>
</SettingsComponentBuilder>,
translationsProperties
);
};
it('should display preloader', () => {
renderJobProfileWithLoading();
expect(document.querySelector('[data-test-preloader]')).toBeVisible();
});
});
});
Example #22
Source File: stepper-control-buttons.test.js From horondi_admin with MIT License | 4 votes |
describe('Stepper control buttons tests', () => {
const useSelectorMock = jest.spyOn(reactRedux, 'useSelector');
const mockHandleNext = jest.fn(noop);
const mockHandleBack = jest.fn(noop);
const activeStep = stepsLabels.length - 1;
let component;
beforeEach(() => {
useSelectorMock.mockImplementation((callback) => callback(mockStore));
component = mount(
<StepperControlButtons
handleNext={mockHandleNext}
handleBack={mockHandleBack}
activeStep={activeStep}
type={inputTypes.button}
/>
);
});
afterEach(() => {
component.unmount();
mockHandleBack.mockClear();
mockHandleNext.mockClear();
useSelectorMock.mockClear();
});
it('Should render two buttons', () => {
expect(component.find('button')).toHaveLength(2);
});
it('Should render the first button with BACK label', () => {
const backBtn = component.find('button').first();
expect(backBtn.text()).toBe(BACK);
});
it('Should render the second button with CREATE_PRODUCT label when activeStep equals stepsLabels.length - 1', () => {
const btn = component.find('button').at(1);
expect(btn.text()).toBe(CREATE_PRODUCT);
});
it('Should render the second button with NEXT label when activeStep does not equal stepsLabels.length - 1', () => {
component.setProps({ activeStep: activeStep + 1 });
const btn = component.find('button').at(1);
expect(btn.text()).toBe(NEXT);
});
it('Should run handleBack when click on the first button', () => {
if (activeStep === 0) {
component.setProps({ activeStep: 5 });
}
component.find('button').first().simulate('click');
expect(mockHandleBack).toHaveBeenCalledTimes(1);
});
it('Should run handleNext when click on the second button', () => {
component.find('button').at(1).simulate('click');
expect(mockHandleNext).toHaveBeenCalledTimes(1);
});
it('BACK button should be disabled when activeStep equals zero', () => {
component.setProps({ activeStep: 0 });
component.find('button').first().simulate('click');
expect(mockHandleBack).toHaveBeenCalledTimes(0);
});
it('Should have default props', () => {
expect(StepperControlButtons.defaultProps).toBeDefined();
expect(StepperControlButtons.defaultProps.type).toBe('button');
});
it('Should have prop types', () => {
expect(StepperControlButtons.propTypes.activeStep).toBe(
PropTypes.number.isRequired
);
expect(StepperControlButtons.propTypes.handleNext).toBe(PropTypes.func);
expect(StepperControlButtons.propTypes.handleBack).toBe(PropTypes.func);
expect(StepperControlButtons.propTypes.type).toBe(PropTypes.string);
});
it('Should render CircularProgress when loading is true', () => {
const circular = component.find('.MuiCircularProgress-svg');
expect(circular).toHaveLength(1);
});
it('Should not render CircularProgress when loading is false', () => {
mockStore.Products.loading = false;
component = mount(
<StepperControlButtons
handleNext={mockHandleNext}
handleBack={mockHandleBack}
activeStep={activeStep}
type={inputTypes.button}
/>
);
const circular = component.find('.MuiCircularProgress-svg');
expect(circular).toHaveLength(0);
});
});
Example #23
Source File: MappingProfilesTransformationsModal.js From ui-data-export with Apache License 2.0 | 4 votes |
MappingProfilesTransformationsModal = ({
isOpen,
initialTransformationsValues,
initialSelectedTransformations = {},
disabledRecordTypes = {},
onCancel,
onSubmit,
}) => {
const [isFilterPaneOpen, setFilterPaneOpen] = useState(true);
const [searchValue, setSearchValue] = useState(initialSearchFormValues.searchValue);
const [searchFilters, setSearchFilters] = useState(initialSearchFormValues.filters);
const [selectedTransformations, setSelectedTransformations] = useState(initialSelectedTransformations);
const transformationsFormStateRef = useRef(null);
const initialFormValues = useMemo(() => ({
searchValue: initialSearchFormValues.searchValue,
filters: searchFilters,
}), [searchFilters]);
const [validatedTransformations, setValidatedTransformations] = useState({});
const [isSubmitButtonDisabled, setIsSubmitButtonDisabled] = useState(true);
const resetSearchForm = useCallback(() => {
setSearchFilters({
...initialSearchFormValues.filters,
recordTypes: initialSearchFormValues.filters.recordTypes.filter(record => !disabledRecordTypes[record]),
});
setSearchValue(initialSearchFormValues.searchValue);
}, [disabledRecordTypes]);
useEffect(() => {
if (!isOpen) {
setFilterPaneOpen(true);
resetSearchForm();
}
}, [isOpen, resetSearchForm]);
const searchValueResults = !searchValue
? initialTransformationsValues.transformations
: initialTransformationsValues.transformations
.filter(value => value.displayName.toLowerCase().includes(searchValue));
const searchResults = [];
let displayedCheckedItemsAmount = 0;
const filterMap = {
recordTypes: (filters, transformation) => filters.includes(transformation.recordType),
statuses: (filters, transformation) => filters.some(status => statusesFilterMap[status](transformation, selectedTransformations)),
};
searchValueResults.forEach(transformation => {
const hasFilterMatch = Object.keys(filterMap)
.every(filterKey => {
const filter = get(searchFilters, filterKey, []);
return filterMap[filterKey](filter, transformation);
});
if (hasFilterMatch) {
searchResults.push(transformation);
if (selectedTransformations[transformation.fieldId]) {
displayedCheckedItemsAmount++;
}
}
});
const toggleFilterPane = useCallback(() => setFilterPaneOpen(curState => !curState), []);
const handleFiltersChange = useCallback((key, value) => setSearchFilters(curFilters => ({
...curFilters,
[key]: value,
})), []);
const handleSelectChange = useCallback(
transformations => {
if (isSubmitButtonDisabled) {
setIsSubmitButtonDisabled(false);
}
setSelectedTransformations(transformations);
}, [isSubmitButtonDisabled]
);
const handleSearchFormSubmit = useCallback(values => {
setSearchValue(values.searchValue?.toLowerCase());
}, []);
const handleCancel = () => {
setValidatedTransformations({});
setIsSubmitButtonDisabled(false);
setSelectedTransformations(initialSelectedTransformations);
onCancel();
};
const handleSaveButtonClick = () => {
const transformations = get(transformationsFormStateRef.current.getState(), 'values.transformations', []);
const invalidTransformations = validateTransformations(transformations);
const isTransformationFormValid = isEmpty(invalidTransformations);
if (isTransformationFormValid) {
const normalizedTransformations = normalizeTransformationFormValues(transformations);
setValidatedTransformations({});
setIsSubmitButtonDisabled(false);
onSubmit(normalizedTransformations);
} else {
setValidatedTransformations(invalidTransformations);
setIsSubmitButtonDisabled(true);
}
};
const renderFooter = () => {
return (
<div className={css.modalFooter}>
<Button
data-test-transformations-cancel
className="left"
marginBottom0
onClick={handleCancel}
>
<FormattedMessage id="stripes-components.cancel" />
</Button>
<div data-test-transformations-total-selected>
<FormattedMessage
id="ui-data-export.modal.totalSelected"
values={{ count: Object.keys(selectedTransformations).length }}
/>
</div>
<Button
data-test-transformations-save
buttonStyle="primary"
disabled={isSubmitButtonDisabled}
marginBottom0
onClick={handleSaveButtonClick}
>
<FormattedMessage id="stripes-components.saveAndClose" />
</Button>
</div>
);
};
return (
<Modal
data-test-transformations-modal
contentClass={css.modalContent}
label={<FormattedMessage id="ui-data-export.mappingProfiles.transformations.selectTransformations" />}
footer={renderFooter()}
open={isOpen}
dismissible
enforceFocus={false}
size="large"
onClose={handleCancel}
>
<Paneset>
<Pane
data-test-transformations-search-pane
defaultWidth="30%"
paneTitle={<FormattedMessage id="ui-data-export.searchAndFilter" />}
lastMenu={<CollapseFilterPaneButton onClick={toggleFilterPane} />}
hidden={!isFilterPaneOpen}
>
<SearchForm
initialValues={initialFormValues}
disabledRecordTypes={disabledRecordTypes}
onFiltersChange={handleFiltersChange}
onReset={resetSearchForm}
onSubmit={handleSearchFormSubmit}
/>
</Pane>
<Pane
data-test-transformations-results-pane
defaultWidth="fill"
hasPadding={false}
paneTitle={<FormattedMessage id="ui-data-export.transformations" />}
paneSub={(
<FormattedMessage
id="ui-data-export.mappingProfiles.transformations.searchResultsCountHeader"
values={{ count: searchResults.length }}
/>
)}
firstMenu={!isFilterPaneOpen ? <ExpandFilterPaneButton onClick={toggleFilterPane} /> : null}
{...(!isFilterPaneOpen && fullWidthStyle)}
>
<TransformationsForm
id="transformations-form"
stateRef={transformationsFormStateRef}
initialValues={initialTransformationsValues}
searchResults={searchResults}
validatedTransformations={validatedTransformations}
isSelectAllChecked={displayedCheckedItemsAmount === searchResults.length}
setValidatedTransformations={setValidatedTransformations}
setIsSubmitButtonDisabled={setIsSubmitButtonDisabled}
onSelectChange={handleSelectChange}
onSubmit={noop}
/>
</Pane>
</Paneset>
</Modal>
);
}
Example #24
Source File: Form.spec.js From jafar with MIT License | 4 votes |
describe('Form', () => {
let simpleForm;
let commonForm;
let dependencyChangeForm;
let dependencyChangeWithParserFormatterForm;
let syncValidatorForm;
let asyncValidatorForm;
let stateChangesForm;
let processQueueForm;
let dependenciesForm;
beforeEach(() => {
simpleForm = cloneDeep(simpleFormMock);
commonForm = cloneDeep(commonFormMock);
dependencyChangeForm = cloneDeep(dependencyChangeFormMock);
dependencyChangeWithParserFormatterForm = cloneDeep(dependencyChangeWithParserFormatterFormMock);
syncValidatorForm = cloneDeep(syncValidatorFormMock);
asyncValidatorForm = cloneDeep(asyncValidatorFormMock);
stateChangesForm = cloneDeep(stateChangesFormMock);
processQueueForm = cloneDeep(processQueueFormMock);
dependenciesForm = cloneDeep(dependenciesMock);
});
describe('create form', () => {
it('create few forms without id', async () => {
let form = new Form();
simpleForm.model.id = undefined;
await form.init(simpleForm.model, simpleForm.resources);
expect(form.id).toEqual('form-1');
form = new Form();
delete simpleForm.model.id;
await form.init(simpleForm.model, simpleForm.resources);
expect(form.id).toEqual('form-2');
form = new Form();
simpleForm.model.id = 'some-id';
await form.init(simpleForm.model, simpleForm.resources);
expect(form.id).toEqual('some-id');
form = new Form();
delete simpleForm.model.id;
await form.init(simpleForm.model, simpleForm.resources);
expect(form.id).toEqual('form-3');
});
it('init with toDto', async () => {
simpleForm.model.data = { a: 1 };
const expectedData = { a: 2 };
simpleForm.resources.hooks = {
toDto: ({ data }) => ({ a: data.a + 1 }),
};
let publicForm;
const form = new Form();
await form.init(simpleForm.model, simpleForm.resources, undefined, x => { publicForm = x; });
expect(form.data).toEqual(expectedData);
expect(publicForm.model.data).toEqual(expectedData);
expect(publicForm.model.initializedData).toEqual(expectedData);
expect(publicForm.model.initialModel.data).toEqual({ a: 1 });
});
it('init persistent form with toDto and reset', async () => {
const serverData = { name: 1 }
simpleForm.model.data = serverData;
let expectedDataAfterFirstInit = { name: 2 };
simpleForm.resources.hooks = {
toDto: ({ data }) => ({ name: data.name + 1 }),
};
let publicForm;
let form = new Form();
await form.init(simpleForm.model, simpleForm.resources, undefined, x => { publicForm = x; });
expect(form.data).toEqual(expectedDataAfterFirstInit);
expect(publicForm.model.data).toEqual(expectedDataAfterFirstInit);
expect(publicForm.model.initializedData).toEqual(expectedDataAfterFirstInit);
expect(publicForm.model.initialModel.data).toEqual(serverData);
const expectedData = { name: 3 };
await form.changeValue('name', 3);
expect(form.data).toEqual(expectedData);
form = new Form();
await form.init(publicForm.model, simpleForm.resources, undefined, x => { publicForm = x; });
expect(form.data).toEqual(expectedData);
expect(publicForm.model.data).toEqual(expectedData);
expect(publicForm.model.initializedData).toEqual(expectedDataAfterFirstInit);
expect(publicForm.model.initialModel.data).toEqual(serverData);
await form.reset();
expect(form.data).toEqual(expectedDataAfterFirstInit);
expect(publicForm.model.data).toEqual(expectedDataAfterFirstInit);
expect(publicForm.model.initializedData).toEqual(expectedDataAfterFirstInit);
expect(publicForm.model.initialModel.data).toEqual(serverData);
});
});
describe('change field value', () => {
it('should update the form data on change field value', async () => {
const form = new Form();
await form.init(simpleForm.model, simpleForm.resources);
expect(form.data).toEqual({});
await form.changeValue('name', 'Gal');
expect(form.data).toEqual({
name: 'Gal',
});
});
it('using updater function - with component value - changed ok', async () => {
const form = new Form();
simpleForm.model.fields.name.component = {
name: 'inputText',
value: 1,
};
simpleForm.model.data.name = 1;
simpleForm.resources.components = {
inputText: { renderer: noop },
};
await form.init(simpleForm.model, simpleForm.resources);
expect(form.pendingActions).toEqual([]);
const promise1 = form.changeValue('name', ({ value }) => (value + 1));
const promise2 = form.changeValue('name', ({ value }) => (value + 1));
await Promise.all([promise1, promise2]);
expect(form.fields.name.component.value).toEqual(3);
expect(form.data.name).toEqual(3);
expect(form.pendingActions).toEqual([]);
});
it('using updater function - without a component definition - throws error', async () => {
const form = new Form();
delete simpleForm.model.fields.name.component;
simpleForm.model.data.name = 1;
let error;
log.error = (err) => { error = err; };
await form.init(simpleForm.model, simpleForm.resources);
expect(form.pendingActions).toEqual([]);
await form.changeValue('name', ({ value }) => (value + 1));
expect(error.code).toEqual(errors.CHANGE_VALUE_UPDATER_NOT_SUPPORTED.code);
expect(form.fields.name.component).toEqual(undefined);
expect(form.data.name).toEqual(1);
expect(form.pendingActions).toEqual([]);
});
it('should resolve after dependency change', async () => {
const form = new Form();
await form.init(dependencyChangeForm.model, dependencyChangeForm.resources);
await form.changeValue('country', 'Israel');
expect(form.data).toEqual({
country: 'Israel', city: 'Tel Aviv', address: 'Ben Yehuda', countryCode: 'IL',
});
});
it('should remove field the form data on set empty field value', async () => {
const form = new Form();
await form.init(simpleForm.model, simpleForm.resources);
expect(form.data).toEqual({});
await form.changeValue('name', 'Gal');
expect(form.data).toEqual({
name: 'Gal',
});
await form.changeValue('name', '');
expect(form.data).toEqual({});
});
it('should handle dependencies change changes value - to a field with parser formatter', async () => {
const form = new Form();
await form.init(dependencyChangeWithParserFormatterForm.model, dependencyChangeWithParserFormatterForm.resources);
expect(form.data).toEqual({});
await form.changeValue('country', 'Israel');
expect(form.data).toEqual({ country: 'IL', city: 'JRM' });
expect(form.fields.country.component.value).toEqual('Israel');
expect(form.fields.city.component.value).toEqual('Jerusalem');
await form.changeValue('city', 'Tel Aviv');
expect(form.data).toEqual({ country: 'IL', city: 'TLV' });
expect(form.fields.country.component.value).toEqual('Israel');
expect(form.fields.city.component.value).toEqual('Tel Aviv');
});
it('after dependenciesChange return both new value and state, stateChange uses new data value and view value of itself', async () => {
const form = new Form();
let values;
dependencyChangeWithParserFormatterForm.model.fields.address = {
path: 'address',
dependencies: ['city'],
dependenciesChange: ({ dependencies, prevDependencies }) => {
if (prevDependencies && (dependencies.city.value !== prevDependencies.city.value)) {
return {
value: dependencies.city.value,
state: { a: 1 },
}
}
},
component: {
name: 'address',
},
parser: ({ value }) => value === 'Tel Aviv' ? 'TLV' : 'JRM',
formatter: ({ value }) => value === 'TLV' ? 'Tel Aviv' : 'Jerusalem',
};
dependencyChangeWithParserFormatterForm.resources.components.address = {
renderer: () => {},
stateChange: ({ value, componentValue }) => {
if (values) { // only after init
values.push(`${value} ${componentValue}`);
}
},
};
await form.init(dependencyChangeWithParserFormatterForm.model, dependencyChangeWithParserFormatterForm.resources);
values = [];
await form.changeValue('city', 'Tel Aviv');
await form.changeValue('city', 'Jerusalem');
expect(values).toEqual([
'TLV Tel Aviv',
'JRM Jerusalem',
]);
});
describe('mode cases - with boolean required', () => {
it('field.validators = [‘uniqueName’], field.required = true, incoming value = empty', async () => {
syncValidatorForm.model.fields.name.required = true;
syncValidatorForm.resources.validators.uniqueName.func = jest.fn();
const form = new Form();
await form.init(syncValidatorForm.model, syncValidatorForm.resources);
await form.changeValue('name', '');
// verify value unset
expect(form.data.name).toEqual(undefined);
// verify required error
expect(form.fields.name.errors).toEqual([{ name: 'required', message: 'Field required' }]);
// verify flags
expect(form.fields.name.dirty).toEqual(false);
expect(form.fields.name.empty).toEqual(true);
expect(form.fields.name.invalid).toEqual(true);
expect(form.invalid).toEqual(true);
expect(form.errors).toEqual({ name: form.fields.name.errors });
// verify validators not called
expect(syncValidatorForm.resources.validators.uniqueName.func).not.toHaveBeenCalled();
});
it('field.validators = [‘uniqueName’], field.required = false, incoming value = empty', async () => {
syncValidatorForm.model.fields.name.required = false;
syncValidatorForm.resources.validators.uniqueName.func = jest.fn();
const form = new Form();
await form.init(syncValidatorForm.model, syncValidatorForm.resources);
await form.changeValue('name', '');
// verify value unset
expect(form.data.name).toEqual(undefined);
// verify no error
expect(form.fields.name.errors).toEqual([]);
// verify flags
expect(form.fields.name.dirty).toEqual(false);
expect(form.fields.name.empty).toEqual(true);
expect(form.fields.name.invalid).toEqual(false);
expect(form.invalid).toEqual(false);
expect(form.errors).toEqual({});
// verify validators not called
expect(syncValidatorForm.resources.validators.uniqueName.func).not.toHaveBeenCalled();
});
it('field.validators = [‘uniqueName’], field.required = true, incoming value = not empty - valid name', async () => {
syncValidatorForm.model.fields.name.required = true;
syncValidatorForm.resources.validators.uniqueName.func = jest.fn(() => true);
const form = new Form();
await form.init(syncValidatorForm.model, syncValidatorForm.resources);
await form.changeValue('name', 'Rachel');
// verify value unset
expect(form.data.name).toEqual('Rachel');
// verify no error
expect(form.fields.name.errors).toEqual([]);
// verify flags
expect(form.fields.name.dirty).toEqual(true);
expect(form.fields.name.empty).toEqual(false);
expect(form.fields.name.invalid).toEqual(false);
expect(form.invalid).toEqual(false);
expect(form.errors).toEqual({});
// verify validators not called
expect(syncValidatorForm.resources.validators.uniqueName.func).toHaveBeenCalled();
});
it('field.validators = [‘uniqueName’], field.required = true, incoming value = not empty - not valid name', async () => {
syncValidatorForm.model.fields.name.required = true;
syncValidatorForm.resources.validators.uniqueName.func = jest.fn(() => false);
const form = new Form();
await form.init(syncValidatorForm.model, syncValidatorForm.resources);
await form.changeValue('name', 'Rachel');
// verify value unset
expect(form.data.name).toEqual('Rachel');
// verify no error
expect(form.fields.name.errors).toEqual([{ name: 'uniqueName', message: 'Name should be unique' }]);
// verify flags
expect(form.fields.name.dirty).toEqual(true);
expect(form.fields.name.empty).toEqual(false);
expect(form.fields.name.invalid).toEqual(true);
expect(form.invalid).toEqual(true);
expect(form.errors).toEqual({ name: form.fields.name.errors });
// verify validators not called
expect(syncValidatorForm.resources.validators.uniqueName.func).toHaveBeenCalled();
});
it('field.validators = [‘uniqueName’], field.required = false, incoming value = not empty - valid name', async () => {
syncValidatorForm.model.fields.name.required = false;
syncValidatorForm.resources.validators.uniqueName.func = jest.fn(() => true);
const form = new Form();
await form.init(syncValidatorForm.model, syncValidatorForm.resources);
await form.changeValue('name', 'Rachel');
// verify value unset
expect(form.data.name).toEqual('Rachel');
// verify no error
expect(form.fields.name.errors).toEqual([]);
// verify flags
expect(form.fields.name.dirty).toEqual(true);
expect(form.fields.name.empty).toEqual(false);
expect(form.fields.name.invalid).toEqual(false);
expect(form.invalid).toEqual(false);
expect(form.errors).toEqual({});
// verify validators not called
expect(syncValidatorForm.resources.validators.uniqueName.func).toHaveBeenCalled();
});
it('field.validators = [‘uniqueName’], field.required = false, incoming value = not empty - not valid name', async () => {
syncValidatorForm.model.fields.name.required = false;
syncValidatorForm.resources.validators.uniqueName.func = jest.fn(() => false);
const form = new Form();
await form.init(syncValidatorForm.model, syncValidatorForm.resources);
await form.changeValue('name', 'Rachel');
// verify value unset
expect(form.data.name).toEqual('Rachel');
// verify no error
expect(form.fields.name.errors).toEqual([{ name: 'uniqueName', message: 'Name should be unique' }]);
// verify flags
expect(form.fields.name.dirty).toEqual(true);
expect(form.fields.name.empty).toEqual(false);
expect(form.fields.name.invalid).toEqual(true);
expect(form.invalid).toEqual(true);
expect(form.errors).toEqual({ name: form.fields.name.errors });
// verify validators not called
expect(syncValidatorForm.resources.validators.uniqueName.func).toHaveBeenCalled();
});
});
describe('mode cases - with requireTerm', () => {
it('field.validators = [‘uniqueName’], field.required = true, incoming value = empty', async () => {
syncValidatorForm.model.fields.name.requireTerm = { name: 'isRequired' };
syncValidatorForm.resources.terms = { isRequired: { func: jest.fn(() => true) } };
syncValidatorForm.resources.validators.uniqueName.func = jest.fn();
const form = new Form();
await form.init(syncValidatorForm.model, syncValidatorForm.resources);
await form.changeValue('name', '');
// verify value unset
expect(form.data.name).toEqual(undefined);
// verify required error
expect(form.fields.name.errors).toEqual([{ name: 'required', message: 'Field required' }]);
// verify flags
expect(form.fields.name.dirty).toEqual(false);
expect(form.fields.name.empty).toEqual(true);
expect(form.fields.name.invalid).toEqual(true);
expect(form.invalid).toEqual(true);
expect(form.errors).toEqual({ name: form.fields.name.errors });
// verify validators not called
expect(syncValidatorForm.resources.validators.uniqueName.func).not.toHaveBeenCalled();
});
it('field.validators = [‘uniqueName’], field.required = false, incoming value = empty', async () => {
syncValidatorForm.model.fields.name.requireTerm = { name: 'isRequired' };
syncValidatorForm.resources.terms = { isRequired: { func: jest.fn(() => false) } };
syncValidatorForm.resources.validators.uniqueName.func = jest.fn();
const form = new Form();
await form.init(syncValidatorForm.model, syncValidatorForm.resources);
await form.changeValue('name', '');
// verify value unset
expect(form.data.name).toEqual(undefined);
// verify no error
expect(form.fields.name.errors).toEqual([]);
// verify flags
expect(form.fields.name.dirty).toEqual(false);
expect(form.fields.name.empty).toEqual(true);
expect(form.fields.name.invalid).toEqual(false);
expect(form.invalid).toEqual(false);
expect(form.errors).toEqual({});
// verify validators not called
expect(syncValidatorForm.resources.validators.uniqueName.func).not.toHaveBeenCalled();
});
it('field.validators = [‘uniqueName’], field.required = true, incoming value = not empty - valid name', async () => {
syncValidatorForm.model.fields.name.requireTerm = { name: 'isRequired' };
syncValidatorForm.resources.terms = { isRequired: { func: jest.fn(() => true) } };
syncValidatorForm.resources.validators.uniqueName.func = jest.fn(() => true);
const form = new Form();
await form.init(syncValidatorForm.model, syncValidatorForm.resources);
await form.changeValue('name', 'Rachel');
// verify value unset
expect(form.data.name).toEqual('Rachel');
// verify no error
expect(form.fields.name.errors).toEqual([]);
// verify flags
expect(form.fields.name.dirty).toEqual(true);
expect(form.fields.name.empty).toEqual(false);
expect(form.fields.name.invalid).toEqual(false);
expect(form.invalid).toEqual(false);
expect(form.errors).toEqual({});
// verify validators not called
expect(syncValidatorForm.resources.validators.uniqueName.func).toHaveBeenCalled();
});
it('field.validators = [‘uniqueName’], field.required = true, incoming value = not empty - not valid name', async () => {
syncValidatorForm.model.fields.name.requireTerm = { name: 'isRequired' };
syncValidatorForm.resources.terms = { isRequired: { func: jest.fn(() => true) } };
syncValidatorForm.resources.validators.uniqueName.func = jest.fn(() => false);
const form = new Form();
await form.init(syncValidatorForm.model, syncValidatorForm.resources);
await form.changeValue('name', 'Rachel');
// verify value unset
expect(form.data.name).toEqual('Rachel');
// verify no error
expect(form.fields.name.errors).toEqual([{ name: 'uniqueName', message: 'Name should be unique' }]);
// verify flags
expect(form.fields.name.dirty).toEqual(true);
expect(form.fields.name.empty).toEqual(false);
expect(form.fields.name.invalid).toEqual(true);
expect(form.invalid).toEqual(true);
expect(form.errors).toEqual({ name: form.fields.name.errors });
// verify validators not called
expect(syncValidatorForm.resources.validators.uniqueName.func).toHaveBeenCalled();
});
it('field.validators = [‘uniqueName’], field.required = false, incoming value = not empty - valid name', async () => {
syncValidatorForm.model.fields.name.requireTerm = { name: 'isRequired' };
syncValidatorForm.resources.terms = { isRequired: { func: jest.fn(() => false) } };
syncValidatorForm.resources.validators.uniqueName.func = jest.fn(() => true);
const form = new Form();
await form.init(syncValidatorForm.model, syncValidatorForm.resources);
await form.changeValue('name', 'Rachel');
// verify value unset
expect(form.data.name).toEqual('Rachel');
// verify no error
expect(form.fields.name.errors).toEqual([]);
// verify flags
expect(form.fields.name.dirty).toEqual(true);
expect(form.fields.name.empty).toEqual(false);
expect(form.fields.name.invalid).toEqual(false);
expect(form.invalid).toEqual(false);
expect(form.errors).toEqual({});
// verify validators not called
expect(syncValidatorForm.resources.validators.uniqueName.func).toHaveBeenCalled();
});
it('field.validators = [‘uniqueName’], field.required = false, incoming value = not empty - not valid name', async () => {
syncValidatorForm.model.fields.name.requireTerm = { name: 'isRequired' };
syncValidatorForm.resources.terms = { isRequired: { func: jest.fn(() => false) } };
syncValidatorForm.resources.validators.uniqueName.func = jest.fn(() => false);
const form = new Form();
await form.init(syncValidatorForm.model, syncValidatorForm.resources);
await form.changeValue('name', 'Rachel');
// verify value unset
expect(form.data.name).toEqual('Rachel');
// verify no error
expect(form.fields.name.errors).toEqual([{ name: 'uniqueName', message: 'Name should be unique' }]);
// verify flags
expect(form.fields.name.dirty).toEqual(true);
expect(form.fields.name.empty).toEqual(false);
expect(form.fields.name.invalid).toEqual(true);
expect(form.invalid).toEqual(true);
expect(form.errors).toEqual({ name: form.fields.name.errors });
// verify validators not called
expect(syncValidatorForm.resources.validators.uniqueName.func).toHaveBeenCalled();
});
});
describe('fields dependencies', () => {
it('should trigger dependent field evaluation', async () => {
const invalidError = [{ name: 'descriptionContainsSubject', message: 'Subject should be included in description' }];
const requiredError = [{ name: 'required', message: 'Field required' }];
const form = new Form();
await form.init(dependenciesForm.model, dependenciesForm.resources);
expect(form.invalid).toEqual(false);
// change subject to 'a'
await form.changeValue('subject', 'a');
// verify data
expect(form.data).toEqual({ subject: 'a' });
// verify errors
expect(form.fields.subject.errors).toEqual(invalidError);
expect(form.fields.description.errors).toEqual(requiredError);
// verify form validity
expect(form.invalid).toEqual(true);
// change description to 'b'
await form.changeValue('description', 'b');
// verify data
expect(form.data).toEqual({ subject: 'a', description: 'b' });
// verify errors
expect(form.fields.subject.errors).toEqual(invalidError);
expect(form.fields.description.errors).toEqual(invalidError);
// verify form validity
expect(form.invalid).toEqual(true);
// change description to 'ba'
await form.changeValue('description', 'ba');
// verify data
expect(form.data).toEqual({ subject: 'a', description: 'ba' });
// verify errors
expect(form.fields.subject.errors).toEqual([]);
expect(form.fields.description.errors).toEqual([]);
// verify form validity
expect(form.invalid).toEqual(false);
});
});
});
describe('2 Form instances with the same id', () => {
it('destroy first without await -> init second without await - both with same form definition (id in specific)', async () => {
let uiForm1;
let uiForm2;
const updateUiFrom1 = (form) => { uiForm1 = form; };
const updateUiFrom2 = (form) => { uiForm2 = form; };
const form1 = new Form();
await form1.init(commonForm.model, commonForm.resources, undefined, updateUiFrom1);
const resolve1 = form1.destroy();
const form2 = new Form();
const resolve2 = form2.init(commonForm.model, commonForm.resources, undefined, updateUiFrom2);
await Promise.all([resolve1, resolve2]);
expect(uiForm1).toEqual(undefined);
expect(uiForm2).toBeTruthy();
});
});
describe('process queue', () => {
describe('should handle queue of processes one after another, and not mixed together', () => {
it('form class demonstration', async () => {
const form = new Form();
await form.init(processQueueForm.model, processQueueForm.resources);
expect(form.data).toEqual({});
expect(form.invalid).toBeFalsy();
// form class case - working ok cause we are waiting
await form.changeValue('name', 'Rachel');
await form.changeValue('name', 'Monica');
expect(form.data).toEqual({ name: 'Monica' });
expect(form.invalid).toBeFalsy();
});
/* TODO: add process queue to fix bug. After adding the process queue - this test should ensure it
This is the bug that fails the below test for now:
1. set name Rachel
2. set name Monica
3. validate monica + update form invalid -> Form is valid
4. validate rachel + update form invalid -> Form is invalid
The correct order - using process queue - needs to be (the test will pass after adding process queue)
1. set name Rachel
2. validate rachel + update form invalid -> Form is invalid
3. set name Monica
4. validate monica + update form invalid -> Form is valid
*/
it('react-form demonstration', async () => {
const form = new Form();
await form.init(processQueueForm.model, processQueueForm.resources);
expect(form.data).toEqual({});
expect(form.invalid).toBeFalsy();
// react form case - fails (without having await one after another in the same code block -
// can call action parallel from the ui)
form.changeValue('name', 'Rachel');
await wait(250); // wait for debounce to finish
form.changeValue('name', 'Monica');
await wait(1000); // wait for process to finish
expect(form.data).toEqual({ name: 'Monica' });
expect(form.invalid).toBeFalsy();
});
});
});
describe('destroy form', () => {
it('form should throw an error when try to call action after destroy', async () => {
const form = new Form();
await form.init(simpleForm.model, simpleForm.resources);
expect(form.id).toEqual('simple');
await form.destroy();
// call action of the form
let error;
try {
await form.changeValue('name', 'Tag');
} catch (err) {
error = err;
}
expect(error.code).toEqual(errors.ACCESS_DESTROYED_FORM.code);
});
it('form should throw an error when try to call getter after destroy', async () => {
const form = new Form();
await form.init(simpleForm.model, simpleForm.resources);
expect(form.id).toEqual('simple');
await form.destroy();
// try get property of the form
let error;
try {
const { id } = form; // eslint-disable-line
} catch (err) {
error = err;
}
expect(error.code).toEqual(errors.ACCESS_DESTROYED_FORM.code);
});
it('ui case - destroy form without await and call form action after without await - form should not handle '
+ 'new actions after destroy', async () => {
const form = new Form();
await form.init(simpleForm.model, simpleForm.resources);
expect(form.id).toEqual('simple');
// UI case: when editing component that called "onValueChange" on blur and right after click "save" that
// redirect from the page and destroy the form
// destroy is async so by the time its "addAction" to queue happens - the changeValue already fires
// order: changeValue called (on blur) -> destroy called -> changeValue await 250ms for debounce ->
// destroy "addAction" called -> changeValue "addAction" called after 250ms that will fail cuz form is undefined
// after destroy - so this function make sure it wont throw error when process queue is closed
// we dont want to throw error in this case - cuz the component actually called onValueChange before the destroy
// so only ignore
const promise1 = form.changeValue('name', 'Tag');
const promise2 = form.changeValue('name', 'Tag2');
const promise3 = form.destroy();
let error;
try {
await Promise.all([promise1, promise2, promise3]);
} catch (err) {
error = err;
}
expect(error).toBeFalsy();
});
});
describe('state changes', () => {
it('changed ok', async () => {
const form = new Form();
simpleForm.model.fields.name.component = {
name: 'inputText',
state: {},
};
simpleForm.resources.components = {
inputText: { renderer: noop },
};
await form.init(simpleForm.model, simpleForm.resources);
expect(form.pendingActions).toEqual([]);
await form.changeState('name', { mockState: 'mockState' });
expect(form.fields.name.component.state).toEqual({ mockState: 'mockState' });
expect(form.pendingActions).toEqual([]);
});
it('using updater function - changed ok', async () => {
const form = new Form();
simpleForm.model.fields.name.component = {
name: 'inputText',
state: {
num: 1,
},
};
simpleForm.resources.components = {
inputText: { renderer: noop },
};
await form.init(simpleForm.model, simpleForm.resources);
expect(form.pendingActions).toEqual([]);
const promise1 = form.changeState('name', ({ state }) => ({ num: state.num + 1 }));
const promise2 = form.changeState('name', ({ state }) => ({ num: state.num + 1 }));
await Promise.all([promise1, promise2]);
expect(form.fields.name.component.state).toEqual({ num: 3 });
expect(form.pendingActions).toEqual([]);
});
it('loop state changes - ok', async () => {
const form = new Form();
await form.init(stateChangesForm.model, stateChangesForm.resources);
expect(form.pendingActions).toEqual([]);
const afterInitState = {
items: [{ label: 'Monica', value: 'MONICA' }, { label: 'Ross', value: 'ROSS' }],
isLoading: false,
search: {
value: '',
},
};
expect(form.fields.name.component.state).toEqual(afterInitState);
const newState = Object.assign(afterInitState, {
search: {
value: 'm',
},
});
await form.changeState('name', newState);
const afterChangeState = {
items: [{ label: 'Monica', value: 'MONICA' }],
isLoading: false,
search: {
value: 'm',
},
};
expect(form.fields.name.component.state).toEqual(afterChangeState);
expect(form.pendingActions).toEqual([]);
});
});
describe('Field change ui', () => {
it('changed ok - only component', async () => {
const component = { name: 'myInputText' };
simpleForm.resources.components = {
myInputText: {
renderer: () => {},
},
};
const expectedComponent = {
name: 'myInputText',
value: undefined,
state: {},
modelState: {},
prevState: undefined,
prevValue: undefined,
};
const form = new Form();
await form.init(simpleForm.model, simpleForm.resources);
await form.changeUi('name', { component });
expect(form.fields.name.component).toEqual(expectedComponent);
expect(form.fields.name.formatter).toEqual(undefined);
expect(form.fields.name.parser).toEqual(undefined);
});
it('changed ok - with label, description ,component, formatter, parser', async () => {
const label = 'New Label';
const description = 'New Description';
const component = { name: 'myInputText' };
const formatter = { name: 'formatter1' };
const parser = { name: 'parser1' };
const expectedComponent = {
name: 'myInputText',
value: undefined,
state: {},
modelState: {},
prevState: undefined,
prevValue: undefined,
};
simpleForm.resources.components = {
myInputText: {
renderer: () => {},
},
};
simpleForm.resources.conversions = {
formatter1: { func: () => {} },
parser1: { func: () => {} },
};
const ui = { label, description, component, formatter, parser };
const form = new Form();
await form.init(simpleForm.model, simpleForm.resources);
await form.changeUi('name', ui);
expect(form.fields.name.label).toEqual(label);
expect(form.fields.name.description).toEqual(description);
expect(form.fields.name.component).toEqual(expectedComponent);
expect(form.fields.name.formatter).toEqual(formatter);
expect(form.fields.name.parser).toEqual(parser);
});
it('changed ok - with component, formatter and no parser', async () => {
const component = { name: 'myInputText' };
const expectedComponent = {
name: 'myInputText',
value: undefined,
state: {},
modelState: {},
prevState: undefined,
prevValue: undefined,
};
const formatter = { name: 'formatter1' };
simpleForm.resources.components = {
myInputText: {
renderer: () => {},
},
};
simpleForm.resources.conversions = {
formatter1: { func: () => {} },
};
const form = new Form();
await form.init(simpleForm.model, simpleForm.resources);
await form.changeUi('name', { component, formatter });
expect(form.fields.name.component).toEqual(expectedComponent);
expect(form.fields.name.formatter).toEqual(formatter);
expect(form.fields.name.parser).toEqual(undefined);
});
it('didn\'t change - throws missing component', async () => {
const form = new Form();
await form.init(simpleForm.model, simpleForm.resources);
let error;
log.error = (err) => { error = err; };
await form.changeUi('name', { component: { name: 'myInputText2' } });
expect(error.code).toEqual(errors.ACTION_FAILED.code);
expect(error.subError.code).toEqual(errors.MISSING_COMPONENT.code);
});
});
describe('change data', () => {
it('should update the form data to a new object and evaluates form', async () => {
const form = new Form();
await form.init(commonForm.model, commonForm.resources);
expect(form.data).toEqual({ name: 'Rachel', lastName: 'Green' });
const newData = { name: 'Monica', lastName: 'Geller' };
await form.changeData(newData);
expect(form.data).toEqual(newData);
expect(form.fields.name.component.value).toEqual('Formatted Monica');
});
});
describe('change context', () => {
it('should update the form context to a new object and evaluate form', async () => {
const form = new Form();
commonForm.model.fields.lastName.excludeTerm = { name: 'ifUser222' };
commonForm.resources.terms.ifUser222 = { func: ({context}) => context.userId === '222' };
await form.init(commonForm.model, commonForm.resources);
expect(form.context).toEqual({ userId: '123', companyId: '789' });
expect(form.fields.lastName.excluded).toBeFalsy();
const newContext = { userId: '222', companyId: '333' };
await form.changeContext(newContext);
expect(form.context).toEqual(newContext);
expect(form.fields.lastName.excluded).toBeTruthy();
});
});
describe('submit', () => {
it('should throw invalid submit when form is invalid', async () => {
simpleForm.model.fields.name.required = true;
simpleForm.model.data = {};
let error;
log.error = (err) => { error = err; };
const form = new Form();
await form.init(simpleForm.model, simpleForm.resources);
expect(form.invalid).toEqual(true);
const success = await form.submit();
// verify submit fail
expect(success).toEqual(undefined);
expect(error.code).toEqual(errors.ACTION_FAILED.code);
expect(error.subError.code).toEqual(errors.INVALID_SUBMIT.code);
});
it('validate return errors', async () => {
simpleForm.model.fields.excludedField = { path: 'excludedField', excludeTerm: { name: 'excludeMe' } };
simpleForm.resources.terms = { excludeMe: { func: () => true } };
// validate returns errors of:
// existing fields with errors, un existing fields, excluded fields, undefined fieldId, fields with empty errors
const errors = [{ name: 'unique', message: 'already exists' }];
simpleForm.resources.hooks = {
validate: jest.fn(() => ({
name: errors,
lastName: [],
bla: errors,
excludedField: errors,
undefined: errors,
})),
submit: jest.fn(),
};
const form = new Form();
await form.init(simpleForm.model, simpleForm.resources);
const success = await form.submit();
// verify submit fail
expect(success).toEqual(undefined);
// check validate called
expect(simpleForm.resources.hooks.validate).toHaveBeenCalled();
// check submit not called
expect(simpleForm.resources.hooks.submit).not.toHaveBeenCalled();
// check only existing non-excluded fields has errors and invalid now
expect(form.fields.name.errors).toEqual(errors);
expect(form.fields.name.invalid).toEqual(true);
expect(form.fields.lastName.errors).toEqual([]);
expect(form.fields.lastName.invalid).toEqual(false);
expect(form.fields.excludedField.errors).toEqual([]);
expect(form.fields.excludedField.invalid).toEqual(false);
// verify also form errors and invalid
expect(form.errors).toEqual({ name: errors });
expect(form.invalid).toEqual(true);
});
it('validate return errors - undefined', async () => {
// validate returns errors undefined
const data = { name: 'Rachel' };
simpleForm.model.data = data;
simpleForm.resources.hooks = {
validate: jest.fn(() => undefined),
submit: jest.fn(),
};
const form = new Form();
await form.init(simpleForm.model, simpleForm.resources);
const success = await form.submit();
// verify submit success
expect(success).toEqual(true);
// check validate called
expect(simpleForm.resources.hooks.validate).toHaveBeenCalled();
// check submit not called
expect(simpleForm.resources.hooks.submit).toHaveBeenCalledWith({ data, context: {} });
// verify form errors = [] and invalid = false
expect(form.errors).toEqual({});
expect(form.invalid).toEqual(false);
});
it('validate return errors object - empty', async () => {
// validate returns errors undefined
const data = { name: 'Rachel' };
simpleForm.model.data = data;
simpleForm.resources.hooks = {
validate: jest.fn(() => {}),
submit: jest.fn(),
};
const form = new Form();
await form.init(simpleForm.model, simpleForm.resources);
const success = await form.submit();
// verify submit success
expect(success).toEqual(true);
// check validate called
expect(simpleForm.resources.hooks.validate).toHaveBeenCalled();
// check submit not called
expect(simpleForm.resources.hooks.submit).toHaveBeenCalledWith({ data, context: {} });
// verify form errors = [] and invalid = false
expect(form.errors).toEqual({});
expect(form.invalid).toEqual(false);
});
it('validate return errors - not empty - but all errors are empty', async () => {
const data = { name: 'Rachel' };
simpleForm.model.data = data;
simpleForm.resources.hooks = {
validate: jest.fn(() => ({ name: [] })),
submit: jest.fn(),
};
const form = new Form();
await form.init(simpleForm.model, simpleForm.resources);
const success = await form.submit();
// verify submit success
expect(success).toEqual(true);
// check validate called
expect(simpleForm.resources.hooks.validate).toHaveBeenCalled();
// check submit not called
expect(simpleForm.resources.hooks.submit).toHaveBeenCalledWith({ data, context: {} });
// verify form errors = [] and invalid = false
expect(form.errors).toEqual({});
expect(form.invalid).toEqual(false);
});
it('should wait for sync submit', async () => {
const form = new Form();
const data = { name: 'rachel' };
simpleForm.model.data = data;
let resultData;
simpleForm.resources.hooks = {
submit: ({ data }) => { resultData = data; },
};
await form.init(simpleForm.model, simpleForm.resources);
const success = await form.submit();
expect(success).toEqual(true);
expect(resultData).toEqual(data);
});
it('should wait for sync submit with fromDto', async () => {
const form = new Form();
const data = { a: 1 };
simpleForm.model.data = data;
let resultData;
simpleForm.resources.hooks = {
fromDto: ({ data }) => ({ a: data.a + 1 }),
submit: ({ data }) => { resultData = data; },
};
await form.init(simpleForm.model, simpleForm.resources);
const success = await form.submit();
expect(success).toEqual(true);
expect(resultData).toEqual({ a: 2 });
});
it('should wait for async submit', async () => {
const form = new Form();
const data = { name: 'rachel' };
simpleForm.model.data = data;
let resultData;
simpleForm.resources.hooks = {
submit: props => new Promise((resolve) => {
setTimeout(() => {
resultData = props.data;
resolve();
}, 1);
}),
};
await form.init(simpleForm.model, simpleForm.resources);
const success = await form.submit();
expect(success).toEqual(true);
expect(resultData).toEqual(data);
// verify data was not deleted after submit from the form
expect(form.data).toEqual(resultData);
});
});
describe('reset', () => {
it('resets to the initial form after form had changes', async () => {
delete commonForm.model.initializedData;
let publicForm;
const form = new Form();
await form.init(commonForm.model, commonForm.resources, (x) => { publicForm = x; });
const formAfterFirstUnit = publicForm;
// change field value
expect(form.data).toEqual({ name: 'Rachel', lastName: 'Green' });
await form.changeValue('lastName', 'Geller');
expect(form.data).toEqual({ name: 'Rachel', lastName: 'Geller' });
// change ui
expect(form.fields.lastName.component).toBeFalsy();
await form.changeUi('lastName', { component: { name: 'inputText' } });
expect(form.fields.lastName.component).toBeTruthy();
// change state
expect(form.fields.name.component.state).toEqual({});
await form.changeState('name', { test: 'mock-test' });
expect(form.fields.name.component.state).toEqual({ test: 'mock-test' });
// reset
await form.reset();
/* make sure that after init both forms:
1. form that just passed init
2. form that had init -> change stuff -> reset
check that both result the same public form after the action */
expect(publicForm).toEqual(formAfterFirstUnit);
});
it('reset persistent form - resets to the initial form after form had changes and refresh page (and went through init form)', async () => {
delete commonForm.model.initializedData;
let publicForm;
let form = new Form();
await form.init(commonForm.model, commonForm.resources, undefined, (x) => { publicForm = x; });
const formAfterFirstUnit = publicForm;
// change field value
expect(form.data).toEqual({ name: 'Rachel', lastName: 'Green' });
await form.changeValue('lastName', 'Geller');
expect(form.data).toEqual({ name: 'Rachel', lastName: 'Geller' });
// change ui
expect(form.fields.lastName.component).toBeFalsy();
await form.changeUi('lastName', { component: { name: 'inputText' } });
expect(form.fields.lastName.component).toBeTruthy();
// change state
expect(form.fields.name.component.state).toEqual({});
await form.changeState('name', { test: 'mock-test' });
expect(form.fields.name.component.state).toEqual({ test: 'mock-test' });
// mock refresh page - init the form with the persistent model
const formBeforeRefresh = publicForm;
form = new Form();
await form.init(publicForm.model, commonForm.resources, undefined, (x) => { publicForm = x; });
// verify persistent form loaded ok
expect(publicForm.model).toEqual(formBeforeRefresh.model);
// reset
await form.reset();
// verify form reset to the state it was after first init
expect(publicForm.model).toEqual(formAfterFirstUnit.model);
});
});
describe('validators', () => {
it('should make form valid on sync validator success', async () => {
const form = new Form();
await form.init(syncValidatorForm.model, syncValidatorForm.resources);
expect(form.data).toEqual({});
await form.changeValue('name', 'Moshe');
expect(form.data).toEqual({
name: 'Moshe',
});
expect(form.invalid).toBeFalsy();
});
it('should make form invalid on sync validator fails', async () => {
const form = new Form();
await form.init(syncValidatorForm.model, syncValidatorForm.resources);
expect(form.data).toEqual({});
// gal is unique name that is already taken - suppose to fail
await form.changeValue('name', 'Gal');
expect(form.data).toEqual({
name: 'Gal',
});
expect(form.invalid).toBeTruthy();
expect(form.fields.name.errors).toEqual([{
name: 'uniqueName',
message: 'Name should be unique',
}]);
});
it('should make form invalid on async validator fails', async () => {
const form = new Form();
await form.init(asyncValidatorForm.model, asyncValidatorForm.resources);
expect(form.data).toEqual({});
// gal is unique name that is already taken - suppose to fail
await form.changeValue('name', 'Gal');
expect(form.data).toEqual({
name: 'Gal',
});
expect(form.invalid).toBeTruthy();
expect(form.fields.name.errors).toEqual([{
name: 'uniqueName',
message: 'Name should be unique',
}]);
});
it('should make form invalid on async validator fails with debounce usage inside changeValue', async () => {
const form = new Form();
await form.init(asyncValidatorForm.model, asyncValidatorForm.resources);
expect(form.data).toEqual({});
// gal is unique name that is already taken - suppose to fail
const change1 = form.changeValue('name', 'Gal');
const change2 = form.changeValue('lastName', 'Havivi');
await Promise.all([change1, change2]);
expect(form.data).toEqual({
name: 'Gal',
lastName: 'Havivi',
});
expect(form.invalid).toBeTruthy();
});
it('field with exclude term and required=true, when its excluded - its should be keep required value', async () => {
const form = new Form();
simpleForm.model.data = { name: 'Custom' };
simpleForm.model.fields.lastName.required = true;
simpleForm.model.fields.lastName.dependencies = ['name'];
simpleForm.model.fields.lastName.excludeTerm = {
not: true,
name: 'equals',
args: { fieldId: 'name', value: 'Custom' }
},
await form.init(simpleForm.model, simpleForm.resources);
expect(form.fields.lastName.excluded).toBeFalsy();
expect(form.fields.lastName.required).toBeTruthy();
expect(form.fields.lastName.empty).toBeTruthy();
expect(form.fields.lastName.errors[0].name).toEqual('required');
// change value - to exclude the field
await form.changeValue('name', 'mock');
expect(form.fields.lastName.excluded).toBeTruthy();
expect(form.fields.lastName.required).toBeTruthy();
expect(form.fields.lastName.empty).toBeFalsy();
expect(form.fields.lastName.errors).toEqual([]);
// change value - to include the field
await form.changeValue('name', 'Custom');
expect(form.fields.lastName.excluded).toBeFalsy();
expect(form.fields.lastName.required).toBeTruthy();
expect(form.fields.lastName.empty).toBeTruthy();
expect(form.fields.lastName.errors[0].name).toEqual('required');
});
});
describe('dirty', () => {
it('should make form dirty', async () => {
const form = new Form();
await form.init(simpleForm.model, simpleForm.resources);
expect(form.data).toEqual({});
expect(form.dirty).toBeFalsy();
await form.changeValue('name', 'Moshe');
expect(form.data).toEqual({
name: 'Moshe',
});
expect(form.dirty).toBeTruthy();
});
it('should make form dirty and then not dirty', async () => {
const form = new Form();
simpleForm.model.data = { name: 'Assaf' };
await form.init(simpleForm.model, simpleForm.resources);
expect(form.dirty).toBeFalsy();
expect(form.data).toEqual({ name: 'Assaf' });
await form.changeValue('name', 'Moshe');
expect(form.data).toEqual({
name: 'Moshe',
});
expect(form.dirty).toBeTruthy();
await form.changeValue('name', 'Assaf');
expect(form.data).toEqual({
name: 'Assaf',
});
expect(form.dirty).toBeFalsy();
});
});
});
Example #25
Source File: index.js From strapi-molecules with MIT License | 4 votes |
PreviewProvider = ({
children,
initialData,
isCreatingEntry,
layout,
modifiedData,
slug,
canUpdate,
canCreate,
getPreviewUrlParams = noop,
getRequestUrl = getRequestUrlBackup,
}) => {
const { formatMessage } = useIntl();
const [showWarningClone, setWarningClone] = useState(false);
const [showWarningPublish, setWarningPublish] = useState(false);
const [isButtonLoading, setButtonLoading] = useState(false);
// for strapi 3.5.x
const isPreviewable = get(
layout,
'schema.options.previewable',
get(layout, ['options', 'previewable'], false),
);
const isCloneable = get(
layout,
'schema.options.cloneable',
get(layout, ['options', 'cloneable'], false),
);
const toggleWarningClone = () => setWarningClone((prevState) => !prevState);
const toggleWarningPublish = () =>
setWarningPublish((prevState) => !prevState);
const didChangeData = useMemo(() => {
return (
!isEqual(initialData, modifiedData) ||
(isCreatingEntry && !isEmpty(modifiedData))
);
}, [initialData, isCreatingEntry, modifiedData]);
const { state, pathname } = useLocation();
const { push } = useHistory();
const redirect = (id) => {
if (state && state.from) {
push({
pathname: `${state.from}/${id}`,
state: { from: state.from },
});
} else {
// for clone from create view
const [oldId, ...tmpUrl] = pathname.split('/').reverse();
const rootUrl = tmpUrl.reverse().join('/');
push({
pathname: `${rootUrl}/${id}`,
state: { from: rootUrl },
});
}
};
const previewHeaderActions = useMemo(() => {
const headerActions = [];
if (!((isCreatingEntry && canCreate) || (!isCreatingEntry && canUpdate))) {
return headerActions;
}
if (isPreviewable) {
const params = getPreviewUrlParams(initialData, modifiedData, layout);
headerActions.push({
disabled: didChangeData,
label: formatMessage({
id: getPreviewPluginTrad('containers.Edit.preview'),
}),
color: 'secondary',
onClick: async () => {
try {
const data = await request(
`/preview/preview-url/${layout.apiID}/${initialData.id}`,
{
method: 'GET',
params,
},
);
if (data.url) {
window.open(data.url, '_blank');
} else {
strapi.notification.error(
getPreviewPluginTrad('error.previewUrl.notFound'),
);
}
} catch (_e) {
strapi.notification.error(
getPreviewPluginTrad('error.previewUrl.notFound'),
);
}
},
type: 'button',
style: {
paddingLeft: 15,
paddingRight: 15,
fontWeight: 600,
},
});
}
if (isCloneable) {
if (initialData.cloneOf) {
headerActions.push({
disabled: didChangeData,
label: formatMessage({
id: getPreviewPluginTrad('containers.Edit.publish'),
}),
color: 'primary',
onClick: toggleWarningPublish,
type: 'button',
style: {
paddingLeft: 15,
paddingRight: 15,
fontWeight: 600,
},
});
} else {
headerActions.push({
disabled: didChangeData,
label: formatMessage({
id: getPreviewPluginTrad('containers.Edit.clone'),
}),
color: 'secondary',
onClick: toggleWarningClone,
type: 'button',
style: {
paddingLeft: 15,
paddingRight: 15,
fontWeight: 600,
},
});
}
}
return headerActions;
}, [
didChangeData,
formatMessage,
layout.apiID,
isPreviewable,
initialData.cloneOf,
initialData.id,
canCreate,
canUpdate,
isCreatingEntry,
]);
const handleConfirmPreviewClone = async () => {
try {
// Show the loading state
setButtonLoading(true);
const clonedPayload = await request(getRequestUrl(slug), {
method: 'POST',
body: {
...initialData,
cloneOf: initialData.id,
},
});
strapi.notification.success(getPreviewPluginTrad('success.record.clone'));
redirect(clonedPayload.id);
} catch (err) {
const errorMessage = get(
err,
'response.payload.message',
formatMessage({ id: getPreviewPluginTrad('error.record.clone') }),
);
strapi.notification.error(errorMessage);
} finally {
setButtonLoading(false);
toggleWarningClone();
}
};
const handleConfirmPreviewPublish = async () => {
try {
// Show the loading state
setButtonLoading(true);
let targetId = initialData.cloneOf.id;
const urlPart = getRequestUrl(slug);
const body = prepareToPublish({
...initialData,
id: targetId,
cloneOf: null,
});
await request(`${urlPart}/${targetId}`, {
method: 'PUT',
body,
});
await request(`${urlPart}/${initialData.id}`, {
method: 'DELETE',
});
strapi.notification.success(
getPreviewPluginTrad('success.record.publish'),
);
redirect(targetId);
} catch (err) {
const errorMessage = get(
err,
'response.payload.message',
formatMessage({ id: getPreviewPluginTrad('error.record.publish') }),
);
strapi.notification.error(errorMessage);
} finally {
setButtonLoading(false);
toggleWarningPublish();
}
};
const value = {
previewHeaderActions,
};
return (
<>
<PreviewContext.Provider value={value}>
{children}
</PreviewContext.Provider>
{isCloneable && (
<PopUpWarning
isOpen={showWarningClone}
toggleModal={toggleWarningClone}
content={{
message: getPreviewPluginTrad('popUpWarning.warning.clone'),
secondMessage: getPreviewPluginTrad(
'popUpWarning.warning.clone-question',
),
}}
popUpWarningType="info"
onConfirm={handleConfirmPreviewClone}
isConfirmButtonLoading={isButtonLoading}
/>
)}
{isCloneable && (
<PopUpWarning
isOpen={showWarningPublish}
toggleModal={toggleWarningPublish}
content={{
message: getPreviewPluginTrad('popUpWarning.warning.publish'),
secondMessage: getPreviewPluginTrad(
'popUpWarning.warning.publish-question',
),
}}
popUpWarningType="info"
onConfirm={handleConfirmPreviewPublish}
isConfirmButtonLoading={isButtonLoading}
/>
)}
</>
);
}