0

I want to query on particular elements.

My structure for code is as below:

HTML

<ul class="main">
    <li>...</li>
    <li>...</li>
    <li>
        <ul class="to--exclude">
            <li>...</li>
            <li>...</li>
        </ul>
    </li>
    <li>...</li>
    ...
</ul>

I want to test li's presence inside 'mainclass but not forli'swhich are insideto-exclude` class.

The problem is if I use element(by.css('.main li')), it will locate all the li's including the ones inside the to-exclude class.

In Chrome's developer tools, I'm able to locate them exactly using JQuery's :not or .not().

$('.main li').not('ul.to--exclude li')
// OR
$(".main li:not('ul.to-exclude li')");

While using it in protractor as

element(by.css('.main li').not('ul.to--exclude li'));
// OR
element(by.css(".main li:not('ul.to--exclude li')"));

The above code gives an error:

InvalidElementStateError: invalid element state: Failed to execute 'querySelectorAll' on 'Document': '.main li:not('ul.to--exclude li')' is not a valid selector.

How to accomplish the same in protractor. How to exclude some classes which are nested inside the parent locator class.

Thanks

softvar
  • 17,917
  • 12
  • 55
  • 76
  • jQuery `:not()` is different from CSS `:not()` - see [Why is my jQuery :not() selector not working in CSS?](http://stackoverflow.com/questions/10711730/why-is-my-jquery-not-selector-not-working-in-css) – BoltClock Jul 01 '14 at 04:21
  • Also note that your HTML is invalid, you cannot have a `ul` directly within a `ul`. To nest lists you must have a `ul` within a `li`. – BoltClock Jul 01 '14 at 04:22

1 Answers1

3

You should be able to do that with the CSS pseudo-class :not like this:

element(by.css(".main > li > ul:not(.to--exclude) li, .main > li)"));

I would add .main > li as a backup selector as it seems that you want to select all child lis under .main. This selector makes sense for such cases:

<ul class="main">
    <li>...</li>
    <li>...</li>
    <li>
        <ul class="to--exclude">
            <li>...</li>
            <li>...</li>
        </ul>
    </li>
    <li>
        <ul class="to--include">
            <li>...</li>
            <li>...</li>
        </ul>
    </li>
    ...
</ul>

If you don't have other uls like .to--include you could reduce the selector to:

element(by.css(".main > li)"));
Artjom B.
  • 61,146
  • 24
  • 125
  • 222
  • 1
    Note that this assumes the `ul` elements will only nest up to one level deep. If you have any more nested `ul` elements you will not be able to use `:not()` to filter them - see [Is the CSS :not() selector supposed to work with distant descendants?](http://stackoverflow.com/questions/20869061/is-the-css-not-selector-supposed-to-work-with-distant-descendants) – BoltClock Jul 01 '14 at 04:24