PhantomJS; клацніть елемент


81

Як клацнути елемент у PhantomJS?

page.evaluate(function() {
    document.getElementById('idButtonSpan').click();  
});

Це призводить до помилки "undefined is not a function ..."

Якщо я замість цього

 return document.getElementById('idButtonSpan');

а потім роздрукуйте його,

потім він друкує [об'єкт об'єкта], отже елемент існує.

Елемент діє як кнопка, але насправді це просто елемент span, а не вхід для подання.

Мені вдалося натиснути цю кнопку, щоб працювати з Casper, але Casper мав інші обмеження, тому я повернувся до PhantomJS.


28
Час прийняти відповідь.

Є 3 відповіді, які використовують функцію "dispatchEvent", 2 - "sendEvent", одна - практично марна, та одна, яка повинна бути коментарем.
redbeam_

Не забудьте знак # ...
GracefulCode

Чому ще ніхто не вказав, що click()взагалі не існує в DOM API, ви, мабуть, бачили це в jQuery чи якомусь подібному lib?
YemSalat

Через 4 роки: Відповідь прийнято! Я пішов від PhantomJS, тому не зміг перевірити відповідь. Але я прийму, що 58 голосів проти - правильні :) @torazaburo
user984003

Відповіді:


68

.click()не є стандартним. Вам потрібно створити подію та відправити її:

function click(el){
    var ev = document.createEvent("MouseEvent");
    ev.initMouseEvent(
        "click",
        true /* bubble */, true /* cancelable */,
        window, null,
        0, 0, 0, 0, /* coordinates */
        false, false, false, false, /* modifier keys */
        0 /*left*/, null
    );
    el.dispatchEvent(ev);
}

9
Обгортання elз JQuery дає вам це defn клацання. Це буде працювати у вашому браузері та у Phantom. $(el).click()
Bluu

3
omg сльози радості, після майже 12 годин безперервної боротьби з цим! нюхати нюхати!
user1323136

1
Мені теж вдалось добре, але слід пам’ятати, що не слід виходити з PhantomJS занадто рано, до завершення обробки. Мені потрібен був короткий сценарій, щоб просто натиснути одну кнопку і вийти. Це не спрацювало б для мене, доки я не зателефонував phantom.exit () з сторінки page.onLoadFinished = function () {...};
gregko

document.querySelector (елемент) .click () чудово працює для мене.
GracefulCode

Для роботи зі спеціальними елементами управління мені довелося зробити більш складне рішення з 3 подіями: функція triggerMouseEvent (elm, eventType) {var ev = document.createEvent ("MouseEvent"); ev.initMouseEvent (eventType, true / * міхур /, true / cancellable /, window, null, 0, 0, 0, 0, / координати / false, false, false, false, / модифікатор ключі * / 0 / * left * /, нуль ); elm.dispatchEvent (ev); } клацніть функцію (в'яз) {triggerMouseEvent (в'яз, 'mousedown'); triggerMouseEvent (elm, 'mouseup'); triggerMouseEvent (в'яз, 'клацніть'); }
a-bobkov

34

В якості альтернативи відповіді @ torazaburo, ви можете HTMLElement.prototype.clickзаглушити під час запуску у PhantomJS. Наприклад, ми використовуємо PhantomJS + QUnit для запуску наших тестів, і у qunit-config.jsнас є щось подібне:

if (window._phantom) {
  // Patch since PhantomJS does not implement click() on HTMLElement. In some 
  // cases we need to execute the native click on an element. However, jQuery's 
  // $.fn.click() does not dispatch to the native function on <a> elements, so we
  // can't use it in our implementations: $el[0].click() to correctly dispatch.
  if (!HTMLElement.prototype.click) {
    HTMLElement.prototype.click = function() {
      var ev = document.createEvent('MouseEvent');
      ev.initMouseEvent(
          'click',
          /*bubble*/true, /*cancelable*/true,
          window, null,
          0, 0, 0, 0, /*coordinates*/
          false, false, false, false, /*modifier keys*/
          0/*button=left*/, null
      );
      this.dispatchEvent(ev);
    };
  }
}

1
Зверніть увагу, що я запускаю Karma 0.12.17 з PhantomJs 1.9.7-14. Немає window._phantomоб’єкта, тому я просто видалив цю умову, і вона спрацювала, як очікувалося.
BradGreens

Цікаво, чи повинна функція приймати параметри для того, щоб встановити різні координати для MouseEvent
ffflabs 02

16

Це не красиво, але я використовував це, щоб дозволити мені використовувати jQuery для виділення:

var rect = page.evaluate(function() {
    return $('a.whatever')[0].getBoundingClientRect();
});
page.sendEvent('click', rect.left + rect.width / 2, rect.top + rect.height / 2);

але ви завжди можете замінити $(s)[0] з , document.querySelector(s)якщо не з допомогою JQuery.

(Він покладається на те, що елемент має на увазі погляд, тобто ваш viewportSize.height досить великий).


2
Перепробував усі можливі підходи, і це єдиний варіант, який спрацював у мене при спробі натиснути tr.
Кай

Працював на phantomjs 1.9.0 та з елементом <a>
redbeam_

1
найкраще рішення imo,+1
Flash Thunder

10

Сподіваюся, наступний метод буде корисним. У мене це працювало у версії 1.9

page.evaluate(function(){
    var a = document.getElementById("spr-sign-in-btn-standard");
    var e = document.createEvent('MouseEvents');
    e.initMouseEvent('click', true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
    a.dispatchEvent(e);
    waitforload = true;
});

Це спрацювало для мене. Сподіваюся, це буде корисним і для інших


@Jobins Джон що таке waitforload = true?
Кадір Хуссейн,

1
@QadirHussain Його фактично чекає повного завантаження сторінки. Це майже як налаштування певного часу для завантаження сторінки.
Jobins John

6

Коли 1.9.2це спрацювало для мене, спрацьовували обробники кліків:

var a = page.evaluate(function() {
    return document.querySelector('a.open');
});

page.sendEvent('click', a.offsetLeft, a.offsetTop);

Це не на всіх елементах. Наприклад, <a> його немає. На кнопках це там.
unludo

6

використовуйте простий JavaScript evaluate, приблизно так:

page.evaluate(function() {
    document.getElementById('yourId').click();
});

1
Насправді це зараз правильне рішення зараз із PhantomJS 2.x
BlaM

3

Я ніколи не міг натиснути елемент прямо. Натомість я подивився html, щоб знайти, яку функцію викликали за допомогою onclick, а потім викликав цю функцію.


як ви могли знайти функцію і як її викликати, якщо вона була приєднана через addEventListener?
Suo6613

2

Document.querySelector (елемент) .click () працює під час використання Phantomjs 2.0

click: function (selector, options, callback) {
    var self = this;
    var deferred = Q.defer();
    options = options || {timeout:1000}; 
    setTimeout(function () { 
        self.page.evaluate(function(targetSelector) {
            $(document).ready(function() {
                document.querySelector(targetSelector).click();
            }) ;
        }, function () {
                deferred.resolve();
        }, selector);
    }, options.timeout);
    return deferred.promise.nodeify(callback);
},

2

Подвійні клацання також можливі з PhantomJS.

Рекомендовано

Це взято з відповіді на stovroz і запускає уродженець dblclickвключаючи mousedown, mouseupі clickподія (два з кожних).

var rect = page.evaluate(function(selector){
    return document.querySelector(selector).getBoundingClientRect();
}, selector);
page.sendEvent('doubleclick', rect.left + rect.width / 2, rect.top + rect.height / 2);

Інші способи

Наступні два способи лише ініціюють dblclickподію, але не інші події, які повинні їй передувати.

Взято з цієї відповіді на torazaburo :

page.evaluate(function(selector){
    var el = document.querySelector(sel);
    var ev = document.createEvent("MouseEvent");
    ev.initMouseEvent(
        'dblclick',
        true /* bubble */, true /* cancelable */,
        window, null,
        0, 0, 0, 0, /* coordinates */
        false, false, false, false, /* modifier keys */
        0 /*left*/, null
    );
    el.dispatchEvent(ev);
}, selector);

Взято з цієї відповіді на Jobins Іоанна :

page.evaluate(function(selector){
    var el = document.querySelector(sel);
    var e = document.createEvent('MouseEvents');
    e.initMouseEvent('dblclick', true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
    el.dispatchEvent(e);
}, selector);

Повний сценарій тесту


2

Найпростіший спосіб - використовувати jQuery.

page.evaluate(function() {
  page.includeJs("your_jquery_file.js", function() {
    page.evaluate(function() {
      $('button[data-control-name="see_more"]').click();
    });
  });
});

0

Для тих, хто використовує JQuery, користувальницький інтерфейс JQuery створив утиліту для імітації таких: jquery-simulate . Я використовую це у PhantomJS та Chrome

$ele..simulate( "click" );
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.