我从这里使用带有Mink + Zombie驱动程序的PHP脚本(在nodejs cannot find module 'zombie' with PHP mink上安装):PHP Mink/Zombie - page visit returns status code 0?;重新发布完整性:
<?php
$nodeModPath = "/home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules";
# composer autoload:
require_once __DIR__ . '/vendor/autoload.php';
$URL = "https://demo.centreon.com/centreon";
$USERNAME = "admin";
$PASSWORD = "centreon";
$LFID = "useralias";
$PFID = "password";
$BFID = "submitLogin";
$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->setRequestHeader('User-Agent', 'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2049.0 Safari/537.36');
$statcode = 0;
while ($statcode != 200) {
$isleep = rand(2, 7); echo "sleeping $isleep sec...\n";
sleep($isleep);
$session->visit($URL);
// $session->wait(20000, '(0 === jQuery.active)'); # Uncaught exception 'RuntimeException' with message 'Could not establish connection: Connection refused (111)'
$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_login = $page->findField($LFID);
$el_password = $page->findField($PFID);
$el_button = $page->find('xpath', '//*[@name="'.$BFID.'"]');//findById($BFID);//findField($BFID);
$el_login->setValue($USERNAME);
$el_password->setValue($PASSWORD);
echo " pressing/clicking login button\n";
$el_button->click();
echo "Page URL after click: ". $session->getCurrentUrl() . "\n";
$page = $session->getPage();
?>
问题是,当脚本运行并进行登录点击时,Mink无法检测到页面使用的某些JavaScript库,并引发异常:
$ php test_php_mink.php
sleeping 4 sec...
current URL: https://demo.centreon.com/centreon/
status code: 200
pressing/clicking login button
PHP Fatal error: Uncaught exception 'Behat\Mink\Exception\DriverException' with message 'Error while processing event 'click': "ReferenceError: Effect is not defined\n at https://demo.centreon.com/centreon/include/common/javascript/modalbox.js:517:1\n at Object.exports.runInContext (vm.js:44:17)\n at window._evaluate (/home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules/zombie/lib/document.js:253:75)\n at Object.DOM.languageProcessors.javascript (/home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules/zombie/lib/dom/scripts.js:26:12)\n at define.proto._eval (/home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules/zombie/node_modules/jsdom/lib/jsdom/level2/html.js:1477:47)\n at /home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules/zombie/node_modules/jsdom/lib/jsdom/browser/resource-loader.js:32:22\n at Object.item.check (/home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules/zombie/node_modules/jsdom/lib/jsdom/level2/html.js:188:11)\n at Object.item.check (/home in /path/to/test_php_mink/vendor/behat/mink-zombie-driver/src/ZombieDriver.php on line 880
例外是ReferenceError: Effect is not defined
,这是由于页面使用了这个javascript:
<script type="text/javascript" src="./include/common/javascript/scriptaculous/scriptaculous.js?load=effects,dragdrop"></script>
...
new Effect.toggle('header', 'appear', { afterFinish: function() {
然而,更大的问题是,在发生此次崩溃之后,当我第二次运行脚本时,它几乎立即崩溃,这次是Error: listen EADDRINUSE 127.0.0.1:8124
:
$ php test_php_mink.php
PHP Fatal error: Uncaught exception 'RuntimeException' with message 'Server process has been terminated: (1) [events.js:141
throw er; // Unhandled 'error' event
^
Error: listen EADDRINUSE 127.0.0.1:8124
at Object.exports._errnoException (util.js:837:11)
at exports._exceptionWithHostPort (util.js:860:20)
at Server._listen2 (net.js:1231:14)
at listen (net.js:1267:10)
at net.js:1376:9
at doNTCallback3 (node.js:440:9)
at process._tickCallback (node.js:346:17)
at Function.Module.runMain (module.js:473:11)
at startup (node.js:117:18)
at node.js:951:3
]' in /path/to/test_php_mink/vendor/behat/mink-zombie-driver/src/NodeJS/Server.php:413
Stack trace:
#0 /path/to/test_php_mink/vendor/behat/mink-zombie-driver/src/NodeJS/Server.php(306): Behat\Mink\Driver\NodeJS\Server->checkAvailability()
#1 /path/to/test_php_mink/vendor/behat/mink-zombie-driver/src/ZombieDriver. in /path/to/test_php_mink/vendor/behat/mink-zombie-driver/src/NodeJS/Server.php on line 413
似乎在第一次崩溃之后,仍然有mink
个进程 - 实际上还有:
$ pgrep -fl mink
7659 sh
7660 node
$ ps axf | grep mink
7687 pts/0 S+ 0:00 | \_ grep --color=tty mink
7659 pts/0 S 0:00 sh -c 'node' '/path/to/test_php_mink/vendor/behat/mink-zombie-driver/bin/mink-zombie-server.js'
7660 pts/0 Sl 0:03 \_ node /path/to/test_php_mink/vendor/behat/mink-zombie-driver/bin/mink-zombie-server.js
此时,如果我杀死这些进程 - 例如,使用pkill -f mink
- 然后它们从进程树中消失,然后我可以再次运行脚本,其结果与OP中的第一个调用相同(然后我必须再次杀死进程等)。
处理此问题的最佳/推荐方法是什么,因此每次脚本达到致命异常时,我都不必手动终止进程? Mink库中有什么东西允许这个吗?
答案 0 :(得分:1)
要避免致命异常,首先要做的是实现/使用具有适当错误处理的方法。 您可以创建一个方法来检查元素是否为null,以及是否抛出自定义异常。
例如,在您的情况下,如果找不到元素, findField 方法将返回null,在这种情况下, setValue 将在非对象上使用,从而导致致命错误。
答案 1 :(得分:0)
异常处理的一个例子是:
public function fillWith($locator, $text){
$element = $this->getSession()->getPage()->find("xpath", $locator);
if($element === null){
throw new Exception("Element $locator not found");
}else{
$element->setValue($text);
}
}