【问题标题】:Returning a value from a from a protractor promise inside a function从函数内的量角器承诺中返回一个值
【发布时间】:2015-08-10 16:48:52
【问题描述】:

我正在尝试从页面中获取文本,然后在规范中进一步使用该文本来断言另一个元素。

我粘贴了一个可以运行的非常简单的规范,它表明如果函数的 return 语句在量角器承诺 return txt; 内(第 24 行),则无法从函数返回值...

describe('My Test', function () {
    var tempVariable;

    it('should go get some text from the page', function () {
        browser.get('https://angularjs.org/');
        tempVariable = getTextFromElement();    //it appears javascript immediately sets this variable before waiting for protractor to return the value
    });

    it('should do some random other stuff', function () {
        element.all(by.cssContainingText('a', 'Learn')).get(0).click();
        element.all(by.cssContainingText('a', 'Case Studies')).get(0).click();
        element.all(by.cssContainingText('a', ' Home')).get(0).click();
    });

    it('should be able to use the text from the first page in this test', function () {
        console.log('\ntempVariable: ' + tempVariable);    //this is undefined!
        expect(typeof tempVariable).not.toBe('undefined', 'failed: tempVariable was undefined!');
    });
});

function getTextFromElement() {
    $('a.learn-link').getText().then(function (txt) {
        console.log('\nInitial text:   ' + txt);
        return txt;     //how do we return this so it's available to other 'it' blocks?
    });
}

在@alecxe 回答和我的评论之后更新了代码的 sn-p。

我正在尝试从页面上的各种文本构造一个对象并将其返回以在以后的页面中断言...

function getRandomProductFromList() {
    var Product = function (line, name, subname, units) {
        this.line       = line;
        this.name       = name;
        this.subname    = subname;
        this.units      = units;
    };

    var myProduct = new Product();

    myProduct.line = 'Ford';
    myProduct.units = 235;

    //select a random product on the page and add it to 'myProduct'
    var allProducts = element.all('div.product');
    allProducts.count().then(function (count) {
        var randomIndex = Math.floor(Math.random() * count);
        var productName = allProducts.get(randomIndex);

        productName.getText().then(function (prodName) {
            myProduct.name = prodName;
            productName.click();
        });
    });

    //If a sub-product can be chosen, select it and add it to 'myProduct'
    var subproduct = $('div.subproduct');
    subproduct.isDisplayed().then(function (subProductExists) {
        if (subProductExists) {
            subproduct.getText().then(function (subProductName) {
                myProduct.subname = subProductName;
            });
            subproduct.click();
        }
    }, function (err) {});

    return myProduct;
}

【问题讨论】:

  • 将返回后要执行的代码包装在匿名函数中,并将其作为参数传递给getTextFromElements。然后只需将该参数作为一个函数调用,您就可以在其中尝试返回值。

标签: javascript node.js testing selenium-webdriver protractor


【解决方案1】:

首先,您没有从函数返回任何内容

function getTextFromElement() {
    return $('a.learn-link').getText();
}

现在,这个函数会返回一个promise,你需要在使用之前解决这个问题:

it('should be able to use the text from the first page in this test', function () {
    tempVariable.then(function (tempVariableValue) {
        console.log('\ntempVariable: ' + tempVariableValue);    
        expect(typeof tempVariableValue).not.toBe('undefined', 'failed: tempVariable was undefined!');
    });
});

另外,要确定变量是否已定义,我会使用来自jasmine-matcherstoBeDefined()

expect(tempVariableValue).toBeDefined();

【讨论】:

  • 这让我从右脚开始,谢谢。事实证明,我的问题比返回一个我可以稍后在规范中解决的承诺更多。在我的真实测试中,getTextFromElement() 实际上多次使用getText() 来构造一个object。我想返回它的那个 object 以便稍后在规范中访问它的属性。不同的getText() 函数分散在整个函数中,所以我不确定在哪里返回完成的对象。你有什么技巧可以完成类似的事情,而不是只返回一个承诺?
  • @luker02 我想我们可以解决它。您能否提供到目前为止的代码以及该对象的外观?谢谢!
  • 酷。我在最初的问题中添加了一个更具体的getTextFromElement() 函数版本,现在称为getRandomProductFromList()
  • @alecxe 我们如何从函数返回值而不是承诺?
  • @SurendraJnawali 我们没有,传递承诺并在需要时解决。
【解决方案2】:

以上都不适合我。这对我有用:

    var item = element.all(by.xpath("some xpath here"));


    this.methodToGetTheText = function () {
       return Promise.resolve(item.getText().then(function (text) {
           return text;
       }));
    }

【讨论】:

  • 仅供参考,您可以简单地调用item.getText(),它与您的整个methodToGetTheText 函数执行相同的操作。但是,如果您需要在返回之前修改文本,请简化为:this.methodToGetTheText = function () { return item.getText().then(function (text) { return text.toLowerCase(); }); }(您不需要Promise.resolve)。如果使用 TypeScript 或 ES6,请进一步简化:this.methodToGetTheText = () => item.getText().then(text => text.toLowerCase());
  • 我不能简单地调用 item.getText()。如果我这样做,该方法将返回 undefined。
【解决方案3】:

感谢@alecxe 让我从正确的角度出发。

在阅读this 之后,我找到了一个我现在使用的解决方案。

通过引用传递对象,您可以动态添加属性并在以后的规范中使用它们。

例子:

describe('My Test', function () {
    var tempObject = {};

    it('should go get some text from the page', function () {
        browser.get('https://angularjs.org/');
        getTextFromElement(tempObject);    //pass an object by reference to populate with page text
    });

    it('should do some random other stuff', function () {
        $('div.someDiv').click();
    });

    it('should be able to use the text from the first page in this test', function () {
        console.log(tempObject.textFromFirstPage); //works!
    });
});

function getTextFromElement(tempObject) {
    $('a.some-link').getText().then(function (txt) {
        tempObject.textFromFirstPage = txt;
    });
}

【讨论】:

    【解决方案4】:

    您是否从您的规范中调用methodToGetTheText().then(.then() 函数中的值应该包含您的实际页面文本

    【讨论】:

      猜你喜欢
      • 2015-10-25
      • 1970-01-01
      • 2017-05-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多