最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to return child elements from within parent element in Protractor - Stack Overflow

programmeradmin2浏览0评论

I'm looking for a way to return the child elements from within a given parent element block (using page objects), and to be able to call them via chaining. For example, given a number of widgets on a page:

<div id="widget-1">
  <div class="name">Widget 42</div>
  <div class="color">Blue</div>
</div>
<div id="widget-2">
  <div class="name">Widget 23</div>
  <div class="color">Red</div>
</div>

And a page object, widgetPage:

this.widget = function(num) { return $('div#widget-' + num) };

I want to ONLY grab the name and color from the first widget block. This works in my spec:

expect(widgetPage.widget('42').$('color').getText()).toBe('Blue');

But I don't want to have selector code in my spec; I want it in the page object, where it belongs. I've not been able to find a good way to do this. I've tried various things like...

this.getWidgetElms = function(num) {
    return this.widget(num).then(function(w) {
        return {
            name: w.$('div.name'),
            color: w.$('div.color')
        };
    });
};
// fails because name and color are undefined... 

Ultimately, I'm looking to be able to do something like this (not working):

expect(widgetPage.getWidgetElms('42').color.getText()).toBe('Blue');

Obviously I'm doing something wrong... How can I return only the child elements for the first widget block?

I'm looking for a way to return the child elements from within a given parent element block (using page objects), and to be able to call them via chaining. For example, given a number of widgets on a page:

<div id="widget-1">
  <div class="name">Widget 42</div>
  <div class="color">Blue</div>
</div>
<div id="widget-2">
  <div class="name">Widget 23</div>
  <div class="color">Red</div>
</div>

And a page object, widgetPage:

this.widget = function(num) { return $('div#widget-' + num) };

I want to ONLY grab the name and color from the first widget block. This works in my spec:

expect(widgetPage.widget('42').$('color').getText()).toBe('Blue');

But I don't want to have selector code in my spec; I want it in the page object, where it belongs. I've not been able to find a good way to do this. I've tried various things like...

this.getWidgetElms = function(num) {
    return this.widget(num).then(function(w) {
        return {
            name: w.$('div.name'),
            color: w.$('div.color')
        };
    });
};
// fails because name and color are undefined... 

Ultimately, I'm looking to be able to do something like this (not working):

expect(widgetPage.getWidgetElms('42').color.getText()).toBe('Blue');

Obviously I'm doing something wrong... How can I return only the child elements for the first widget block?

Share Improve this question edited Feb 19, 2015 at 16:50 alecxe 475k127 gold badges1.1k silver badges1.2k bronze badges asked Feb 19, 2015 at 16:13 BrineBrine 3,7311 gold badge23 silver badges38 bronze badges 0
Add a ment  | 

3 Answers 3

Reset to default 4

What if you would return an object out of the widget function:

this.widget = function (num) {
    var elm = element(by.css('div#widget-' + num));
    return {
        widget: elm,
        name: elm.element(by.css('div.name')),
        color: elm.element(by.css('div.color'))
    };  
};

Then, in your spec:

var widget = widgetPage.widget('42');
expect(widget.name.getText()).toBe('Widget 42');
expect(widget.color.getText()).toBe('Blue');

I don't know about Protractor in particular, but here are two jQuery ways to get from "Widget 42" to "blue." Either one could be turned into a function in the page object. The first depends on the order of the name and color nodes, while the second doesn't.

$('div.name:contains("Widget 42")').next().text()

$('div.name:contains("Widget 42")').parent().find('.color').text();

(But I like alecxe's solution better.)

I found the example for the map() function on element.all really helpful for this type of situation : https://github./angular/protractor/issues/392#issuement-33237672 .

Adapting that example would lead to something like the following in your case (not tested)

element.all(by.css('div[id*="widget"]')).map(function(el) {
  return {
    name: el.element(by.css('div.name')).getText(),
    color: el.element(by.css('div.color')).getText()
  }
});

So if you can use all to get all the widgets, you can then create a map of the name and color.

发布评论

评论列表(0)

  1. 暂无评论