Cucumber with Protractor 是否需要回调?

Does Cucumber with Protractor need the callback?

我正在尝试了解 The WebDriver Control Flow 的确切工作原理。

根据链接文档 (https://github.com/angular/protractor/blob/master/docs/control-flow.md) jasmine 中不需要回调方法/调用:

Protractor adapts Jasmine so that each spec automatically waits until the control flow is empty before exiting.

但是,我不得不用黄瓜。我正在使用此处描述的库 protractor-cucumber-frameworkhttps://github.com/angular/protractor/blob/master/docs/frameworks.md#using-cucumber

它运行良好,但出于某种原因,当我跳过回调变量时它比当我尝试使用它时效果更好。例如,此代码失败:

this.Given(/^the login page is active$/, function (callback) {
  browser.get('/').then(callback);
});

有错误...

TypeError: text.split is not a function

[launcher] Process exited with error code 1

另一方面,此代码按我希望的方式工作,黄瓜/量角器似乎在等待页面加载,然后再执行其他功能:

me.Given(/^the login page is active$/, function () {
  browser.get('/');
});

但是我找不到任何文档来确认我真的可以省略回调函数。

目前我尝试测试的页面没有使用 Angular,因此我的配置文件中有以下代码:

onPrepare: function() {
  browser.ignoreSynchronization = true;
}

Protractor 在底层使用了 WebDriverJS。 WebDriverJS 使用一个 promise 管理器来对它的命令进行排队。这是他们维基页面的一些摘录 here

Internally, the promise manager maintains a call stack. Upon each turn of the manager's execution loop, it will pull a task to execute from the queue of the top-most frame. Any commands scheduled within the callback of a previous command will be scheduled in a new frame, ensuring they run before any tasks previously scheduled. The end result is that if your test is written-in line, with all callbacks defined by function literals, commands should execute in the order they are read vertically on the screen. For example, consider the following WebDriverJS test case:

driver.get(MY_APP_URL);
driver.getTitle().then(function(title) {
  if (title === 'Login page') {
    driver.findElement(webdriver.By.id('user')).sendKeys('bugs');
    driver.findElement(webdriver.By.id('pw')).sendKeys('bunny');
    driver.findElement(webdriver.By.id('login')).click();
  }
});
driver.findElement(webdriver.By.id('userPreferences')).click();

可以使用 !WebDriver 的 Java API 重写此测试用例,如下所示:

driver.get(MY_APP_URL);
if ("Login Page".equals(driver.getTitle())) {
  driver.findElement(By.id("user")).sendKeys("bugs");
  driver.findElement(By.id("pw")).sendKeys("bunny");
  driver.findElement(By.id("login")).click();
}
driver.findElement(By.id("userPreferences")).click();

现在回到您的问题,因为您在步骤中省略了 callback,所以 Cucumber 会将您的测试代码视为同步代码。请参阅文档 here。由于 protractor/WebdriverJS 以上述方式处理 promise 管理器,因此一切都按预期工作。

至于您在使用 callback 时遇到的错误,我不确定。我做的和你做的完全一样。参见 here。我正在使用黄瓜 ^0.9.2。可能是你的cucumber版本有问题

附带说明一下,我发现您可以 return 承诺而不是使用回调让黄瓜知道您已完成执行。所以像这样的东西也可以工作(假设你使用的是 ^0.9.2)。我测试了,

me.Given(/^the login page is active$/, function () {
  return browser.get('/');
});