html 在使用ARIA和React设计的网站上自动执行任务(使用Puppeteer)

ctzwtxfj  于 2023-04-10  发布在  React
关注(0)|答案(1)|浏览(145)
(function(){

  var textbox = document.querySelector('.b-combobox__input'),
    listbox = document.querySelector('#characters-list'),
    options = document.querySelectorAll('.b-listbox__item'),
    suggest = initData(options);

  initEvents();

  function initEvents () {
    // Textbox events
    textbox.addEventListener('focus', function (e) {
      textbox.setAttribute('aria-expanded', true);
      listbox.setAttribute('aria-hidden', false);
    });
    textbox.addEventListener('keyup', function (e) {
      var userInput = textbox.value.substr(0, textbox.selectionStart),
          re = new RegExp("^" + userInput),
          isSuggestFound = false;

      if (textbox.value === '') {
        for (var k = 0; k < options.length; k++) {
          options[k].setAttribute('aria-hidden', false);
        }
      } else {
        for (var i = 0; i < suggest.length; i++) {
          options[i].setAttribute('aria-hidden', true);
          options[i].setAttribute('aria-selected', false);

          for (var j = 0; j < suggest[i].length; j++) {
            if (re.test(suggest[i][j])) {
              options[i].setAttribute('aria-hidden', false);

              if (!isSuggestFound) {
                textbox.value = suggest[i][j];
                textbox.setSelectionRange(userInput.length, suggest[i][j].length);
                options[i].setAttribute('aria-selected', true);
                isSuggestFound = true;
              }
            }
          }
        }
      }
    });

    // Listbox events
    for (var i = 0; i < options.length; i++) {
      options[i].addEventListener('click', function (e) {
        textbox.setAttribute('aria-expanded', false);
        listbox.setAttribute('aria-hidden', true);

        textbox.value = this.querySelector('.data_nickname').textContent;
      });
    }

  }

  function initData (options) {
    var data = [];

    for (var i = 0; i < options.length; i++) {
      data.push([
        options[i].querySelector('.data_nickname').textContent,
        options[i].querySelector('.data_realname').textContent,
        options[i].querySelector('.data_group').textContent,
        options[i].querySelector('.data_skill').textContent
      ]);
    }

    return data;
  }

})();
body {
  padding: 32px;
}

.b-combobox {
  position: relative;
  font: 400 14px/16px sans-serif;
}
.b-combobox__input {
  width: 300px;
}

.b-listbox {
  position: absolute;
  left: 100px;
  top: 10px;
  width: 300px;
  list-style: none;
  border: 1px solid #aaa;
  padding: 2px 2px 0;
}
.b-listbox[aria-hidden=true] {
  display: none;
}
.b-listbox[aria-hidden=false] {
  display: block;
}

.b-listbox__item {
  min-height: 64px;
  cursor: pointer;
  margin: 0 0 2px;
}
.b-listbox__item[aria-hidden=true] {
  display: none;
}
.b-listbox__item[aria-hidden=false] {
  display: block;
}
.b-listbox__item:hover, .b-listbox__item:focus {
  background: #369;
  color: #FFF;
}

.b-vcard__photo {
  float: left;
  padding: 0 4px 0 0;
}
.b-vcard__name {
  font: 600 16px/20px sans-serif;
  margin: 0;
}
.b-vcard__info {
  list-style: none;
  font: 400 10px/14px sans-serif;
  color: #666;
}
<div class="b-combobox">
  <label>
    <span class="b-combobox__label">Choose profile:</span>
    <input type="text" class="b-combobox__input"
      role="combobox"
      aria-expanded="false"
      aria-autocomplete="list"
      aria-owns="characters-list"
    />
  </label>
  <ul role="listbox" aria-hidden="true" class="b-listbox" id="characters-list">
    <li role="option" aria-selected="true" tabindex="0" class="b-listbox__item">
      <div class="b-vcard">
        <img class="b-vcard__photo" src="http://nechunaev.com/tutu/ARIA/Batman.jpg" />
        <h1 class="b-vcard__name data data_nickname">Batman</h1>
        <ul class="b-vcard__info">
          <li class="b-vcard__info__item">
            <strong>Real name:</strong>
            <span class="data data_realname">Bruce Wayne</span>
          </li>
          <li class="b-vcard__info__item">
            <strong>Affiliations:</strong>
            <span class="data data_group">Justice League</span>
          </li>
          <li class="b-vcard__info__item">
            <strong>Abilities:</strong>
            <span class="data data_skill">Master martial artist</span>
          </li>
        </ul>
      </div>
    </li>
    <li role="option" tabindex="0" class="b-listbox__item">
      <div class="b-vcard">
        <img class="b-vcard__photo" src="http://nechunaev.com/tutu/ARIA/Joker.jpg" />
        <h1 class="b-vcard__name data data_nickname">Joker</h1>
        <ul class="b-vcard__info">
          <li class="b-vcard__info__item">
            <strong>Real name:</strong>
            <span class="data data_realname">Unknown</span>
          </li>
          <li class="b-vcard__info__item">
            <strong>Affiliations:</strong>
            <span class="data data_group">Injustice League</span>
          </li>
          <li class="b-vcard__info__item">
            <strong>Abilities:</strong>
            <span class="data data_skill">Skilled chemist</span>
          </li>
        </ul>
      </div>
    </li>
    <li role="option" tabindex="0" class="b-listbox__item">
      <div class="b-vcard">
        <img class="b-vcard__photo" src="http://nechunaev.com/tutu/ARIA/Penguin.jpg" />
        <h1 class="b-vcard__name data data_nickname">Penguin</h1>
        <ul class="b-vcard__info">
          <li class="b-vcard__info__item">
            <strong>Real name:</strong>
            <span class="data data_realname">Oswald Chesterfield Cobblepot</span>
          </li>
          <li class="b-vcard__info__item">
            <strong>Affiliations:</strong>
            <span class="data data_group">Suicide Squad</span>
          </li>
          <li class="b-vcard__info__item">
            <strong>Abilities:</strong>
            <span class="data data_skill">Expert in judo</span>
          </li>
        </ul>
      </div>
    </li>
  </ul>
</div>

我有这个组合框在一个网页,这是使用ARIA和React设计的。

<div class="Select-control">
  <div class="Select-multi-value-wrapper" id="react-select-4--value">
    <div class="Select-placeholder">Choose category</div>
    <div class="Select-input" style="display: inline-block;">
      <input id="category-select" aria-activedescendant="react-select-4--value" aria-expanded="false" aria-haspopup="false" aria-owns="" role="combobox" value="" style="box-sizing: content-box; width: 5px;">
      <div style="position: absolute; top: 0px; left: 0px; visibility: hidden; height: 0px; overflow: scroll; white-space: pre; font-size: 16px; font-family: &quot;Source Sans Pro&quot;, Helvetica, Arial, sans-serif; font-weight: 400; font-style: normal; letter-spacing: normal; text-transform: none;"></div>
    </div>
  </div>
  <span class="Select-arrow-zone">
    <span class="Select-arrow"></span>
  </span>
</div>

改变组合框中的值的理想方法是什么?我使用Puppeteer来自动化这个过程。
我尝试通过ID找到元素,并使用Puppeteer中的click功能,尝试选择所需的项目,但它并不像预期的那样工作。我尝试在下面的情况下复制它,尽管它并不理想。区别在于组合框的值是使用react设置的。
这就是我正在做的

const category = await page.$x('//*[@id="react-select-4--value"]/div[1]')

await category[0].click()

点击组合框。我注意到一个新元素是在列表的页面中通过编程创建的。
所以我试着点击元素

const character = await page.$x('//*[@id="react-select-4--option-6"]') 
await character[0].click()

这种方法。
我得到的错误如下所示
未捕获错误错误:评估失败:TypeError:无法读取undefined的属性(阅读'click')

ej83mcc0

ej83mcc01#

从给定的代码中,你试图选择的是错误的,所以错误。这里有两种方法可以做到这一点。
使用xpath:

let input = await page.$x("//input[contains(@class,'combobox')]")   
await input[0].click(); 

let selectables = await page.$x('//*[@id="characters-list"]/li');
await selectables[1].click();  // selects Joker

使用选择器:

await page.click("input[class*=combobox]"); 
let selectables = await page.$$('*[id=characters-list] > li');
await selectables[2].click(); // selects Penguin

注意事项:

  • selectables -是下拉列表中三个最上面的li标签中的一个数组,如图所示。因此,循环它以根据其顺序选择组合框中的任何内容。
  • 您也可以在单击输入后放置.waitForSelector或延迟。

相关问题