如何在Protractor中获取输入框的文本内容

112

在protractor的文档中,我看到了以下示例:

describe('by model', function() {
  it('should find an element by text input model', function() {
    var username = element(by.model('username'));
    username.clear();
    username.sendKeys('Jane Doe');

    var name = element(by.binding('username'));

    expect(name.getText()).toEqual('Jane Doe');
  });

这里显而易见的是,您可以使用 "by.model" 在输入框中设置值,但如果您想查看输入框中的内容,则需要使用 "by.binding"。

我有一组代码(简述)如下:

element(by.model('risk.name')).sendKeys('A value');
expect(element(by.model('risk.name')).getText()).toEqual('A value');

在我的实际代码中,我保存实体,然后在编辑模式下返回它,并检查我的值是否实际保存。但最终归结为同样的问题,这个示例代码也存在同样的问题。

这个给了我一个错误:

Error: Expected '' to equal 'A value'.

理论上,如果按照文档的示例,我可以这样做:

element(by.model('risk.name')).sendKeys('A value');
expect(element(by.binding('risk.name)).getText()).toEqual('A value');

但是用 by.binding 的时候似乎不支持完全限定的模型,我会收到一个错误:

Error: No element found using locator: by.binding("risk.name")

如果我这样做,它确实可以工作(在某种程度上):

element(by.model('risk.name')).sendKeys('A value');
expect(element(by.binding('name')).getText()).toEqual('A value');

这段代码找到了一个元素,但是它也警告我匹配“name”的元素不止一个。不幸的是,它选择的不是正确的那个。

所以,有两个问题:

  1. by.model是否能够返回getText(),或者这是一个设计决策,需要使用by.binding代替?
  2. 是否可以在by.binding中使用完全限定的实体名称,或者这是一个设计决策,by.binding不喜欢完整的模型名称?如果是这样,还可以使用哪些限定符来在不同的绑定之间进行选择?

编辑:

我还尝试了vdrulerz建议的解决方案,将代码修改如下:

element(by.model('risk.name')).getText().then(function(text) {
  console.log(text);
  expect(text).toEqual('A risk name');  
});

console.log 返回一个空值(不是 promise 或对象),expect 则报错并给出以下信息:

Expected '' to equal 'A risk name'.

我的理解是protractor已经通过修补expect来处理promise,所以我觉得潜在的问题是getText不能在通过模型识别的字段上正常工作(我可以成功地在标签和其他小部件上使用getText)。

我还可以运行以下代码,使用getAttribute而不是getText():

expect(element(by.model('risk.name')).getAttribute('autofocus')).toEqual('true');
element(by.model('risk.name')).getAttribute('autofocus').then(function(text) {
  console.log(text);
  expect(text).toEqual('true');  
});

第一部分通过了 - 预期的工作。第二部分也能工作,表明vdrulerz的语法也是有效的,并且它会将“true”记录到控制台。我认为getText可能存在缺陷?

8个回答

219

在Protractor FAQ中已经回答了这个问题:https://github.com/angular/protractor/blob/master/docs/faq.md#the-result-of-gettext-from-an-input-element-is-always-empty

从输入框获取getText的结果始终为空,这是webdriver的一个怪异行为。相反,尝试使用以下方法:

element.getAttribute('value')

至于问题2,是的,您应该能够在by.binding中使用完全限定的名称。我怀疑您的模板实际上没有通过 {{}} 或 ng-bind 绑定到 risk.name 的元素。


啊,我觉得我已经到处都找了,包括搜索。今天我在protractor的github上提出这个问题,因为我没有找到答案。烦人。我的元素绑定了ng-model,所以在html中有"ng-model="risk.name""。但这可能不是使它工作所需的。我会建议更新文档以建议使用getAttribute。 - PaulL
2
为了记录,我在解决这个问题上花费了太长时间:getAttribute实际上返回的是一个Promise而不是字符串。https://github.com/angular/protractor/issues/673 - boardlemur
我认为这个魔法的原理在于getAttribute的行为,它实际上会获取一个属性(即使在您的DOM中没有"value"属性,它也会返回一个值):“...除非该属性不存在,在这种情况下将返回具有相同名称的属性的值”。 - Nate Anderson

6

getText()函数对于webdriver的工作方式不再像以前那样有效,为了让它在protractor中发挥作用,您需要将其包装在一个函数中并返回文本,就像我们为protractor框架所做的一样,我们将其保留在一个常见的函数中,例如:

getText : function(element, callback) {
        element.getText().then (function(text){             
            callback(text);
         });        

    },

通过这个方法,你可以获取一个元素的文本。

如果还不清楚,请告诉我。


我明白如果我想直接使用文本,我需要这样做,但我认为Protractor修补了Jasmine的expect匹配器以处理Promise - 所以expect(element.getText())。toEqual实际上等同于element.getText()。then(expect(text)。toEqual)。不是这样吗? - PaulL
这对我也不起作用。我已经在上面扩展了我的问题,这样你就可以看到它的格式了。 - PaulL
尝试使用element(by.locator('abc').getText().then(function(text) { console.log(text) expect(text).toEqual("sometext"); }); - vdrulerz
报告显示对象[object Object]没有'locator'方法。我在protractor api中没有看到'by.locator'方法,代码中也没有看到-如果确实有一个by.locator方法,那么它肯定是像'by.locator('model','risk.name')'这样的东西。 - PaulL
使用 by.locator,我指的是您可以使用类似于 prot.findelement(By.id)、CSS、Xpath 或任何定位器属性... 如果仍然无法正常工作,请与我分享您的代码和 HTML 属性... 我一定会帮助您解决问题... - vdrulerz

3

我曾经遇到过这个问题,尝试了Jmr的解决方案,但对我没有用。由于所有输入字段都有ng-model属性,因此我可以提取属性并评估它,从而获得值。

HTML

<input ng-model="qty" type="number">

Protractor

var qty = element( by.model('qty') );
qty.sendKeys('10');
qty.evaluate(qty.getAttribute('ng-model')) //-> 10

2
以下代码对我有效,用于获取输入框中的文本。
return(this.webelement.getAttribute('value').then(function(text)
    {
        console.log("--------" + text);
}))

0

你必须使用 Promise 来打印或存储元素的值。

 var ExpectedValue:string ="AllTestings.com";
          element(by.id("xyz")).getAttribute("value").then(function (Text) {

                        expect(Text.trim()).toEqual("ExpectedValue", "Wrong page navigated");//Assertion
        console.log("Text");//Print here in Console

                    });

0
这段代码是有效的。我有一个日期输入字段,已经设置为只读,这强制用户从日历中选择。
对于开始日期:
var updateInput = "var input = document.getElementById('startDateInput');" +
    "input.value = '18-Jan-2016';" +
    "angular.element(input).scope().$apply(function(s) { s.$parent..searchForm[input.name].$setViewValue(input.value);})";
browser.executeScript(updateInput);

对于结束日期:

var updateInput = "var input = document.getElementById('endDateInput');" +
    "input.value = '22-Jan-2016';" +
    "angular.element(input).scope().$apply(function(s) { s.$parent.searchForm[input.name].$setViewValue(input.value);})";
    browser.executeScript(updateInput);

-1

你可以尝试这样做

var access_token = driver.findElement(webdriver.By.name("AccToken"))

        var access_token_getTextFunction = function() {
            access_token.getText().then(function(value) {
                console.log(value);
                return value;
            });
        }

然后您可以在需要获取值的地方调用此函数。


-3
你可以使用 jQuery 获取文本框中的文本(对我很有效),详见图像细节。
代码:
$(document.evaluate( "xpath" ,document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ).singleNodeValue).val()

Example: 
$(document.evaluate( "//*[@id='mail']" ,document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ).singleNodeValue).val()

将此代码插入到您的代码中。图像细节:

enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接