如何以编程方式填写在 React 应用程序中使用 Formik 构建的表单,并确保表单的填写方式与手动填写表单的方式相同?
我遇到的一个问题是该页面正在使用 React 的生产版本,并且其组件没有暴露给 DOM(例如,Formik 上下文对象)。我已经确定了可以在 React Developer Tools 扩展中查看的属性列表,但我担心如果我尝试自动化页面,这些属性可能无法正确触发或填充。
我正在考虑的属性列表包括
handleChange
、handleBlur
、touched
、validateForm
、validateField
、isSubmitting
、submitCount
和嵌套对象。该表单包含嵌套对象,例如城市或机构 ID,因此我需要确保在设置这些字段的值之前使用正确的值正确填充这些字段。此外,我不确定是否有任何表单字段具有异步更新或副作用。如果有任何异步更新,我需要确保在提交表单之前正确触发并解决这些更新。
出于某些原因,我不想使用 BeautifulSoup 或 Selenium。我尝试使用下面提供的代码,但未能正确填写表格。
(function () {
const inputXPath = '/html/body/div/div/div[2]/div/form/div/div/div[4]/div/div/div[1]/div/input';
const valueToSet = 'John';
const inputName = 'firstName';
const touchedValue = true;
const inputElement = document.evaluate(inputXPath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
if (inputElement) {
const nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, 'value').set;
const focusEvent = new Event('focus', { bubbles: true });
const inputEvent = new Event('input', { bubbles: true });
const blurEvent = new Event('blur', { bubbles: true });
const changeEvent = new Event('change', { bubbles: true });
const formikContextXPath = '/html/body/div/div/div[2]/div/form';
const formikContext = document.evaluate(formikContextXPath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
if (formikContext && formikContext.hasAttribute('data-formik-context')) {
const setTouched = (name, value) => {
formikContext.formik.setTouched({ [name]: value });
};
inputElement.dispatchEvent(focusEvent);
nativeInputValueSetter.call(inputElement, valueToSet);
inputElement.dispatchEvent(inputEvent);
inputElement.dispatchEvent(blurEvent);
inputElement.dispatchEvent(changeEvent);
setTouched(inputName, touchedValue);
console.log(`success`);
} else {
console.error('Cannot find the Formik context object');
}
} else {
console.error(`Cannot find the XPath`);
}
})();
您可以使用该函数以编程方式更改输入字段的值。
function fillInputValue(input, value) => {
let nativeInputValueSetter = Object.getOwnPropertyDescriptor(
window.HTMLInputElement.prototype,
"value"
).set;
nativeInputValueSetter.call(input, value);
let inputEvent = new Event("input", { bubbles: true });
input.dispatchEvent(inputEvent);
};