问题在JavaScript的recursion调用

说明:我想从网页上读取一个特定的标签,其值将变为“开始”,“进行中”,“成功”,“错误”之一。 一旦标签值变为“成功”或“错误”,就不会有任何进一步的变化。

问题:当我在量angular器中使用JavaScript读取标签值时,标签的文本值不会返回到调用函数; 相反,它返回“未定义”。 下面是我的代码,请看看,让我问题的地方。

CheckColor_Test.js

var commonFunctions = require('../pages/CommonFunctions.js'); describe("Run Test", function () { it("should stop once the status reached Success or Error", function () { var processStatus = commonFunctions.refreshTillProcessFinish(); expect(processStatus).toContain('Success','Error'); }); }); 

CommonFunctions.js

 Var CommonFunctions = function(){ var label = element(by.id('Status')); var refreshStatusBtn = element(by.css('[ng-click="getJob()"]')); this.getStatusValue = function () { return label.then(function (headers) { return headers.getText(); }); }; this.refreshTillRefreshFinish = function () { var refreshStatusMonitor = function (currentStatus) { return currentStatus.then(function (Status) { if (Status == 'Success' || Status.includes("Error")) { console.log(Status); return Status; } else { refreshStatusBtn.click(); console.log(Status); browser.sleep(2000); refreshStatusMonitor (currentStatus); } }); }; return refreshStatusMonitor (this.getStatusValue); }; } module.exports = new CommonFunctions(); 

在量angular器中执行:我已经在Webstorm中configuration了量angular器,因此我曾经使用过。

预期结果:testing应该成功通过

实际结果:testing失败,出现以下错误。

 "C:\Program Files (x86)\JetBrains\WebStorm 2016.1.1\bin\runnerw.exe" "C:\Program Files\nodejs\node.exe" node_modules\protractor\built\cli.js D:\Somesh_HDD\WebstormProjects\ProjectUBET\conf.js [22:19:59] I/direct - Using ChromeDriver directly... [22:19:59] I/launcher - Running 1 instances of WebDriver Spec started Started InProgress Success Run Test ? should stop once the status reached Success or Error - Expected undefined to contain 'Success', 'Error'. ************************************************** * Failures * ************************************************** 1) Run Test should stop once the status reached Success or Error - Expected undefined to contain 'Success', 'Error'. Executed 1 of 1 spec (1 FAILED) in 33 secs. [22:20:36] I/launcher - 0 instance(s) of WebDriver still running [22:20:36] I/launcher - chrome #01 failed 1 test(s) [22:20:36] I/launcher - overall: 1 failed spec(s) [22:20:36] E/launcher - Process exited with error code 1 Process finished with exit code 1 

以下返回值:

 return currentStatus.then(...); 

是不是这个声明返回的值:

 return Status; 

事实上,后者被返回到refreshStatusMonitor的recursion调用之一,这个调用在任何地方都没有被捕获。

因为这是涉及promise的asynchronous代码,所以currentStatus的返回值也应该是一个承诺,它会通过refreshStatusMonitorrefreshTillRefreshFinish向您的testingrefreshStatusMonitor ,然后需要适应等待承诺在期待之前完成。

我也build议不要使用browser.sleep(...)因为它完全阻止你的JavaScript环境。 你可以使用setTimeout(...)来代替。

下面是一些基于这些想法的未经testing的代码:

 this.refreshTillRefreshFinish = function () { // create a promise var deferred = protractor.promise.defer(); var refreshStatusMonitor = function (currentStatus) { currentStatus.then(function refresh(Status) { if (Status == 'Success' || Status.includes("Error")) { // Signal the completion via the promise. // This triggers the `then` callback in your revised test deferred.fulfill(Status); } else { refreshStatusBtn.click(); console.log(Status); // Use setTimeout so JavaScript is not blocked here: setTimeout(function () { refreshStatusMonitor(currentStatus); }, 2000); } }); }; refreshStatusMonitor(this.getStatusValue); // Don't wait for the result to happen while blocking everything, // instead return a custom-made promise immediately return deferred.promise; }; 

你的testing也应该考虑到你正在处理一个承诺:

 it("should stop once the status reached Success or Error", function () { var processStatus = commonFunctions.refreshTillProcessFinish().then(function () { expect(processStatus).toContain('Success','Error'); done(); }); }, 20000); // set timeout to 20 seconds 

请注意,Jasmine的默认超时时间为2秒,因此您需要在最后提供额外的参数。

注意:这种asynchronoustesting不适合运行批量的unit testing。

你的脚本是否可以recursion地点击刷新button?

通过在recursion方法中引入承诺,我对现有的脚本做了一些改动。只要试试看。

 var CommonFunctions = function(){ var label = element(by.id('Status')); var refreshStatusBtn = element(by.css('[ng-click="getJob()"]')); this.refreshTillRefreshFinish = function () { var defer = protractor.promise().defer(); var refreshStatusMonitor = function () { label.getText().then(function (Status) { if (Status == 'Success' || Status.includes("Error")) { defer.fulfill(Status); } else { refreshStatusBtn.click(); browser.sleep(2000); refreshStatusMonitor (); } }); return defer.promise; }; return refreshStatusMonitor (); }; } module.exports = new CommonFunctions();