admin 管理员组

文章数量: 1086019

I thought there was a way to chain locators and get a direct child doing so. So for example, say I have the following html structure

<tab title="my tab">
    <div _ngcontent-cjx-7>
        <div class='my other content'>...</div
    </div>
</tab>

I have a parent ElementFinder

var myTab = element(by.css('tab[title="my tab"]')); 

But I need to select that div. This doesn't work for me, but I thought I had seen something similar to this.

var myTabsDiv = myTab.$(' > div');

Is there a way to do this without falling back to xpath?

I thought there was a way to chain locators and get a direct child doing so. So for example, say I have the following html structure

<tab title="my tab">
    <div _ngcontent-cjx-7>
        <div class='my other content'>...</div
    </div>
</tab>

I have a parent ElementFinder

var myTab = element(by.css('tab[title="my tab"]')); 

But I need to select that div. This doesn't work for me, but I thought I had seen something similar to this.

var myTabsDiv = myTab.$(' > div');

Is there a way to do this without falling back to xpath?

Share Improve this question edited Nov 3, 2017 at 14:18 Machtyn asked Jul 15, 2016 at 15:16 MachtynMachtyn 3,2808 gold badges43 silver badges69 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 7

There is no way to refer to the current node in CSS selectors in general.

You have three options:

  • violate the DRY principle a bit and repeat the parent locator:

    var myTabsDiv = myTab.$('tab[title="my tab"] > div');
    
  • or revert to XPath location technique:

    var myTabsDiv = myTab.element(by.xpath('./div'));
    
  • or, this is Protractor-specific: get the locator() of the parent element and concatenate to make a new CSS selector:

    var myTabsDiv = myTab.$(myTab.locator().value + ' > div');
    

I've got a similar problem recently:

  • Using CSS selectors instead of XPath locators when searching through siblings

It's been well over a year since I asked this question and it is still getting some views. Using locator().value has been very good. But it isn't foolproof. Particularly when generating ElementFinders dynamically. For instance, element(by.css('tab[title="my tab"]')).element(by.css('.my.other.content')).locator().value will only return .my.other.content.

In my project, for my Page Object classes, I'm using a string to hold the locator and then exposing the ElementFinder object publicly.

Suppose we have a page with the following structure:

<tab title="my tab">
    <div _ngcontent-cjx-7>
        <div class='my other content'>...</div
    </div>
    <div id="shopping-cart"> ... </div>
    <div class="pricing">
        <div class="sub-total">...</div>
        <div class="tax">...</div>
        <div class="total">...</div>
    </div>
</tab>

My typescript page object might look like the following:

export class TheTab {
    private static myTab = 'tab[title="my tab"]';
    private static otherContent = '.my.other.content';
    private static shoppingCart = '#shopping-cart';
    private static subTotal = '.pricing > .sub-total';
    private static tax = '.pricing > .tax';
    private static total = '.pricing > .total';

    public static myTabEl = $(TheTab.myTab);
    public static otherContentEl = $(`${TheTab.myTab} ${TheTab.otherContent});
    public static shoppingCartEl = $(`${TheTab.myTab} > ${TheTab.shoppingCart});
    public static subTotalEl = $(`${TheTab.myTab} > ${TheTab.subTotal});
    public static taxEl = $(`${TheTab.myTab} > ${TheTab.tax});
    public static totalEl = $(`${TheTab.myTab} > ${TheTab.total});
}

If needing an ElementFinder to be generated dynamically, then exposing a string may be necessary or providing a function to build and return the ElementFinder using the private strings.

Using Xpath selectors is not a better choice as it slows down the element finding mechanism.

It will be very simple with protractor-css-booster plugin.

Download the plugin with

npm install --save protractor-css-booster

Add the plugin in your configuration file:

exports.config = {
  // ... the rest of your config
  plugins: [
    {
      // The module name
      package: "protractor-css-booster"
    }
  ]
};

Now, you can find your element like:

const divElement=element(by.firstChildOf('tab[title="my tab"]')); \\ returns the first div

You can also do some cool staffs with the plugin... check that out

本文标签: javascriptGetting direct child element in protractor using chainingStack Overflow