通过 Javascript 填充 ReactJS HTML 表单

IT技术 javascript jquery reactjs
2021-05-20 07:03:56

我正在开发一个应用程序,在该应用程序中,我可以在打开 3rd 方网站后在浏览器上下文中运行我自己的 Javascript。作为一个建立在 reactjs 上并有登录表单的示例网站,您可以参考这个链接。

我正在尝试在 reactjs 生成的表单中填写用户名和密码。但是,我无法完全实现它。

我能够在用户名/密码字段和 reactjs 内部设置值的最接近的代码库是:

function setNativeValue(element, value) {
    element.focus();
    element.click();
    element.value = value;
    element.defaultValue = value;
    let tracker = element._valueTracker;
    if (tracker) {
        tracker.setValue(lastValue);
    }
    let inputEvent = new Event("input", { target: element, bubbles: true });
    inputEvent.simulated = true;
    element.dispatchEvent(inputEvent);
}

document.getElementsByClassName("sc-qamJO")[0].click(); // login top button
setTimeout(function () {
    setNativeValue(document.getElementsByClassName("sc-AxheI")[1], "username"); // username
    setNativeValue(document.getElementsByClassName("sc-AxheI")[2], "password"); // password

    setTimeout(function () {
        document.getElementsByClassName("sc-fzpans")[3].click(); // login button
    }, 1000);
}, 1000);

问题: 但是,我无法自动提交 reactjs 表单。它抛出一个错误This field is required*错误,即使我根据我的理解和谷歌搜索建议正确地完成了所有事情。我无法满足现场验证器的要求。

我尝试了很多方法来自动提交表单。他们之中有一些是:

  1. 遵循此 stackoverflow 问题中提供的所有方法
  2. 获取 reactjs 实例然后尝试 setState。在这种情况下,.setState is not a function错误来了
  3. 这个github 问题评论是我目前正在关注以解决我的问题
  4. 我也尝试过一系列事件,比如mouseenter mousedown……keydown keypress keyup和其他人,类似于这个人正在做的事情

你能告诉我,我该怎么做才能满足登录表单中可用的 reactjs 验证器,以便使用 javascript 或 jQuery 自动在网站上提交表单。

注 - 示例网站不包含 jQuery,因此纯 Javascript 代码也可用于理解。

我使用 Chromium 作为浏览器。

1个回答

基于这个setState例子,我可以用这个提交登录表单:

const openLoginModal = () => document.getElementsByClassName('sc-qamJO')[0].click()
const submitLoginForm = () => document.getElementsByClassName('sc-fzpans')[3].click()

const getCompFiber = fiber => {
    let parentFiber = fiber.return

    while (parentFiber && typeof parentFiber.type === 'string') {
        parentFiber = parentFiber.return
    }

    return parentFiber
}

const getLoginForm = () => {
    const dom = document.getElementsByClassName('sc-AxheI')[1]
    const key = Object.keys(dom).find(key => key.startsWith('__reactInternalInstance$'))
    const domFiber = dom[key]

    if (domFiber == null) return null

    let compFiber = getCompFiber(domFiber)

    while (compFiber) {
        compFiber = getCompFiber(compFiber);

        if (compFiber && compFiber.stateNode && compFiber.stateNode.props && compFiber.stateNode.props.loginForm) {
            return compFiber
        }
    }
}

const login = (username, password) => {
    openLoginModal()

    setTimeout(() => {
        const loginForm = getLoginForm()

        loginForm.stateNode.props.loginForm.password = {
            value: password,
            error: false,
            errorMessage: 'This field is required',
            type: 'password'
        }

        loginForm.stateNode.props.loginForm.username = {
            value: username,
            error: false,
            errorMessage: 'This field is required'
        }

        submitLoginForm()
    }, 1000)
}

login('myUser', 'myPassword')

登录失败,出现 500 错误(这很奇怪),但我检查过,当尝试使用无效的用户名/密码手动登录时,这是相同的错误代码,所以我想它应该使用正确的凭据。