如何用Behat和Goutte处理Drupal 8中的Ajax加载模态框?
这种Drupal Ajax自定义模态框的Behat测试问题我碰到过好几次,确实比原生alert麻烦不少——毕竟它是动态加载的DOM元素,Behat默认的步骤太急,赶不上元素渲染的速度。我给你几个实用的解决思路,应该能搞定:
1. 先解决「Ajax加载延迟」的问题
你点击“Select files”后,模态框是通过Ajax异步加载的,Behat默认会立刻执行下一步的「我应该看到XX」,这时候模态框还没渲染出来,自然会失败。所以必须加智能等待,而不是固定等待(当然固定等待可以先用来测试)。
可以写一个自定义等待步骤,专门等模态框容器出现:
/** * @Then I wait for the upload modal to load */ public function waitForUploadModal() { $page = $this->getSession()->getPage(); // Drupal的Ajax模态框通常有固定ID #drupal-modal,你可以用开发者工具确认下 $modal = $page->waitFor(10, function($page) { return $page->find('css', '#drupal-modal'); }); if (!$modal) { throw new \Exception('文件上传模态框加载超时'); } }
2. 修正元素定位的方式
你之前用的div:contains("%s")是jQuery的选择器,原生CSS不支持,Behat的CSS选择器遵循原生标准,所以肯定找不到元素。换用XPath来定位包含指定文本的元素,或者先定位模态框容器,再在里面找内容。
比如写一个通用的“在模态框中看到文本”的步骤:
/** * @Then I should see :text in the upload modal */ public function seeTextInUploadModal($text) { $this->waitForUploadModal(); // 先确保模态框加载完成 $page = $this->getSession()->getPage(); // 在模态框容器内查找包含指定文本的元素 $element = $page->find('xpath', '//div[@id="drupal-modal"]//*[contains(text(), "' . $text . '")]'); if (!$element) { throw new \Exception('模态框中未找到文本: ' . $text); } }
3. 调整你的测试场景
把原来的步骤换成自定义的,确保流程正确:
Scenario: Creates a stage test with two sessions Given I am on "/user/login" And I fill in "user@user.com" for "name" And I fill in "password" for "pass" And I press "Log in" Then I should get a "200" HTTP response And I should see "User Name" When I go to "/node/add/stage" Then I should get a "200" HTTP response And I should see "Add content CISIA Stage" When I fill in "Test Cisia Stage" for "edit-title-0-value" And I press "Select files" And I wait for the upload modal to load Then I should see "Upload files" in the upload modal Then I should see "Click or drop files here to upload them" in the upload modal
额外提示:确认模态框的实际DOM结构
打开浏览器开发者工具,点击“Select files”后,查看模态框的HTML:
- 确认容器的ID或类名是不是
#drupal-modal(Drupal默认是这个,但如果是自定义模块可能有变化) - 查看文本所在的元素层级,比如是不是在
.modal-body或者.ui-dialog-content里,调整XPath或CSS选择器
如果你的Behat环境用的是Selenium驱动,还可以用WebDriver的原生等待方法,稳定性更高:
$driver = $this->getSession()->getDriver(); if ($driver instanceof \Behat\Mink\Driver\Selenium2Driver) { $webDriver = $driver->getWebDriver(); $webDriver->wait(10)->until( \Facebook\WebDriver\WebDriverExpectedCondition::visibilityOfElementLocated( \Facebook\WebDriver\WebDriverBy::id('drupal-modal') ) ); }
这样调整后,应该就能正确识别到自定义模态框了。
内容的提问来源于stack exchange,提问作者Jaeger
相关产品推荐
相关产品推荐

