简体   繁体   English

javascript递归调用中的问题

[英]issue in recursive call of javascript

Description: I want to read a particular label from the webpage, whose value changes to one of "started", "inprogress", "success", "Error".说明:我想从网页中读取特定标签,其值更改为“开始”、“进行中”、“成功”、“错误”之一。 Once the label value changes to "success" or "Error" there will not be any further changes.一旦标签值更改为“成功”或“错误”,就不会再有任何更改。

Issue: When I read the label value using javascript in protractor, the text value of the label is not returned to the calling function;问题:当我在量角器中使用 javascript 读取标签值时,标签的文本值没有返回给调用函数; instead it returns 'undefined'.相反,它返回“未定义”。 Below is my code, please have a look and let me where the issue is.下面是我的代码,请看一下,让我看看问题出在哪里。

CheckColor_Test.js 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 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();

Executing in Protractor: I have configured protractor in Webstorm, hence I used to run using that.在量角器中执行:我已经在 Webstorm 中配置了量角器,因此我曾经使用它运行。

Expected Result: The test should get successful and passed预期结果:测试应该成功并通过

Actual Result: The test fails with below error.实际结果:测试失败并出现以下错误。

"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

The following return value:以下返回值:

return currentStatus.then(...);

is not the value returned by this statement:不是此语句返回的值:

return Status;

In fact, the latter is returned to one of the recursive calls of refreshStatusMonitor which is not captured anywhere.事实上,后者返回到refreshStatusMonitor的递归调用之一,该调用没有在任何地方捕获。

Because this is asynchronous code involving promises, the return value of currentStatus should be a promise as well, which would bubble up via refreshStatusMonitor , refreshTillRefreshFinish to your test, which then also needs to be adapted to wait for the promise to be fulfilled before expecting anything.因为这是涉及promise的异步代码, currentStatus的返回值也应该是promise,它会通过refreshStatusMonitorrefreshTillRefreshFinish到你的测试中,然后还需要调整以等待promise完成,然后再期待任何事情.

I would also advise against the use of browser.sleep(...) as it completely blocks your JavaScript environment.我还建议不要使用browser.sleep(...)因为它会完全阻止您的 JavaScript 环境。 You could use setTimeout(...) instead.您可以改用setTimeout(...)

Here is some untested code which builds on those ideas:以下是一些基于这些想法的未经测试的代码:

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;
};

Your test should then also take into account that you are dealing with a promise:你的测试还应该考虑到你正在处理一个承诺:

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

Note that Jasmine has a default timeout of 2 seconds, so you need to provide that extra argument at the end.请注意,Jasmine 的默认超时时间为 2 秒,因此您需要在最后提供该额外参数。

NB: Such asynchronous tests are not very suitable for running batches of unit tests.注意:这种异步测试不太适合运行批量单元测试。

Is your script able to click on the refresh button recursively?您的脚本是否能够递归单击刷新按钮?

i have made few changes to your existing script by introducing promises inside the recursive method.Just give a try.我通过在递归方法中引入 promise 对您现有的脚本进行了一些更改。试一试。

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();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM