Home Documentation Having Operations

H - Having Operations

Define conditions on related elements (child, parent, ancestor, sibling) inside the same expression.

XPathy introduces Having operations, which allow you to define conditions on related elements inside the same expression. The byHaving() method acts as a predicate builder.

1. Basic Having with Direct Condition

Example
XPathy locator = div.byAttribute(class_).equals("product-card").and()
                .byHaving(
                         span.byText().contains("In Stock")
                         );
Result
//div[@class='product-card' and ( span[contains(text(), 'In Stock')] )]

Use Case: Selects <div class="product-card"> elements only if they contain a <span> with text containing "In Stock".

2. Having with Child

Example
XPathy locator = table.byHaving().child(
                  tr.byAttribute(class_).equals("total-row")
                  );
Result
//table[( ./tr[@class='total-row'] )]

Use Case: Matches an <table> if it has a direct child row with the class total-row.

3. Having with Descendant

Example
XPathy locator = section.byAttribute(id).equals("checkout").and()
                .byHaving().descendant(
                      button.byText().contains("Place Order")
                      );
Result
//section[@id='checkout' and ( .//button[contains(text(), 'Place Order')] )]

Use Case: Matches a <section id="checkout"> if any nested descendant button contains the text "Place Order".

4. Having with Ancestor

Example
XPathy locator = div.byAttribute(class_).equals("price-tag").and()
                .byHaving().ancestor(
                       section.byAttribute(id).equals("product-details")
                       );
Result
//div[@class='price-tag' and ( ancestor::section[@id='product-details'] )]

Use Case: Matches <div class="price-tag"> only if it has a <section> ancestor with id="product-details".

5. Having with Parent

Example
XPathy locator = ul.byAttribute(class_).equals("menu-items").and()
                .byHaving().parent(
                      nav.byAttribute(role).equals("navigation")
                      );
Result
//ul[@class='menu-items' and ( parent::nav[@role='navigation'] )]

Use Case: Matches <ul class="menu-items"> only if its immediate parent <nav> has the role navigation.

6. Having with Siblings

Following Sibling

Example
XPathy locator = h2.byText().equals("Features").and()
                .byHaving().followingSibling(
                       div.byAttribute(class_).equals("description")
                       );
Result
//h2[text()='Features' and ( following-sibling::div[@class='description'] )]

Preceding Sibling

Example
XPathy locator = li.byText().equals("Contact").and()
                .byHaving().precedingSibling(
                     li.byText().equals("About")
                     );
Result
//li[text()='Contact' and ( preceding-sibling::li[text()='About'] )]

7. Simplified Workflow

Example
XPathy locator = table.byAttribute(id).equals("invoice").and()
                .byHaving().child(td).byText().contains("Subtotal");
Result
//table[@id='invoice' and ./td[contains(text(), 'Subtotal')]]

Use Case: Matches <table id="invoice"> if it contains a direct <td> child with text "Subtotal".

Key Benefits:
  • Readability: Express complex DOM relationships inline without writing full XPath manually
  • Flexibility: Mix with transformations for resilient conditions
  • Reusability: You can insert any XPathy expression into byHaving()