在PHP中使用Mink/Zombie检查JavaScript AJAX加载的资源? [英] Checking JavaScript AJAX loaded resources with Mink/Zombie in PHP?

查看:87
本文介绍了在PHP中使用Mink/Zombie检查JavaScript AJAX加载的资源?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试测试一个页面,否则该页面将使用大量异步加载的JavaScript资源以及使用Mink和Zombie的PHP脚本.不幸的是,此过程失败(留下了挂起过程).我终于设法在一个最小的示例上模拟了此错误,我将在此处发布.

第一页-要测试的页面-基本上是一个 <?php if (array_key_exists("QUERY_STRING", $_SERVER)) { if ($_SERVER["QUERY_STRING"] == "getone") { echo "<!doctype html> <html> <head> <script src='test_JSload.php?gettwo'></script> </head> </html> "; exit; } if ($_SERVER["QUERY_STRING"] == "gettwo") { header('Content-Type: application/javascript'); echo " function person(firstName) { this.firstName = firstName; this.changeName = function (name) { this.firstName = name; }; } "; exit; } } ?> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <style type="text/css"> .my_btn { background-color:yellow; } </style> <script src="http://code.jquery.com/jquery-1.12.4.min.js"></script> <script type="text/javascript"> var thishref = window.location.href.slice(0, window.location.href.indexOf('?')+1); var qstr = window.location.href.slice(window.location.href.indexOf('?')+1); function OnGetdata(inbtn) { console.log("OnGetdata; loading ?getone via AJAX call"); //~ $.ajax(thishref + "?getone", { // works var ptest = {}; // init as empty object console.log(" ptest pre ajax is ", ptest); $.ajax({url: thishref + "?getone", async: true, // still "Synchronous XMLHttpRequest on the main thread is deprecated", because we load a script; https://stackoverflow.com/q/24639335 success: function(data) { console.log("got getone data "); //, data); $("#dataholder").html(data); ptest = new person("AHA"); console.log(" ptest post getone is ", ptest); }, error: function(xhr, ajaxOptions, thrownError) { console.log("getone error " + thishref + " : " + xhr.status + " / " + thrownError); } }); ptest.changeName("Somename"); console.log(" ptest post ajax is ", ptest); } ondocready = function() { $("#getdatabtn").click(function(){ OnGetdata(this); }); } $(document).ready(ondocready); </script> </head> <body> <h1>Hello World!</h1> <button type="button" id="getdatabtn" class="my_btn">Get Data!</button> <div id="dataholder"></div> </body> </html>

因此,当页面首次加载时,不会执行任何操作;按下按钮后:首先,通过AJAX调用返回一些包含<script>的HTML内容(这是?getone);然后该脚本本身会从?gettwo自动"加载.我知道这可能不是正确的选择(请参阅),但是我要测试的实际页面中有类似的组织.

要运行此页面,您只需拥有命令行php版本> 5.3,并在文件的同一目录中运行:

 php -S localhost:8080
 

...,然后在浏览器中转到http://127.0.0.1:8080/test_JSload.php.

无论如何,一旦我单击按钮,Firefox控制台就会显示:

 OnGetdata; loading ?getone via AJAX call      test_JSload.php:13:3
 ptest pre ajax is  Object {  }               test_JSload.php:16:3
TypeError: ptest.changeName is not a function test_JSload.php:31:3
got getone data                               test_JSload.php:21:7
Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help http://xhr.spec.whatwg.org/ jquery-1.12.4.min.js:4:26272
 ptest post getone is  Object { firstName: "AHA", changeName: person/this.changeName(name) } test_JSload.php:24:7
 

顺便说一句,错误"TypeError: ... is not a function"与我从Mink/Zombie得到的和我要检查的实际页面完全相同;尽管我不认为页面本身在独立运行时会显示该错误,但在这里却是如此.

现在,让我们尝试使用Mink检查此页面(安装为 nodejs无法使用PHP Mink找到模块'zombie'):

test_JSload_mink.php

 <?php
$nodeModPath = "/home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules";

# composer autoload:
require_once __DIR__ . '/vendor/autoload.php';


$zsrv = new \Behat\Mink\Driver\NodeJS\Server\ZombieServer();
$zsrv->setNodeModulesPath($nodeModPath . "/"); # needs to end with a trailing '/'
$driver = new \Behat\Mink\Driver\ZombieDriver( $zsrv );
$session = new \Behat\Mink\Session($driver);

// start the session
$session->start();

$session->visit("http://127.0.0.1:8080/test_JSload.php");
$session->wait(20000, '(browser.statusCode > 0)'); ### THIS makes things work?!
$statcode = $session->getStatusCode();
echo "  current URL: " . $session->getCurrentUrl() ."\n";
echo "  status code: " . $statcode ."\n";

$page = $session->getPage();
$el_button = $page->findButton('getdatabtn');
echo "Check: el_b " . gettype($el_button) . "\n";

echo "  pressing/clicking the button\n";
$el_button->click();

echo "Page URL after click: ". $session->getCurrentUrl() . "\n";
?>
 

从另一个终端外壳运行该命令(虽然第一个仍然运行为test_JSload.php提供服务的php服务器进程),结果如下:

$ php test_JSload_mink.php
  current URL: http://127.0.0.1:8080/test_JSload.php
  status code: 200
Check: el_b object
  pressing/clicking the button
PHP Fatal error:  Uncaught exception 'Behat\Mink\Exception\DriverException' with message 'Error while processing event 'click': "ReferenceError: person is not defined\n    at Object.OnGetdata.$.ajax.success (http://127.0.0.1:8080/test_JSload.php:script:16:19)\n    at i (http://code.jquery.com/jquery-1.12.4.min.js:2:27449)\n    at Object.j.fireWith [as resolveWith] (http://code.jquery.com/jquery-1.12.4.min.js:2:28213)\n    at y (http://code.jquery.com/jquery-1.12.4.min.js:4:22721)\n    at XMLHttpRequest.c (http://code.jquery.com/jquery-1.12.4.min.js:4:26925)\n    at callListeners (/home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules/zombie/node_modules/jsdom/lib/jsdom/events/EventTarget.js:170:34)\n    at dispatchPhase (/home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules/zombie/node_modules/jsdom/lib/jsdom/events/EventTarget.js:159:7)\n    at XMLHttpRequest.EventTarget.dispatchEvent (/home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules/zombie/node_modules/jsdom/lib/jsdom/events/EventTarget.js:115: in /media/Data1/work/bbs/gits/econdk-vis-01_git/test/test_php_mink/vendor/behat/mink-zombie-driver/src/ZombieDriver.php on line 880

现在,这里来自Mink/Zombie的错误是'ReferenceError: person is not defined',而在我实际的页面检查中,它是'TypeError: ... is not a function'-但我认为它们足够相似.

问题是-我该如何处理这样的错误?

例如,这里已经使用了'$session->wait(20000, '(browser.statusCode > 0)');',它检查JavaScript中的browser.statusCode;我知道这里还有:

$returnstring = $session->evaluateScript('document.readyState');

...也可以从JavaScript询问数据.因此,原则上,类似这样的东西可以用来等待"直到加载给定的资源.

但是这里的问题是暴露问题的ptest变量在函数OnGetdata() local 范围内,因此我不知道如何构造一个语句会从PHP检查"它-我希望只能访问诸如browserdocument之类的全局变量.

那么,现在有没有人可以让Mink/Zombie PHP脚本等待"进行这样的嵌套" JavaScript加载-这样,我就可以在虚拟点击后完成页面的加载,而不会出现错误?


设法将这个问题减少为一个简单的Zombie JavaScript文件:

test_JSload_zombie.js

 // call with:
// DEBUG=zombie NODE_PATH=/home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules node test_JSload_zombie.js

var Browser = require("zombie");

browser = new Browser({waitDuration: 30*1000, runScripts: true});

browser.visit("http://127.0.0.1:8080/test_JSload.php", function () {
  browser.pressButton('Get Data!'); //, done);
  console.log(' person, post-click pre-wait:', browser.evaluate('typeof(person)'), browser.evaluate('$("script").length') ); // $("script").length is 2
  var checkCondition = function () {
    var ret =browser.evaluate("(typeof(person) != 'undefined')");
    console.log("ret is " + ret);
    return ret;
  };
  browser.wait({function: checkCondition, duration: 100000}, function() {
    console.log(' person, post-wait:', browser.evaluate('typeof(person)'), browser.evaluate('$("script").length')); // $("script").length is 3
    /// browser.dump(); // not too much info
  });
});
 

运行此文件,记录完全相同的错误:

   zombie Opened window http://127.0.0.1:8080/test_JSload.php  +0ms
  zombie GET http://127.0.0.1:8080/test_JSload.php => 200 +198ms
  zombie Loaded document http://127.0.0.1:8080/test_JSload.php +233ms
  zombie GET http://code.jquery.com/jquery-1.12.4.min.js => 200 +207ms
  zombie Event loop is empty +476ms
OnGetdata; loading ?getone via AJAX call
 ptest pre ajax is  Object {}
  zombie XHR readystatechange http://127.0.0.1:8080/test_JSload.php?getone +54ms
  zombie XHR loadstart http://127.0.0.1:8080/test_JSload.php?getone +3ms
  zombie TypeError: ptest.changeName is not a function
    at OnGetdata (http://127.0.0.1:8080/test_JSload.php:script:24:9)
    at null.<anonymous> (http://127.0.0.1:8080/test_JSload.php:script:30:5)
    at n.event.dispatch (http://code.jquery.com/jquery-1.12.4.min.js:3:12444)
    at r.handle (http://code.jquery.com/jquery-1.12.4.min.js:3:9173)
    at callListeners (/home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules/zombie/node_modules/jsdom/lib/jsdom/events/EventTarget.js:170:34)
    at dispatchPhase (/home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules/zombie/node_modules/jsdom/lib/jsdom/events/EventTarget.js:159:7)
    at EventTarget.dispatchEvent (/home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules/zombie/node_modules/jsdom/lib/jsdom/events/EventTarget.js:115:3)
    at DOM.EventTarget.dispatchEvent (/home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules/zombie/lib/dom/jsdom_patches.js:155:31)
    at define.proto.dispatchEvent (/home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules/zombie/node_modules/jsdom/lib/jsdom/level2/html.js:365:55)
    at Browser.fire (/home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules/zombie/lib/index.js:424:14)
    in http://127.0.0.1:8080/test_JSload.php +24ms
 person, post-click pre-wait: undefined 2
ret is false
  zombie GET http://127.0.0.1:8080/test_JSload.php?getone => 200 +36ms
  zombie XHR readystatechange http://127.0.0.1:8080/test_JSload.php?getone +7ms
  zombie XHR readystatechange http://127.0.0.1:8080/test_JSload.php?getone +0ms
ret is false
got getone data 
  zombie ReferenceError: person is not defined
    at Object.OnGetdata.$.ajax.success (http://127.0.0.1:8080/test_JSload.php:script:16:19)
    at i (http://code.jquery.com/jquery-1.12.4.min.js:2:27449)
    at Object.j.fireWith [as resolveWith] (http://code.jquery.com/jquery-1.12.4.min.js:2:28213)
    at y (http://code.jquery.com/jquery-1.12.4.min.js:4:22721)
    at XMLHttpRequest.c (http://code.jquery.com/jquery-1.12.4.min.js:4:26925)
    at callListeners (/home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules/zombie/node_modules/jsdom/lib/jsdom/events/EventTarget.js:170:34)
    at dispatchPhase (/home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules/zombie/node_modules/jsdom/lib/jsdom/events/EventTarget.js:159:7)
    at XMLHttpRequest.EventTarget.dispatchEvent (/home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules/zombie/node_modules/jsdom/lib/jsdom/events/EventTarget.js:115:3)
    at XMLHttpRequest.DOM.EventTarget.dispatchEvent (/home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules/zombie/lib/dom/jsdom_patches.js:155:31)
    at XMLHttpRequest._fire (/home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules/zombie/lib/xhr.js:242:12)
    in http://127.0.0.1:8080/test_JSload.php +73ms
 person, post-wait: undefined 3
  zombie XHR readystatechange http://127.0.0.1:8080/test_JSload.php?getone +4ms
  zombie XHR progress http://127.0.0.1:8080/test_JSload.php?getone +0ms
  zombie XHR load http://127.0.0.1:8080/test_JSload.php?getone +1ms
  zombie XHR loadend http://127.0.0.1:8080/test_JSload.php?getone +0ms
  zombie GET http://127.0.0.1:8080/test_JSload.php?gettwo => 200 +18ms
 

所以,我想如果这在Zombie/JS级别上得到解决,那么最终可以在Mink/PHP级别上解决...但是请注意,对?gettwo的调用仅在错误被排除之后才发生.发出(并且是日志中的最后一个条目)-似乎Zombie根本无法等待同步请求.

解决方案

也尝试一下:

$session->wait(50000, "document.readyState === 'complete'");

或尝试其他等待条件,例如在等待对象时执行do,另外请不要因为如果未找到/加载元素,则findButton可能会返回null,因此您可以尝试执行do-while几秒钟,并且if按钮!== null,然后断开/返回按钮.

我总是使用等待返回对象或引发异常并单击的元素,例如:

$this->waitForElement('selector')->click();

如果您需要一个waitForElement示例,请告诉我.

以下是一些ajax条件,您可以尝试 how-制作要等待的ajax呼叫

I'm trying to test a page, which otherwise uses massive asynchronously loaded JavaScript resources, with PHP script that uses Mink and Zombie. Unfortunately, this process fails (leaving behind hanging processes). I have managed finally to simulate this error on a minimal example, which I'll post here.

The first page - the page to be tested - is basically a self-contained file, that simulates the AJAX calls by calling itself:

test_JSload.php

<?php
if (array_key_exists("QUERY_STRING", $_SERVER)) {
  if ($_SERVER["QUERY_STRING"] == "getone") {
    echo "<!doctype html>
  <html>
  <head>
  <script src='test_JSload.php?gettwo'></script>
  </head>
  </html>
  ";
    exit;
  }

  if ($_SERVER["QUERY_STRING"] == "gettwo") {
    header('Content-Type: application/javascript');
    echo "
  function person(firstName) {
    this.firstName = firstName;
    this.changeName = function (name) {
        this.firstName = name;
    };
  }
  ";
    exit;
  }
}
?>
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
  <style type="text/css">
.my_btn { background-color:yellow; }
  </style>
  <script src="http://code.jquery.com/jquery-1.12.4.min.js"></script>
  <script type="text/javascript">
var thishref = window.location.href.slice(0, window.location.href.indexOf('?')+1);
var qstr = window.location.href.slice(window.location.href.indexOf('?')+1);

function OnGetdata(inbtn) {
  console.log("OnGetdata; loading ?getone via AJAX call");
  //~ $.ajax(thishref + "?getone", { // works
  var ptest = {}; // init as empty object
  console.log(" ptest pre ajax is ", ptest);

  $.ajax({url: thishref + "?getone",
    async: true, // still "Synchronous XMLHttpRequest on the main thread is deprecated", because we load a script; https://stackoverflow.com/q/24639335
    success: function(data) {
      console.log("got getone data "); //, data);
      $("#dataholder").html(data);
      ptest = new person("AHA");
      console.log(" ptest post getone is ", ptest);
    },
    error: function(xhr, ajaxOptions, thrownError) {
      console.log("getone error " + thishref + " : " + xhr.status + " / " + thrownError);
    }
  });

  ptest.changeName("Somename");
  console.log(" ptest post ajax is ", ptest);
}

ondocready = function() {
  $("#getdatabtn").click(function(){
    OnGetdata(this);
  });
}
$(document).ready(ondocready);
  </script>
</head>


<body>
  <h1>Hello World!</h1>

  <button type="button" id="getdatabtn" class="my_btn">Get Data!</button>
  <div id="dataholder"></div>
</body>
</html>

So, when the page first loads, there's no action; and as soon as the button is pressed: first some HTML content, which contains <script>, is returned (this is ?getone) through an AJAX call; then this script itself loads "automatically" from ?gettwo. I'm aware this is probably not the right thing to do (see JavaScript console.log causes error: "Synchronous XMLHttpRequest on the main thread is deprecated..."), but there is a similar organization in the actual page I'm trying to test.

To run this page, you can just have the command-line php version > 5.3, and run in the same directory of the file:

php -S localhost:8080

... and then, in a browser, go to http://127.0.0.1:8080/test_JSload.php.

In any case, once I click the button, Firefox console shows:

OnGetdata; loading ?getone via AJAX call      test_JSload.php:13:3
 ptest pre ajax is  Object {  }               test_JSload.php:16:3
TypeError: ptest.changeName is not a function test_JSload.php:31:3
got getone data                               test_JSload.php:21:7
Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help http://xhr.spec.whatwg.org/ jquery-1.12.4.min.js:4:26272
 ptest post getone is  Object { firstName: "AHA", changeName: person/this.changeName(name) } test_JSload.php:24:7

Btw, the error 'TypeError: ... is not a function' is the exact same I get from Mink/Zombie with the actual page I'm trying to inspect; although I don't think the page itself exhibits that error when called standalone, as it does here.

Now, let's try inspect this page with Mink (install as on nodejs cannot find module 'zombie' with PHP mink):

test_JSload_mink.php

<?php
$nodeModPath = "/home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules";

# composer autoload:
require_once __DIR__ . '/vendor/autoload.php';


$zsrv = new \Behat\Mink\Driver\NodeJS\Server\ZombieServer();
$zsrv->setNodeModulesPath($nodeModPath . "/"); # needs to end with a trailing '/'
$driver = new \Behat\Mink\Driver\ZombieDriver( $zsrv );
$session = new \Behat\Mink\Session($driver);

// start the session
$session->start();

$session->visit("http://127.0.0.1:8080/test_JSload.php");
$session->wait(20000, '(browser.statusCode > 0)'); ### THIS makes things work?!
$statcode = $session->getStatusCode();
echo "  current URL: " . $session->getCurrentUrl() ."\n";
echo "  status code: " . $statcode ."\n";

$page = $session->getPage();
$el_button = $page->findButton('getdatabtn');
echo "Check: el_b " . gettype($el_button) . "\n";

echo "  pressing/clicking the button\n";
$el_button->click();

echo "Page URL after click: ". $session->getCurrentUrl() . "\n";
?>

Running this from another terminal shell (while the first one still runs the php server process that serves test_JSload.php) results with:

$ php test_JSload_mink.php
  current URL: http://127.0.0.1:8080/test_JSload.php
  status code: 200
Check: el_b object
  pressing/clicking the button
PHP Fatal error:  Uncaught exception 'Behat\Mink\Exception\DriverException' with message 'Error while processing event 'click': "ReferenceError: person is not defined\n    at Object.OnGetdata.$.ajax.success (http://127.0.0.1:8080/test_JSload.php:script:16:19)\n    at i (http://code.jquery.com/jquery-1.12.4.min.js:2:27449)\n    at Object.j.fireWith [as resolveWith] (http://code.jquery.com/jquery-1.12.4.min.js:2:28213)\n    at y (http://code.jquery.com/jquery-1.12.4.min.js:4:22721)\n    at XMLHttpRequest.c (http://code.jquery.com/jquery-1.12.4.min.js:4:26925)\n    at callListeners (/home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules/zombie/node_modules/jsdom/lib/jsdom/events/EventTarget.js:170:34)\n    at dispatchPhase (/home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules/zombie/node_modules/jsdom/lib/jsdom/events/EventTarget.js:159:7)\n    at XMLHttpRequest.EventTarget.dispatchEvent (/home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules/zombie/node_modules/jsdom/lib/jsdom/events/EventTarget.js:115: in /media/Data1/work/bbs/gits/econdk-vis-01_git/test/test_php_mink/vendor/behat/mink-zombie-driver/src/ZombieDriver.php on line 880

Now, here the error from Mink/Zombie is 'ReferenceError: person is not defined', whereas in my actual page inspection, it is 'TypeError: ... is not a function' - but I think they are similar enough.

The question is - how can I handle errors like this?

For instance, here there is already '$session->wait(20000, '(browser.statusCode > 0)');' used, which checks for browser.statusCode inside JavaScript; I'm aware there is also:

$returnstring = $session->evaluateScript('document.readyState');

... which can also ask for data from JavaScript. So something like this - in principle - could be used to "wait" until given resources are loaded.

But the problem here is that the ptest variable, which exposes the problem, is in the local scope of function OnGetdata(), and so I have no idea how to construct a statement that would "check" it from PHP - where I expect only global variables like browser and document to be accessible.

So, does anyone now how could I have a Mink/Zombie PHP script "wait" for such "nested" JavaScript loading - so I could complete the loading of the page, after the virtual click, without an error?


EDIT: Managed to reduce this problem to a plain Zombie JavaScript file:

test_JSload_zombie.js

// call with:
// DEBUG=zombie NODE_PATH=/home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules node test_JSload_zombie.js

var Browser = require("zombie");

browser = new Browser({waitDuration: 30*1000, runScripts: true});

browser.visit("http://127.0.0.1:8080/test_JSload.php", function () {
  browser.pressButton('Get Data!'); //, done);
  console.log(' person, post-click pre-wait:', browser.evaluate('typeof(person)'), browser.evaluate('$("script").length') ); // $("script").length is 2
  var checkCondition = function () {
    var ret =browser.evaluate("(typeof(person) != 'undefined')");
    console.log("ret is " + ret);
    return ret;
  };
  browser.wait({function: checkCondition, duration: 100000}, function() {
    console.log(' person, post-wait:', browser.evaluate('typeof(person)'), browser.evaluate('$("script").length')); // $("script").length is 3
    /// browser.dump(); // not too much info
  });
});

Running this file, logs the exact same error:

  zombie Opened window http://127.0.0.1:8080/test_JSload.php  +0ms
  zombie GET http://127.0.0.1:8080/test_JSload.php => 200 +198ms
  zombie Loaded document http://127.0.0.1:8080/test_JSload.php +233ms
  zombie GET http://code.jquery.com/jquery-1.12.4.min.js => 200 +207ms
  zombie Event loop is empty +476ms
OnGetdata; loading ?getone via AJAX call
 ptest pre ajax is  Object {}
  zombie XHR readystatechange http://127.0.0.1:8080/test_JSload.php?getone +54ms
  zombie XHR loadstart http://127.0.0.1:8080/test_JSload.php?getone +3ms
  zombie TypeError: ptest.changeName is not a function
    at OnGetdata (http://127.0.0.1:8080/test_JSload.php:script:24:9)
    at null.<anonymous> (http://127.0.0.1:8080/test_JSload.php:script:30:5)
    at n.event.dispatch (http://code.jquery.com/jquery-1.12.4.min.js:3:12444)
    at r.handle (http://code.jquery.com/jquery-1.12.4.min.js:3:9173)
    at callListeners (/home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules/zombie/node_modules/jsdom/lib/jsdom/events/EventTarget.js:170:34)
    at dispatchPhase (/home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules/zombie/node_modules/jsdom/lib/jsdom/events/EventTarget.js:159:7)
    at EventTarget.dispatchEvent (/home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules/zombie/node_modules/jsdom/lib/jsdom/events/EventTarget.js:115:3)
    at DOM.EventTarget.dispatchEvent (/home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules/zombie/lib/dom/jsdom_patches.js:155:31)
    at define.proto.dispatchEvent (/home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules/zombie/node_modules/jsdom/lib/jsdom/level2/html.js:365:55)
    at Browser.fire (/home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules/zombie/lib/index.js:424:14)
    in http://127.0.0.1:8080/test_JSload.php +24ms
 person, post-click pre-wait: undefined 2
ret is false
  zombie GET http://127.0.0.1:8080/test_JSload.php?getone => 200 +36ms
  zombie XHR readystatechange http://127.0.0.1:8080/test_JSload.php?getone +7ms
  zombie XHR readystatechange http://127.0.0.1:8080/test_JSload.php?getone +0ms
ret is false
got getone data 
  zombie ReferenceError: person is not defined
    at Object.OnGetdata.$.ajax.success (http://127.0.0.1:8080/test_JSload.php:script:16:19)
    at i (http://code.jquery.com/jquery-1.12.4.min.js:2:27449)
    at Object.j.fireWith [as resolveWith] (http://code.jquery.com/jquery-1.12.4.min.js:2:28213)
    at y (http://code.jquery.com/jquery-1.12.4.min.js:4:22721)
    at XMLHttpRequest.c (http://code.jquery.com/jquery-1.12.4.min.js:4:26925)
    at callListeners (/home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules/zombie/node_modules/jsdom/lib/jsdom/events/EventTarget.js:170:34)
    at dispatchPhase (/home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules/zombie/node_modules/jsdom/lib/jsdom/events/EventTarget.js:159:7)
    at XMLHttpRequest.EventTarget.dispatchEvent (/home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules/zombie/node_modules/jsdom/lib/jsdom/events/EventTarget.js:115:3)
    at XMLHttpRequest.DOM.EventTarget.dispatchEvent (/home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules/zombie/lib/dom/jsdom_patches.js:155:31)
    at XMLHttpRequest._fire (/home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules/zombie/lib/xhr.js:242:12)
    in http://127.0.0.1:8080/test_JSload.php +73ms
 person, post-wait: undefined 3
  zombie XHR readystatechange http://127.0.0.1:8080/test_JSload.php?getone +4ms
  zombie XHR progress http://127.0.0.1:8080/test_JSload.php?getone +0ms
  zombie XHR load http://127.0.0.1:8080/test_JSload.php?getone +1ms
  zombie XHR loadend http://127.0.0.1:8080/test_JSload.php?getone +0ms
  zombie GET http://127.0.0.1:8080/test_JSload.php?gettwo => 200 +18ms

So, I guess if this gets solved on a Zombie/JS level, then it can eventually be solved on a Mink/PHP level... Note however, that the call to ?gettwo happens only after the error has been emitted (and is the final entry in the log) - it seems that Zombie simply cannot wait for synchronous requests..

解决方案

Try this too:

$session->wait(50000, "document.readyState === 'complete'");

Or try other wait condition, for example a do while to wait for an object, also please not that findButton may return null if the element is not found/loaded so you can try a do-while for some seconds and if button !== null then break/return the button.

I always use wait for element that returns the object or throws an exception and click, for example something like:

$this->waitForElement('selector')->click();

If you need an example of waitForElement please let me know.

Here are some ajax conditions that you can try how-to-make-behat-wait-for-an-ajax-call

这篇关于在PHP中使用Mink/Zombie检查JavaScript AJAX加载的资源?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆