Class ComponentQuery<T extends Component>

java.lang.Object
com.vaadin.browserless.ComponentQuery<T>
Type Parameters:
T - the type of the component(s) to search for

public class ComponentQuery<T extends Component> extends Object
Query class used for finding a component inside a given search context. The search context is either the current UI instance which searches through the whole component tree, or a Component instance, which limits the search to the component subtree.

Not everything a view shows is in that tree. A component that another component renders per item, and the content of an overlay that is not open, are reached through the tester of the component that owns them: GridTester.getCellComponent(row, column) for grid cells, ContextMenuTester.open() or GridTester.contextMenu(row) for menus. A query returns an empty result rather than failing, so such a component reads as if it was never created.

Since:
1.0
See Also:
  • Constructor Details

    • ComponentQuery

      public ComponentQuery(Class<T> componentType)
      Creates a new instance of ComponentQuery to search for components of given type.
      Parameters:
      componentType - the type of the component(s) to search for
  • Method Details

    • withPropertyValue

      public <V> ComponentQuery<T> withPropertyValue(Function<T,V> getter, V expectedValue)
      Requires the given property to have expected value.
      Parameters:
      getter - the function to get the value of the property of the field, not null
      expectedValue - value to be compared with the one obtained by applying the getter function to a component instance
      Returns:
      this element query instance for chaining
    • withValue

      public <V> ComponentQuery<T> withValue(V expectedValue)
      Requires the component to be an implementation of HasValue interface and to have exactly the given value. Providing a null value as expectedValue has no effects since the filter will not be applied.
      Parameters:
      expectedValue - value to be compared with the one obtained by HasValue.getValue()
      Returns:
      this element query instance for chaining
      See Also:
    • withId

      public ComponentQuery<T> withId(String id)
      Requires the component to have the given id
      Parameters:
      id - the id to look up
      Returns:
      this element query instance for chaining
    • withTestId

      public ComponentQuery<T> withTestId(String testId)
      Requires the component to have the given data-testid attribute, as set by Component.setTestId(String).

      Test ids are expected to be unique within the UI, so a match always resolves to at most one component (just like withId(String)).

      Parameters:
      testId - the test id to look up
      Returns:
      this element query instance for chaining
      Since:
      1.1
      See Also:
    • withCondition

      public ComponentQuery<T> withCondition(Predicate<T> condition)
      Requires the components to satisfy the given condition.
      Parameters:
      condition - the condition to check against the components.
      Returns:
      this element query instance for chaining
    • withClassName

      public ComponentQuery<T> withClassName(String... className)
      Requires the components to have all the given CSS class names
      Parameters:
      className - required CSS class names, not null
      Returns:
      this element query instance for chaining
    • withoutClassName

      public ComponentQuery<T> withoutClassName(String... className)
      Requires the components to have none of the given CSS class names
      Parameters:
      className - CSS class names that component should not have, not null
      Returns:
      this element query instance for chaining
    • withTheme

      public ComponentQuery<T> withTheme(ThemeVariant variant)
      Add a theme variant that should be set on the target component. Prefer this over the raw-string withTheme(String) so the IDE can autocomplete the variant and a typo becomes a compile error.
      
       ui.find(Button.class).withTheme(ButtonVariant.LUMO_PRIMARY).all();
       
      Parameters:
      variant - the variant to require on the component
      Returns:
      this element query instance for chaining
      Since:
      1.1
    • withTheme

      @Deprecated public ComponentQuery<T> withTheme(String theme)
      Deprecated.
      use withTheme(ThemeVariant) with the component's typed variant enum where possible ? it autocompletes in the IDE and turns typos into compile errors. This raw-string overload remains for callers that need to filter on a theme not surfaced through a ThemeVariant enum.
      Add theme that should be set on the target component.
      Parameters:
      theme - theme that should exist on the component.
      Returns:
      this element query instance for chaining
    • withoutTheme

      public ComponentQuery<T> withoutTheme(ThemeVariant variant)
      Add a theme variant that should not be set on the target component. Prefer this over the raw-string withoutTheme(String) for the same reasons as withTheme(ThemeVariant).
      Parameters:
      variant - the variant that should not be present on the component
      Returns:
      this element query instance for chaining
      Since:
      1.1
    • withoutTheme

      @Deprecated public ComponentQuery<T> withoutTheme(String theme)
      Deprecated.
      use withoutTheme(ThemeVariant) with the component's typed variant enum where possible.
      Add theme that should not be available on the target component.
      Parameters:
      theme - theme that should not exist on the component.
      Returns:
      this element query instance for chaining
    • withCaption

      public ComponentQuery<T> withCaption(String caption)
      Requires the component to have a caption equal to the given text Concept of caption vary based on the component type. The check is usually made against the Element label property, but for some component (e.g. Button) the text content may be used.
      Parameters:
      caption - the text the component is expected to have as its caption
      Returns:
      this element query instance for chaining
    • withCaptionContaining

      public ComponentQuery<T> withCaptionContaining(String text)
      Requires the component to have a caption containing the given text Concept of caption vary based on the component type. The check is usually made against the Element label property, but for some component (e.g. Button) the text content may be used.
      Parameters:
      text - the text the component is expected to have as its caption
      Returns:
      this element query instance for chaining
    • withLabel

      public ComponentQuery<T> withLabel(String label)
      Requires the component's label property to be exactly the given value. Use this for form fields (TextField, ComboBox, etc.) where the end user identifies a field by its label.
      Parameters:
      label - the expected label, not null
      Returns:
      this element query instance for chaining
      Since:
      1.1
      See Also:
    • withLabelContaining

      public ComponentQuery<T> withLabelContaining(String text)
      Requires the component's label property to contain the given text.
      Parameters:
      text - substring to find in the label, not null
      Returns:
      this element query instance for chaining
      Since:
      1.1
    • withPlaceholder

      public ComponentQuery<T> withPlaceholder(String placeholder)
      Requires the component's placeholder to be exactly the given value. Useful for toolbar / search fields that intentionally omit a stacked label and identify themselves to the user via placeholder text instead.
      Parameters:
      placeholder - the expected placeholder, not null
      Returns:
      this element query instance for chaining
      Since:
      1.1
      See Also:
    • withPlaceholderContaining

      public ComponentQuery<T> withPlaceholderContaining(String text)
      Requires the component's placeholder to contain the given text. Comparison is case-sensitive. Read in the same way as withPlaceholder(String).
      Parameters:
      text - substring to find in the placeholder, not null
      Returns:
      this element query instance for chaining
      Since:
      1.1
    • withAriaLabel

      public ComponentQuery<T> withAriaLabel(String ariaLabel)
      Requires the component's aria-label attribute to be exactly the given value. Useful for components like Button that don't carry a visible label property but identify themselves to assistive technology via aria-label.
      Parameters:
      ariaLabel - the expected aria-label, not null
      Returns:
      this element query instance for chaining
      Since:
      1.1
    • withAriaLabelContaining

      public ComponentQuery<T> withAriaLabelContaining(String text)
      Requires the component's aria-label attribute to contain the given text.
      Parameters:
      text - substring to find in the aria-label, not null
      Returns:
      this element query instance for chaining
      Since:
      1.1
    • withText

      public ComponentQuery<T> withText(String text)
      Requires the text content of the component to be equal to the given text
      Parameters:
      text - the text the component is expected to have as its content
      Returns:
      this element query instance for chaining
      See Also:
    • withTextContaining

      public ComponentQuery<T> withTextContaining(String text)
      Requires the text content of the component to contain the given text
      Parameters:
      text - the text the component is expected to have as its caption
      Returns:
      this element query instance for chaining
      See Also:
    • withResultsSize

      public ComponentQuery<T> withResultsSize(int count)
      Requires the search to find exactly the given number of components
      Parameters:
      count - the expected number of component retrieved by the search
      Returns:
      this element query instance for chaining
      Throws:
      IllegalArgumentException - if count is negative
    • withResultsSize

      public ComponentQuery<T> withResultsSize(int min, int max)
      Requires the search to find a number of components within given range
      Parameters:
      min - minimum number of components that should be found (inclusive)
      max - maximum number of components that should be found (inclusive)
      Returns:
      this element query instance for chaining
      Throws:
      IllegalArgumentException - if min or max are negative, or if min is greater than max
    • withMinResults

      public ComponentQuery<T> withMinResults(int min)
      Requires the search to find at least the given number of components
      Parameters:
      min - minimum number of components that should be found (inclusive)
      Returns:
      this element query instance for chaining
      Throws:
      IllegalArgumentException - if min or max are negative, or if min is greater than max
    • withMaxResults

      public ComponentQuery<T> withMaxResults(int max)
      Requires the search to find at most the given number of components
      Parameters:
      max - maximum number of components that should be found (inclusive)
      Returns:
      this element query instance for chaining
      Throws:
      IllegalArgumentException - if min or max are negative, or if min is greater than max
    • withAttribute

      public ComponentQuery<T> withAttribute(String attribute)
      Requires the search to find components with the given attribute set, independently of its value.
      Parameters:
      attribute - the name of the attribute, not null
      Returns:
      this element query instance for chaining
    • withAttribute

      public ComponentQuery<T> withAttribute(String attribute, String value)
      Requires the search to find components having the given attribute with exactly the expected value.
      Parameters:
      attribute - the name of the attribute, not null
      value - value expected to be set on attribute, not null
      Returns:
      this element query instance for chaining
    • withoutAttribute

      public ComponentQuery<T> withoutAttribute(String attribute)
      Requires the search to find components without the given attribute.
      Parameters:
      attribute - the name of the attribute, not null
      Returns:
      this element query instance for chaining
    • withoutAttribute

      public ComponentQuery<T> withoutAttribute(String attribute, String value)
      Requires the search to find components having the given attribute value different from the provided one, or to not have the attribute at all.
      Parameters:
      attribute - the name of the attribute, not null
      value - value expected not to be set on attribute, not null
      Returns:
      this element query instance for chaining
    • withinSlot

      public ComponentQuery<T> withinSlot(String slot)
      Requires the components to sit in the given named slot of the component that hosts them.

      A component is in slot name when an element carrying slot="name" is one of its ancestors, or is the component itself. The whole subtree below a slot belongs to it, however deeply nested: a button inside a footer Div is in the footer just like a button that is the footer. When slots nest, the outermost one ? the one closest to the search context ? decides.

      This filter narrows an already slot-aware search rather than widening one: an unfiltered find(Class) on a component returns matches from every one of its slots, and from the slots of the components nested in them, so withinSlot only drops what sits outside the named slot.

      Take this card, dumped with toPrettyTree() (the same tree TreeOnFailureExtension prints on failure), where the slotted elements show up as @slot='...':

       ??? Card[#card]
           ??? Button[#content]
           ??? Button[#title, @slot='header']
           ??? Div[#footer-bar, @slot='footer']
           ?   ??? Button[#save]
           ??? Button[#cancel, @slot='footer']
           ??? Card[#inner, @slot='footer']
               ??? Button[#open]
               ??? Button[#details, @slot='header']
       
      test(card).find(Button.class).withinSlot("footer").all() returns #save, #cancel, #open and #details ? everything the card put in its footer:
      • #cancel is itself the slot root.
      • #save is nested inside the slotted Div.
      • #open and #details are inside the inner card, which the outer card placed in its footer. What those nested components do with their own slots does not matter: the inner card's slot='header' does not take #details out of the outer card's footer.
      • #content is not returned: it is in the card's default slot, and no slot name matches a component that is not slotted.
      Because the outer slot wins, repeated slot names at different nesting levels stay separate: the card's header holds only #title, and #details counts as header content only once the inner card is itself the search context, which puts its header slot outermost:
      
       // [#save, #cancel, #open, #details]
       test(card).find(Button.class).withinSlot("footer").all();
      
       // [#title] ? #details is footer content of this card
       test(card).find(Button.class).withinSlot("header").all();
      
       // [#details] ? and header content of the inner one
       test(inner).find(Button.class).withinSlot("header").all();
       
      Not every component puts the attribute on the component it slots. Here a dialog holds a layout in its header and a button plus a card in its footer, and the dump shows no @slot at all:
       ??? Dialog[#dialog, opened='true', @role='dialog']
           ??? Button[#body]
           ??? Div[#header-bar]
           ?   ??? Button[#close]
           ??? Button[#ok]
           ??? Card[#card]
               ??? Button[#content]
       
      A dialog slots that content into wrapper elements which carry the attribute but have no component of their own, and the tree dump descends through them. This filter walks the element tree, so it still sees the slots: withinSlot("header-content") matches #close and withinSlot("footer") matches #ok and #content.

      The search context (see from(Component)) bounds the walk, so a slot the context itself is placed in does not leak into the result. Scoped to the card above, test(card).find(Button.class).withinSlot("footer").all() is therefore empty ? the footer slot the card sits in belongs to the dialog, not to the card ? while the same query scoped to the dialog, to any component in between, or to nothing at all does return #content. Widening the search context never drops matches: it can only bring further slots into view.

      Slot names are the ones the component uses in the browser, and they are component specific: Card and ConfirmDialog name their header slot header, while Dialog names it header-content, as above. A name no component is slotted under simply produces no results.

      This is not the same as withAttribute("slot", name): the attribute filter only matches a component that is itself the slot root, so on the card it finds #cancel but neither #save nor #open, and on the dialog it matches nothing at all.

      Parameters:
      slot - the name of the slot, not null nor blank
      Returns:
      this element query instance for chaining
      Throws:
      IllegalArgumentException - if slot is null or blank
    • thenOnFirst

      public <E extends Component> ComponentQuery<E> thenOnFirst(Class<E> componentType)
      Gets a new ComponentQuery to search for given component type on the context of first matching component for current query.
      Type Parameters:
      E - the type of the component(s) to search for
      Parameters:
      componentType - the type of the component(s) to search for
      Returns:
      a new query object, to search for nested components.
      Throws:
      NoSuchElementException - if first component is found
    • thenOn

      public <E extends Component> ComponentQuery<E> thenOn(int index, Class<E> componentType)
      Gets a new ComponentQuery to search for given component type on the context of the matching component at given index for current query. Index is 1-based. Given a zero or negative index or an index higher than the actual number of components found results in an IndexOutOfBoundsException.
      Type Parameters:
      E - the type of the component(s) to search for
      Parameters:
      componentType - the type of the component(s) to search for
      Returns:
      a new query object, to search for nested components.
      Throws:
      IllegalArgumentException - if index is zero or negative
      IndexOutOfBoundsException - if index is greater than the number of found components
      NoSuchElementException - if current query does not produce results
      See Also:
    • single

      public T single()
      Executes the search against current context and returns the component, expecting to find exactly one. Exceptions are thrown if the search produces zero or more than one result.
      Returns:
      the component of the type specified in the constructor.
      Throws:
      NoSuchElementException - if not exactly one component is found
    • first

      @Deprecated(since="10.0", forRemoval=true) public T first()
      Deprecated, for removal: This API element is subject to removal in a future version.
      Use single() for more reliable tests that assert exactly one matching component, or use atIndex(int) with an explicit index if selecting from multiple components is intentional.
      Executes the search against current context and returns the first result.

      Warning: This method can lead to flaky tests when multiple matching components exist, as it arbitrarily selects the first one without validation. Consider using single() instead, which asserts that exactly one component matches and fails immediately if multiple components are found, making tests more reliable and failures easier to diagnose.

      Returns:
      a component of the type specified in the constructor.
      Throws:
      NoSuchElementException - if no component is found
      See Also:
    • last

      public T last()
      Executes the search against current context and returns the last result.
      Returns:
      a component of the type specified in the constructor.
      Throws:
      NoSuchElementException - if no component is found
    • atIndex

      public T atIndex(int index)
      Executes the search against current context and returns the component at given index. Index is 1-based. Given a zero or negative index or an index higher than the actual number of components found results in an IndexOutOfBoundsException.
      Returns:
      the component of the type specified in the constructor.
      Throws:
      IllegalArgumentException - if index is zero or negative
      IndexOutOfBoundsException - if index is greater than the number of found components
      NoSuchElementException - if no component is found
    • id

      public T id(String id)
      Executes a search for a component with the given id.
      Parameters:
      id - the id to look up
      Returns:
      the component with the given id
      Throws:
      NoSuchElementException - if no component is found
    • testId

      public T testId(String testId)
      Executes a search for a component with the given data-testid attribute, as set by Component.setTestId(String).
      Parameters:
      testId - the test id to look up
      Returns:
      the component with the given test id
      Throws:
      NoSuchElementException - if no component is found
      Since:
      1.1
      See Also:
    • exists

      public boolean exists()
      Checks if this ComponentQuery describes existing components.
      Returns:
      true if components are found, otherwise false.
    • all

      public List<T> all()
      Executes the search against current context and returns a list of matching components.
      Returns:
      a list of found components, or an empty list if search does not produce results. Never null.
    • from

      public ComponentQuery<T> from(Component context)
      Sets the context to search inside. If a null value is given, the search will be performed againt the UI.
      Parameters:
      context - a component used as starting element for search.
      Returns:
      this component query instance for chaining.
    • find

      protected T find()