Skip to content

API reference

This page provides a complete reference for all public APIs in selenium-expect.

Quick navigation

expect(target, ...)

Create an assertion for the given target. Dispatches to the appropriate assertion class based on the target's type.

Supported targets

Target type Assertion class Example
WebElement ExpectElement expect(element).to_be_visible()
WebDriver ExpectDriver expect(driver).to_have_title("Page")
list[WebElement] ExpectList expect(elements).to_have_count(5)
Alert ExpectAlert expect(alert).to_have_text("Confirm?")
Select ExpectSelect expect(select).to_have_value("opt1")
ShadowRoot ExpectShadow expect(shadow).to_have_element(By.ID, "x")
WebDriver + by/value LocatorExpect expect(driver, by=By.ID, value="x").to_be_visible()

Parameters

Parameter Type Default Description
target Any — The object to assert on
by str None Locator strategy (for locator-based expect)
value str None Locator value (for locator-based expect)
locator tuple[str, str] None (by, value) tuple shorthand
message str None Custom message for error output
soft bool \| None None Enable soft assertion mode (None inherits global config)
timeout float None Override default timeout
polling float \| list[float] None Override default polling

selenium_expect._expect.Expect

Callable expect dispatcher with attached utilities.

Use expect(target) to create assertions, expect.poll(fn) for retry-based polling, and expect.configure(...) for pre-configured variants.

Source code in selenium_expect/_expect.py
class Expect:
    """Callable expect dispatcher with attached utilities.

    Use ``expect(target)`` to create assertions, ``expect.poll(fn)`` for
    retry-based polling, and ``expect.configure(...)`` for pre-configured
    variants.
    """

    def __call__(
        self,
        target: Any,
        /,
        *,
        message: str | None = None,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
        soft: bool | None = None,
        config: ExpectConfig | None = None,
        by: str | None = None,
        value: str | None = None,
        locator: tuple[str, str] | None = None,
    ) -> AssertionMixin:
        """Create an expect assertion for the given target.

        Dispatches to the appropriate assertion class via ``ASSERTION_REGISTRY``
        based on the target's type.

        If ``by`` and ``value`` are provided, a ``LocatorExpect`` is created
        that re-finds the element on each poll cycle.

        Alternatively, ``locator=(By.ID, 'foo')`` can be used as a tuple
        shorthand for ``by=..., value=...``.
        """
        if locator is not None:
            if by is not None or value is not None:
                raise ValueError("Cannot use both 'locator' and 'by/value' arguments")
            by, value = locator

        if (by is not None) != (value is not None):
            raise ValueError("Must provide both 'by' and 'value', or neither")

        if by is not None and value is not None:
            from selenium_expect._locator import LocatorExpect

            if not isinstance(target, WebDriver):
                raise TypeError("expect() with by/value requires a WebDriver target")

            effective_config = _effective_config(config, timeout, polling, soft)

            return LocatorExpect(
                driver=target,
                by=by,
                value=value,
                config=effective_config,
                message=message,
            )

        if target is None:
            raise TypeError("expect() does not support None as target")

        type_name = _resolve_target_type(target)
        cls = ASSERTION_REGISTRY.get(type_name)
        if cls is None:
            raise TypeError(f"expect() does not support target type '{type_name}'")

        assertion_cls = cast(type[AssertionMixin], cls)

        effective_config = _effective_config(config, timeout, polling, soft)

        return assertion_cls(target=target, config=effective_config, message=message)

    def poll(
        self,
        fn: Callable[[], Any],
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
        config: ExpectConfig | None = None,
    ) -> PollAssertion:
        """Create a ``PollAssertion`` for retry-based assertions on *fn*.

        Usage::

            expect.poll(lambda: driver.execute_script("return document.readyState"))
                .to_equal("complete")
        """
        return PollAssertion(fn, timeout=timeout, polling=polling, config=config)

    def configure(self, **defaults: Any) -> Callable[..., AssertionMixin]:
        """Create a pre-configured expect variant.

        Returns a callable that behaves like ``expect()`` with *defaults*
        pre-applied. Explicit kwargs from the caller override the defaults.

        Usage::

            fast_expect = expect.configure(timeout=1.0, polling=0.1)
            fast_expect(el).to_be_visible()
        """

        def _configured_expect(
            target: Any,
            /,
            **overrides: Any,
        ) -> AssertionMixin:
            merged: dict[str, Any] = {**defaults, **overrides}
            return self(target, **merged)

        def _configured_poll(
            fn: Callable[[], Any],
            /,
            **overrides: Any,
        ) -> PollAssertion:
            poll_keys = ("timeout", "polling", "config")
            merged = {
                **{k: v for k, v in defaults.items() if k in poll_keys},
                **overrides,
            }
            return self.poll(fn, **merged)

        _configured_expect.poll = _configured_poll  # type: ignore[attr-defined]
        return _configured_expect

__call__

__call__(target: Any, /, *, message: str | None = None, timeout: float | None = None, polling: float | list[float] | None = None, soft: bool | None = None, config: ExpectConfig | None = None, by: str | None = None, value: str | None = None, locator: tuple[str, str] | None = None) -> AssertionMixin

Create an expect assertion for the given target.

Dispatches to the appropriate assertion class via ASSERTION_REGISTRY based on the target's type.

If by and value are provided, a LocatorExpect is created that re-finds the element on each poll cycle.

Alternatively, locator=(By.ID, 'foo') can be used as a tuple shorthand for by=..., value=....

Source code in selenium_expect/_expect.py
def __call__(
    self,
    target: Any,
    /,
    *,
    message: str | None = None,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
    soft: bool | None = None,
    config: ExpectConfig | None = None,
    by: str | None = None,
    value: str | None = None,
    locator: tuple[str, str] | None = None,
) -> AssertionMixin:
    """Create an expect assertion for the given target.

    Dispatches to the appropriate assertion class via ``ASSERTION_REGISTRY``
    based on the target's type.

    If ``by`` and ``value`` are provided, a ``LocatorExpect`` is created
    that re-finds the element on each poll cycle.

    Alternatively, ``locator=(By.ID, 'foo')`` can be used as a tuple
    shorthand for ``by=..., value=...``.
    """
    if locator is not None:
        if by is not None or value is not None:
            raise ValueError("Cannot use both 'locator' and 'by/value' arguments")
        by, value = locator

    if (by is not None) != (value is not None):
        raise ValueError("Must provide both 'by' and 'value', or neither")

    if by is not None and value is not None:
        from selenium_expect._locator import LocatorExpect

        if not isinstance(target, WebDriver):
            raise TypeError("expect() with by/value requires a WebDriver target")

        effective_config = _effective_config(config, timeout, polling, soft)

        return LocatorExpect(
            driver=target,
            by=by,
            value=value,
            config=effective_config,
            message=message,
        )

    if target is None:
        raise TypeError("expect() does not support None as target")

    type_name = _resolve_target_type(target)
    cls = ASSERTION_REGISTRY.get(type_name)
    if cls is None:
        raise TypeError(f"expect() does not support target type '{type_name}'")

    assertion_cls = cast(type[AssertionMixin], cls)

    effective_config = _effective_config(config, timeout, polling, soft)

    return assertion_cls(target=target, config=effective_config, message=message)

configure

configure(**defaults: Any) -> Callable[..., AssertionMixin]

Create a pre-configured expect variant.

Returns a callable that behaves like expect() with defaults pre-applied. Explicit kwargs from the caller override the defaults.

Usage::

fast_expect = expect.configure(timeout=1.0, polling=0.1)
fast_expect(el).to_be_visible()
Source code in selenium_expect/_expect.py
def configure(self, **defaults: Any) -> Callable[..., AssertionMixin]:
    """Create a pre-configured expect variant.

    Returns a callable that behaves like ``expect()`` with *defaults*
    pre-applied. Explicit kwargs from the caller override the defaults.

    Usage::

        fast_expect = expect.configure(timeout=1.0, polling=0.1)
        fast_expect(el).to_be_visible()
    """

    def _configured_expect(
        target: Any,
        /,
        **overrides: Any,
    ) -> AssertionMixin:
        merged: dict[str, Any] = {**defaults, **overrides}
        return self(target, **merged)

    def _configured_poll(
        fn: Callable[[], Any],
        /,
        **overrides: Any,
    ) -> PollAssertion:
        poll_keys = ("timeout", "polling", "config")
        merged = {
            **{k: v for k, v in defaults.items() if k in poll_keys},
            **overrides,
        }
        return self.poll(fn, **merged)

    _configured_expect.poll = _configured_poll  # type: ignore[attr-defined]
    return _configured_expect

poll

poll(fn: Callable[[], Any], *, timeout: float | None = None, polling: float | list[float] | None = None, config: ExpectConfig | None = None) -> PollAssertion

Create a PollAssertion for retry-based assertions on fn.

Usage::

expect.poll(lambda: driver.execute_script("return document.readyState"))
    .to_equal("complete")
Source code in selenium_expect/_expect.py
def poll(
    self,
    fn: Callable[[], Any],
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
    config: ExpectConfig | None = None,
) -> PollAssertion:
    """Create a ``PollAssertion`` for retry-based assertions on *fn*.

    Usage::

        expect.poll(lambda: driver.execute_script("return document.readyState"))
            .to_equal("complete")
    """
    return PollAssertion(fn, timeout=timeout, polling=polling, config=config)

ExpectConfig

Immutable configuration dataclass for all assertions.

Fields

Field Type Default Description
timeout float 5.0 Default timeout in seconds
polling_interval float 0.5 Fixed polling interval
polling_intervals list[float] \| None None Backoff schedule
screenshot_on_failure bool False Capture screenshot on failure
screenshot_path str \| None None Screenshot directory
debug_mode bool False Debug logging
soft_mode bool False Soft assertion mode

Usage

from selenium_expect import ExpectConfig, expect

# Create a custom config
config = ExpectConfig(timeout=10, polling_interval=0.25, debug_mode=True)

# Use it per call or pre-apply it with expect.configure()
expect(element, config=config).to_be_visible()
debug_expect = expect.configure(config=config)
debug_expect(element).to_be_visible()

selenium_expect._config.ExpectConfig dataclass

Immutable configuration for expect assertions.

Use replace() to create a new instance with overridden fields. The global config singleton is mutated via the module-level setters.

Source code in selenium_expect/_config.py
@dataclass(frozen=True, slots=True)
class ExpectConfig:
    """Immutable configuration for expect assertions.

    Use ``replace()`` to create a new instance with overridden fields.
    The global config singleton is mutated via the module-level setters.
    """

    timeout: float = 5.0
    polling_interval: float = 0.5
    polling_intervals: Sequence[float] | None = None
    screenshot_on_failure: bool = False
    screenshot_path: str | None = None
    debug_mode: bool = False
    soft_mode: bool = False

    def __post_init__(self) -> None:
        if self.timeout < 0:
            raise ValueError(f"timeout must be >= 0, got {self.timeout}")
        if self.polling_interval < 0:
            raise ValueError(f"polling_interval must be >= 0, got {self.polling_interval}")
        if self.polling_intervals is not None:
            # Store as tuple so the frozen dataclass is truly immutable.
            object.__setattr__(self, "polling_intervals", tuple(self.polling_intervals))
            if len(self.polling_intervals) == 0:
                raise ValueError("polling_intervals must not be empty; use None for fixed interval")
            for i, interval in enumerate(self.polling_intervals):
                if interval < 0:
                    raise ValueError(f"polling_intervals[{i}] must be >= 0, got {interval}")

    def replace(self, **kwargs: Any) -> ExpectConfig:
        """Return a new instance with overridden fields."""
        return _replace(self, **kwargs)

replace

replace(**kwargs: Any) -> ExpectConfig

Return a new instance with overridden fields.

Source code in selenium_expect/_config.py
def replace(self, **kwargs: Any) -> ExpectConfig:
    """Return a new instance with overridden fields."""
    return _replace(self, **kwargs)

poll(fn, ...)

Create a PollAssertion for retry-based assertions on an arbitrary function.

Parameters

Parameter Type Default Description
fn Callable[[], Any] — Zero-argument callable to poll
timeout float None Override default timeout
polling float \| list[float] None Override default polling

Example

from selenium_expect import expect, poll

# Using expect.poll
expect.poll(lambda: driver.execute_script("return document.readyState")).to_equal("complete")

# Using standalone poll
poll(lambda: driver.current_url, timeout=10).to_match(r"https://.*\.example\.com")

selenium_expect._poll.poll

poll(fn: Callable[[], Any], *, timeout: float | None = None, polling: float | list[float] | None = None, config: ExpectConfig | None = None) -> PollAssertion

Create a PollAssertion for retry-based assertions on fn.

Usage::

poll(lambda: driver.execute_script("return document.readyState"))
    .to_equal("complete")
Source code in selenium_expect/_poll.py
def poll(
    fn: Callable[[], Any],
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
    config: ExpectConfig | None = None,
) -> PollAssertion:
    """Create a ``PollAssertion`` for retry-based assertions on *fn*.

    Usage::

        poll(lambda: driver.execute_script("return document.readyState"))
            .to_equal("complete")
    """
    return PollAssertion(fn, timeout=timeout, polling=polling, config=config)

PollAssertion

Assertion over an arbitrary function with retry loop.

Methods

Method Description
to_equal(expected) Assert fn() == expected
to_be_truthy() Assert bool(fn()) is True
to_be_falsy() Assert bool(fn()) is False
to_be_none() Assert fn() is None
to_contain(expected) Assert expected in fn()
to_match(pattern) Assert re.search(pattern, str(fn())) matches
to_be_greater_than(expected) Assert fn() > expected
to_be_less_than(expected) Assert fn() < expected
to_be_in_list(expected) Assert fn() in expected
to_have_length(expected) Assert len(fn()) == expected

selenium_expect._poll.PollAssertion

Assertion over an arbitrary function with retry loop.

Source code in selenium_expect/_poll.py
class PollAssertion:
    """Assertion over an arbitrary function with retry loop."""

    def __init__(
        self,
        fn: Callable[[], Any],
        timeout: float | None = None,
        polling: float | list[float] | None = None,
        config: ExpectConfig | None = None,
    ) -> None:
        self._fn = fn
        self._config = config if config is not None else get_config()
        self._timeout = _normalize_timeout(timeout) if timeout is not None else self._config.timeout
        if self._timeout < 0:
            raise ValueError(f"timeout must be >= 0, got {self._timeout}")
        if polling is None:
            self._polling_interval = self._config.polling_interval
            self._polling_intervals = self._config.polling_intervals
        elif isinstance(polling, list):
            if len(polling) == 0:
                raise ValueError("polling list must not be empty; use a float for fixed interval")
            self._polling_interval = 0.5
            self._polling_intervals = polling
        else:
            self._polling_interval = _normalize_timeout(polling)
            self._polling_intervals = None
        if self._polling_interval < 0:
            raise ValueError(f"polling interval must be >= 0, got {self._polling_interval}")
        if self._polling_intervals is not None:
            for i, interval in enumerate(self._polling_intervals):
                if interval < 0:
                    raise ValueError(f"polling_intervals[{i}] must be >= 0, got {interval}")

    def _run(
        self,
        condition: Callable[[], tuple[bool, Any]],
        condition_name: str,
        expected: Any = None,
    ) -> None:
        """Execute the retry loop and raise on failure."""
        result = retry_until(
            condition=condition,
            timeout=self._timeout,
            polling_interval=self._polling_interval,
            polling_intervals=self._polling_intervals,
            debug=self._config.debug_mode,
        )
        if result.passed:
            return
        error_msg = AssertionFormatter.format_error(
            entity="poll()",
            condition=condition_name,
            expected=expected,
            actual=result.actual_value,
            elapsed_ms=result.elapsed_ms,
            poll_count=result.poll_count,
            polling_interval=self._polling_interval,
            timeline=result.timeline,
        )
        if self._config.soft_mode:
            from selenium_expect._soft import SoftAssertionCollector

            SoftAssertionCollector.add_failure(error_msg)
        else:
            raise AssertionError(error_msg)

    def to_equal(self, expected: Any) -> Self:
        """Assert fn() == expected."""
        fn = self._fn

        def condition() -> tuple[bool, Any]:
            actual = fn()
            return (actual == expected, actual)

        self._run(condition, f"to equal {expected!r}", expected)

        return self

    def to_be_truthy(self) -> Self:
        """Assert bool(fn()) is True."""
        fn = self._fn

        def condition() -> tuple[bool, Any]:
            actual = fn()
            return (bool(actual), actual)

        self._run(condition, "to be truthy", True)

        return self

    def to_be_falsy(self) -> Self:
        """Assert bool(fn()) is False."""
        fn = self._fn

        def condition() -> tuple[bool, Any]:
            actual = fn()
            return (not bool(actual), actual)

        self._run(condition, "to be falsy", False)

        return self

    def to_be_none(self) -> Self:
        """Assert fn() is None."""
        fn = self._fn

        def condition() -> tuple[bool, Any]:
            actual = fn()
            return (actual is None, actual)

        self._run(condition, "to be None", None)

        return self

    def to_contain(self, expected: Any) -> Self:
        """Assert expected in fn()."""
        fn = self._fn

        def condition() -> tuple[bool, Any]:
            actual = fn()
            if actual is None:
                return (False, actual)
            try:
                return (expected in actual, actual)
            except TypeError:
                return (False, f"not iterable: {actual!r}")

        self._run(condition, f"to contain {expected!r}", expected)

        return self

    def to_match(self, pattern: str) -> Self:
        """Assert re.search(pattern, str(fn()))."""
        fn = self._fn

        def condition() -> tuple[bool, Any]:
            actual = fn()
            return (re.search(pattern, str(actual)) is not None, actual)

        self._run(condition, f"to match {pattern!r}", pattern)

        return self

    def to_be_greater_than(self, expected: Any) -> Self:
        """Assert fn() > expected."""
        fn = self._fn

        def condition() -> tuple[bool, Any]:
            actual = fn()
            try:
                return (actual > expected, actual)
            except TypeError:
                return (False, f"not comparable: {actual!r} > {expected!r}")

        self._run(condition, f"to be greater than {expected}", expected)

        return self

    def to_be_less_than(self, expected: Any) -> Self:
        """Assert fn() < expected."""
        fn = self._fn

        def condition() -> tuple[bool, Any]:
            actual = fn()
            try:
                return (actual < expected, actual)
            except TypeError:
                return (False, f"not comparable: {actual!r} < {expected!r}")

        self._run(condition, f"to be less than {expected}", expected)

        return self

    def to_be_in_list(self, expected: list[Any]) -> Self:
        """Assert fn() in expected."""
        fn = self._fn

        def condition() -> tuple[bool, Any]:
            actual = fn()
            return (actual in expected, actual)

        self._run(condition, f"to be in {expected!r}", expected)

        return self

    def to_have_length(self, expected: int) -> Self:
        """Assert len(fn()) == expected."""
        fn = self._fn

        def condition() -> tuple[bool, Any]:
            actual = fn()
            try:
                actual_len = len(actual)
            except TypeError:
                return (False, f"no len() for {actual!r}")
            return (actual_len == expected, actual_len)

        self._run(condition, f"to have length {expected}", expected)

        return self

to_be_falsy

to_be_falsy() -> Self

Assert bool(fn()) is False.

Source code in selenium_expect/_poll.py
def to_be_falsy(self) -> Self:
    """Assert bool(fn()) is False."""
    fn = self._fn

    def condition() -> tuple[bool, Any]:
        actual = fn()
        return (not bool(actual), actual)

    self._run(condition, "to be falsy", False)

    return self

to_be_greater_than

to_be_greater_than(expected: Any) -> Self

Assert fn() > expected.

Source code in selenium_expect/_poll.py
def to_be_greater_than(self, expected: Any) -> Self:
    """Assert fn() > expected."""
    fn = self._fn

    def condition() -> tuple[bool, Any]:
        actual = fn()
        try:
            return (actual > expected, actual)
        except TypeError:
            return (False, f"not comparable: {actual!r} > {expected!r}")

    self._run(condition, f"to be greater than {expected}", expected)

    return self

to_be_in_list

to_be_in_list(expected: list[Any]) -> Self

Assert fn() in expected.

Source code in selenium_expect/_poll.py
def to_be_in_list(self, expected: list[Any]) -> Self:
    """Assert fn() in expected."""
    fn = self._fn

    def condition() -> tuple[bool, Any]:
        actual = fn()
        return (actual in expected, actual)

    self._run(condition, f"to be in {expected!r}", expected)

    return self

to_be_less_than

to_be_less_than(expected: Any) -> Self

Assert fn() < expected.

Source code in selenium_expect/_poll.py
def to_be_less_than(self, expected: Any) -> Self:
    """Assert fn() < expected."""
    fn = self._fn

    def condition() -> tuple[bool, Any]:
        actual = fn()
        try:
            return (actual < expected, actual)
        except TypeError:
            return (False, f"not comparable: {actual!r} < {expected!r}")

    self._run(condition, f"to be less than {expected}", expected)

    return self

to_be_none

to_be_none() -> Self

Assert fn() is None.

Source code in selenium_expect/_poll.py
def to_be_none(self) -> Self:
    """Assert fn() is None."""
    fn = self._fn

    def condition() -> tuple[bool, Any]:
        actual = fn()
        return (actual is None, actual)

    self._run(condition, "to be None", None)

    return self

to_be_truthy

to_be_truthy() -> Self

Assert bool(fn()) is True.

Source code in selenium_expect/_poll.py
def to_be_truthy(self) -> Self:
    """Assert bool(fn()) is True."""
    fn = self._fn

    def condition() -> tuple[bool, Any]:
        actual = fn()
        return (bool(actual), actual)

    self._run(condition, "to be truthy", True)

    return self

to_contain

to_contain(expected: Any) -> Self

Assert expected in fn().

Source code in selenium_expect/_poll.py
def to_contain(self, expected: Any) -> Self:
    """Assert expected in fn()."""
    fn = self._fn

    def condition() -> tuple[bool, Any]:
        actual = fn()
        if actual is None:
            return (False, actual)
        try:
            return (expected in actual, actual)
        except TypeError:
            return (False, f"not iterable: {actual!r}")

    self._run(condition, f"to contain {expected!r}", expected)

    return self

to_equal

to_equal(expected: Any) -> Self

Assert fn() == expected.

Source code in selenium_expect/_poll.py
def to_equal(self, expected: Any) -> Self:
    """Assert fn() == expected."""
    fn = self._fn

    def condition() -> tuple[bool, Any]:
        actual = fn()
        return (actual == expected, actual)

    self._run(condition, f"to equal {expected!r}", expected)

    return self

to_have_length

to_have_length(expected: int) -> Self

Assert len(fn()) == expected.

Source code in selenium_expect/_poll.py
def to_have_length(self, expected: int) -> Self:
    """Assert len(fn()) == expected."""
    fn = self._fn

    def condition() -> tuple[bool, Any]:
        actual = fn()
        try:
            actual_len = len(actual)
        except TypeError:
            return (False, f"no len() for {actual!r}")
        return (actual_len == expected, actual_len)

    self._run(condition, f"to have length {expected}", expected)

    return self

to_match

to_match(pattern: str) -> Self

Assert re.search(pattern, str(fn())).

Source code in selenium_expect/_poll.py
def to_match(self, pattern: str) -> Self:
    """Assert re.search(pattern, str(fn()))."""
    fn = self._fn

    def condition() -> tuple[bool, Any]:
        actual = fn()
        return (re.search(pattern, str(actual)) is not None, actual)

    self._run(condition, f"to match {pattern!r}", pattern)

    return self

extend(name)

Decorator to register a custom matcher under name.

Parameters

Parameter Type Description
name str Method name to register (e.g. "to_be_in_viewport")

Matcher signature

def my_matcher(target: Any, *args, **kwargs) -> tuple[bool, Any]:
    ...
    return (passed, actual_value)

Example

from selenium_expect import extend

@extend("to_have_trimmed_text")
def check_trimmed_text(element, expected: str):
    actual = element.text.strip()
    return (actual == expected, actual)

# Usage
expect(element).to_have_trimmed_text("Hello!")
expect(element).not_.to_have_trimmed_text("  Hello!  ")

selenium_expect._matcher.extend

extend(name: str) -> Callable[[_MatcherFn], _MatcherFn]

Decorator to register a custom matcher under name.

Usage::

@extend("to_be_in_viewport")
def check_in_viewport(element: Any) -> tuple[bool, Any]:
    ...
    return (passed, actual_value)

The matcher function receives the assertion's _target as its first argument and must return a (bool, Any) tuple where the bool indicates pass/fail and the Any is the actual value for error reporting.

name must be a valid public identifier. If it collides with an existing assertion method (e.g. to_be_visible), the built-in method takes precedence on assertion classes that define it.

Source code in selenium_expect/_matcher.py
def extend(name: str) -> Callable[[_MatcherFn], _MatcherFn]:
    """Decorator to register a custom matcher under *name*.

    Usage::

        @extend("to_be_in_viewport")
        def check_in_viewport(element: Any) -> tuple[bool, Any]:
            ...
            return (passed, actual_value)

    The matcher function receives the assertion's ``_target`` as its
    first argument and must return a ``(bool, Any)`` tuple where the
    bool indicates pass/fail and the Any is the actual value for
    error reporting.

    *name* must be a valid public identifier. If it collides with an
    existing assertion method (e.g. ``to_be_visible``), the built-in
    method takes precedence on assertion classes that define it.
    """
    if not name.isidentifier() or name.startswith("_"):
        raise ValueError(f"Invalid matcher name: {name!r}")

    def decorator(fn: Callable[..., tuple[bool, Any]]) -> Callable[..., tuple[bool, Any]]:
        CustomMatcherRegistry.register(name, fn)
        fn._selenium_expect_matcher = name  # type: ignore[attr-defined]
        return fn

    return decorator

merge_expects(*modules)

Combine custom matchers from multiple modules into the registry.

Parameters

Parameter Type Description
*modules ModuleType \| str Modules or importable module paths

Example

from selenium_expect import merge_expects

# Pass module objects
import my_project.matchers
import my_project.custom_assertions
merge_expects(my_project.matchers, my_project.custom_assertions)

# Or pass importable strings
merge_expects("my_project.matchers", "my_project.custom_assertions")

selenium_expect._matcher.merge_expects

merge_expects(*modules: ModuleType | str) -> list[str]

Combine custom matchers from multiple modules into the registry.

Each module should have used @extend to register matchers. Pass modules as objects or importable strings.

Usage::

import my_matchers
merge_expects(my_matchers)

# or by import path:
merge_expects("my_project.matchers")

Returns the list of newly registered matcher names.

Source code in selenium_expect/_matcher.py
def merge_expects(*modules: ModuleType | str) -> list[str]:
    """Combine custom matchers from multiple modules into the registry.

    Each module should have used ``@extend`` to register matchers.
    Pass modules as objects or importable strings.

    Usage::

        import my_matchers
        merge_expects(my_matchers)

        # or by import path:
        merge_expects("my_project.matchers")

    Returns the list of newly registered matcher names.
    """
    import importlib

    resolved: list[ModuleType] = []
    for mod in modules:
        if isinstance(mod, str):
            resolved.append(importlib.import_module(mod))
        else:
            resolved.append(mod)
    return CustomMatcherRegistry.merge_from(*resolved)

SoftAssertionCollector

Collects soft assertion failures for deferred raising.

Methods

Method Description
reset() Clear all collected failures
get_failures() Return list of failure messages
assert_all() Raise AssertionError if any failures, then reset

Example

from selenium_expect import expect, SoftAssertionCollector, assert_all

SoftAssertionCollector.reset()

expect(element, soft=True).to_be_visible()
expect(element, soft=True).to_have_text("Hello")

failures = SoftAssertionCollector.get_failures()
if failures:
    print(f"{len(failures)} failures collected")

assert_all()  # raises if any failures

selenium_expect._soft.SoftAssertionCollector

Collects soft assertion failures for deferred raising.

Failures are stored per execution context (ContextVar): each thread and each async task has its own list.

Source code in selenium_expect/_soft.py
class SoftAssertionCollector:
    """Collects soft assertion failures for deferred raising.

    Failures are stored per execution context (``ContextVar``): each
    thread and each async task has its own list.
    """

    _failures: ClassVar[ContextVar[list[str] | None]] = ContextVar(
        "soft_assertion_failures", default=None
    )

    @classmethod
    def _current(cls) -> list[str]:
        """Return this context's failure list, creating it on first use."""
        failures = cls._failures.get()
        if failures is None:
            failures = []
            cls._failures.set(failures)
        return failures

    @classmethod
    def add_failure(cls, message: str) -> None:
        """Record a soft assertion failure."""
        cls._current().append(message)

    @classmethod
    def get_failures(cls) -> list[str]:
        """Return all collected failures in this context."""
        return list(cls._current())

    @classmethod
    def reset(cls) -> None:
        """Clear all collected failures in this context."""
        cls._failures.set([])

    @classmethod
    def assert_all(cls) -> None:
        """Raise ``AssertionError`` if any failures were collected, then reset."""
        failures = cls._current()
        if not failures:
            return
        messages = list(failures)
        cls.reset()
        combined = "\n---\n".join(messages)
        raise AssertionError(f"Soft assertion failures ({len(messages)}):\n{combined}")

add_failure classmethod

add_failure(message: str) -> None

Record a soft assertion failure.

Source code in selenium_expect/_soft.py
@classmethod
def add_failure(cls, message: str) -> None:
    """Record a soft assertion failure."""
    cls._current().append(message)

assert_all classmethod

assert_all() -> None

Raise AssertionError if any failures were collected, then reset.

Source code in selenium_expect/_soft.py
@classmethod
def assert_all(cls) -> None:
    """Raise ``AssertionError`` if any failures were collected, then reset."""
    failures = cls._current()
    if not failures:
        return
    messages = list(failures)
    cls.reset()
    combined = "\n---\n".join(messages)
    raise AssertionError(f"Soft assertion failures ({len(messages)}):\n{combined}")

get_failures classmethod

get_failures() -> list[str]

Return all collected failures in this context.

Source code in selenium_expect/_soft.py
@classmethod
def get_failures(cls) -> list[str]:
    """Return all collected failures in this context."""
    return list(cls._current())

reset classmethod

reset() -> None

Clear all collected failures in this context.

Source code in selenium_expect/_soft.py
@classmethod
def reset(cls) -> None:
    """Clear all collected failures in this context."""
    cls._failures.set([])

assert_all()

Raise AssertionError if any soft failures were collected, then reset.

Example

from selenium_expect import expect, assert_all

expect(element, soft=True).to_be_visible()
expect(element, soft=True).to_have_text("Hello")

assert_all()  # raises AssertionError with combined message if any failed

selenium_expect._soft.assert_all

assert_all() -> None

Raise AssertionError if any soft failures were collected, then reset.

Convenience wrapper around SoftAssertionCollector.assert_all().

Source code in selenium_expect/_soft.py
def assert_all() -> None:
    """Raise ``AssertionError`` if any soft failures were collected, then reset.

    Convenience wrapper around ``SoftAssertionCollector.assert_all()``.
    """
    SoftAssertionCollector.assert_all()

Configuration setters

set_default_timeout(seconds)

Set the global default timeout for all assertions.

from selenium_expect import set_default_timeout

set_default_timeout(10)     # 10 seconds
set_default_timeout(5000)   # interpreted as 5000ms = 5 seconds (int >= 1000)

selenium_expect._config.set_default_timeout

set_default_timeout(seconds: float) -> None

Set the default timeout for all expect assertions.

Any value >= 1000 is interpreted as milliseconds (consistent with expect(timeout=...)).

Source code in selenium_expect/_config.py
def set_default_timeout(seconds: float) -> None:
    """Set the default timeout for all expect assertions.

    Any value >= 1000 is interpreted as milliseconds
    (consistent with ``expect(timeout=...)``).
    """
    global _global_config
    _global_config = _global_config.replace(timeout=normalize_timeout(seconds))

set_default_polling_interval(seconds)

Set the global default polling interval (fixed).

from selenium_expect import set_default_polling_interval

set_default_polling_interval(0.25)

selenium_expect._config.set_default_polling_interval

set_default_polling_interval(seconds: float) -> None

Set the default polling interval for all expect assertions.

Source code in selenium_expect/_config.py
def set_default_polling_interval(seconds: float) -> None:
    """Set the default polling interval for all expect assertions."""
    global _global_config
    _global_config = _global_config.replace(polling_interval=seconds)

set_default_polling_intervals(intervals)

Set a backoff schedule for polling. The list is cycled through during the retry loop.

from selenium_expect import set_default_polling_intervals

set_default_polling_intervals([0.1, 0.2, 0.5, 1.0])

selenium_expect._config.set_default_polling_intervals

set_default_polling_intervals(intervals: Sequence[float]) -> None

Set a backoff schedule for polling intervals.

Source code in selenium_expect/_config.py
def set_default_polling_intervals(intervals: Sequence[float]) -> None:
    """Set a backoff schedule for polling intervals."""
    global _global_config
    _global_config = _global_config.replace(polling_intervals=intervals)

set_screenshot_on_failure(enabled, path=None)

Enable automatic screenshot capture on assertion failure.

from selenium_expect import set_screenshot_on_failure

set_screenshot_on_failure(True, path="./screenshots/")

selenium_expect._config.set_screenshot_on_failure

set_screenshot_on_failure(enabled: bool, path: str | None = None) -> None

Enable or disable screenshot capture on assertion failure.

Source code in selenium_expect/_config.py
def set_screenshot_on_failure(enabled: bool, path: str | None = None) -> None:
    """Enable or disable screenshot capture on assertion failure."""
    global _global_config
    _global_config = _global_config.replace(
        screenshot_on_failure=enabled,
        screenshot_path=path if path is not None else "./screenshots/",
    )

set_debug_mode(enabled)

Enable debug logging for retry loops. Prints poll count, elapsed time, and actual values.

from selenium_expect import set_debug_mode

set_debug_mode(True)

selenium_expect._config.set_debug_mode

set_debug_mode(enabled: bool) -> None

Enable or disable debug logging for retry loops.

Source code in selenium_expect/_config.py
def set_debug_mode(enabled: bool) -> None:
    """Enable or disable debug logging for retry loops."""
    global _global_config
    _global_config = _global_config.replace(debug_mode=enabled)

get_config()

Return the current global ExpectConfig instance.

from selenium_expect import get_config

config = get_config()
print(f"Timeout: {config.timeout}s, Polling: {config.polling_interval}s")

selenium_expect._config.get_config

get_config() -> ExpectConfig

Return the current global config.

Source code in selenium_expect/_config.py
def get_config() -> ExpectConfig:
    """Return the current global config."""
    return _global_config

Assertion classes

ExpectElement

Assertions for WebElement objects. Provides methods for visibility, state, text, attributes, CSS, identity, position, accessibility, shadow DOM, and JavaScript properties.

Key method categories:

  • State: to_be_visible, to_be_hidden, to_be_present, to_be_absent, to_be_enabled, to_be_disabled, to_be_selected, to_be_unselected, to_be_checked, to_be_unchecked, to_be_clickable, to_be_editable, to_be_readonly, to_be_focused, to_be_empty, to_be_stale
  • Text: to_have_text, to_have_text_contains, to_have_text_matches, to_have_text_empty, to_have_text_not_empty, to_have_text_starting_with, to_have_text_ending_with, to_have_text_in_list
  • Attributes: to_have_attribute, to_have_attribute_present, to_have_attribute_absent, to_have_attribute_contains, to_have_attribute_empty, to_have_attribute_in_list, to_have_attribute_matches, to_have_dom_attribute, to_have_dom_attribute_contains, to_have_class, to_have_class_contains, to_contain_class, to_have_class_in_list, to_have_class_matching, to_have_all_classes, to_have_id, to_have_value, to_have_value_contains, to_have_value_in_list, to_have_value_matches
  • CSS: to_have_css_property, to_have_css_property_contains, to_have_css_property_matches
  • Identity: to_have_tag, to_have_aria_role, to_have_aria_role_contains, to_have_aria_role_in_list, to_have_accessible_name, to_have_accessible_name_contains
  • Position: to_have_location, to_have_location_x, to_have_location_y, to_have_location_greater_than, to_have_location_less_than, to_have_location_once_scrolled_into_view, to_have_size, to_have_size_width, to_have_size_height, to_have_size_greater_than, to_have_size_less_than, to_have_rect
  • Properties/JS: to_have_property, to_have_property_contains, to_have_js_property
  • Shadow DOM: to_have_shadow_root, to_have_shadow_root_absent
  • Composition: to_satisfy_all, to_satisfy_any, to_satisfy_none

selenium_expect.assertions.element.ExpectElement

Bases: AssertionMixin

Assertions for WebElement state, text, attributes, CSS, identity, position.

Source code in selenium_expect/assertions/element.py
  15
  16
  17
  18
  19
  20
  21
  22
  23
  24
  25
  26
  27
  28
  29
  30
  31
  32
  33
  34
  35
  36
  37
  38
  39
  40
  41
  42
  43
  44
  45
  46
  47
  48
  49
  50
  51
  52
  53
  54
  55
  56
  57
  58
  59
  60
  61
  62
  63
  64
  65
  66
  67
  68
  69
  70
  71
  72
  73
  74
  75
  76
  77
  78
  79
  80
  81
  82
  83
  84
  85
  86
  87
  88
  89
  90
  91
  92
  93
  94
  95
  96
  97
  98
  99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183
 184
 185
 186
 187
 188
 189
 190
 191
 192
 193
 194
 195
 196
 197
 198
 199
 200
 201
 202
 203
 204
 205
 206
 207
 208
 209
 210
 211
 212
 213
 214
 215
 216
 217
 218
 219
 220
 221
 222
 223
 224
 225
 226
 227
 228
 229
 230
 231
 232
 233
 234
 235
 236
 237
 238
 239
 240
 241
 242
 243
 244
 245
 246
 247
 248
 249
 250
 251
 252
 253
 254
 255
 256
 257
 258
 259
 260
 261
 262
 263
 264
 265
 266
 267
 268
 269
 270
 271
 272
 273
 274
 275
 276
 277
 278
 279
 280
 281
 282
 283
 284
 285
 286
 287
 288
 289
 290
 291
 292
 293
 294
 295
 296
 297
 298
 299
 300
 301
 302
 303
 304
 305
 306
 307
 308
 309
 310
 311
 312
 313
 314
 315
 316
 317
 318
 319
 320
 321
 322
 323
 324
 325
 326
 327
 328
 329
 330
 331
 332
 333
 334
 335
 336
 337
 338
 339
 340
 341
 342
 343
 344
 345
 346
 347
 348
 349
 350
 351
 352
 353
 354
 355
 356
 357
 358
 359
 360
 361
 362
 363
 364
 365
 366
 367
 368
 369
 370
 371
 372
 373
 374
 375
 376
 377
 378
 379
 380
 381
 382
 383
 384
 385
 386
 387
 388
 389
 390
 391
 392
 393
 394
 395
 396
 397
 398
 399
 400
 401
 402
 403
 404
 405
 406
 407
 408
 409
 410
 411
 412
 413
 414
 415
 416
 417
 418
 419
 420
 421
 422
 423
 424
 425
 426
 427
 428
 429
 430
 431
 432
 433
 434
 435
 436
 437
 438
 439
 440
 441
 442
 443
 444
 445
 446
 447
 448
 449
 450
 451
 452
 453
 454
 455
 456
 457
 458
 459
 460
 461
 462
 463
 464
 465
 466
 467
 468
 469
 470
 471
 472
 473
 474
 475
 476
 477
 478
 479
 480
 481
 482
 483
 484
 485
 486
 487
 488
 489
 490
 491
 492
 493
 494
 495
 496
 497
 498
 499
 500
 501
 502
 503
 504
 505
 506
 507
 508
 509
 510
 511
 512
 513
 514
 515
 516
 517
 518
 519
 520
 521
 522
 523
 524
 525
 526
 527
 528
 529
 530
 531
 532
 533
 534
 535
 536
 537
 538
 539
 540
 541
 542
 543
 544
 545
 546
 547
 548
 549
 550
 551
 552
 553
 554
 555
 556
 557
 558
 559
 560
 561
 562
 563
 564
 565
 566
 567
 568
 569
 570
 571
 572
 573
 574
 575
 576
 577
 578
 579
 580
 581
 582
 583
 584
 585
 586
 587
 588
 589
 590
 591
 592
 593
 594
 595
 596
 597
 598
 599
 600
 601
 602
 603
 604
 605
 606
 607
 608
 609
 610
 611
 612
 613
 614
 615
 616
 617
 618
 619
 620
 621
 622
 623
 624
 625
 626
 627
 628
 629
 630
 631
 632
 633
 634
 635
 636
 637
 638
 639
 640
 641
 642
 643
 644
 645
 646
 647
 648
 649
 650
 651
 652
 653
 654
 655
 656
 657
 658
 659
 660
 661
 662
 663
 664
 665
 666
 667
 668
 669
 670
 671
 672
 673
 674
 675
 676
 677
 678
 679
 680
 681
 682
 683
 684
 685
 686
 687
 688
 689
 690
 691
 692
 693
 694
 695
 696
 697
 698
 699
 700
 701
 702
 703
 704
 705
 706
 707
 708
 709
 710
 711
 712
 713
 714
 715
 716
 717
 718
 719
 720
 721
 722
 723
 724
 725
 726
 727
 728
 729
 730
 731
 732
 733
 734
 735
 736
 737
 738
 739
 740
 741
 742
 743
 744
 745
 746
 747
 748
 749
 750
 751
 752
 753
 754
 755
 756
 757
 758
 759
 760
 761
 762
 763
 764
 765
 766
 767
 768
 769
 770
 771
 772
 773
 774
 775
 776
 777
 778
 779
 780
 781
 782
 783
 784
 785
 786
 787
 788
 789
 790
 791
 792
 793
 794
 795
 796
 797
 798
 799
 800
 801
 802
 803
 804
 805
 806
 807
 808
 809
 810
 811
 812
 813
 814
 815
 816
 817
 818
 819
 820
 821
 822
 823
 824
 825
 826
 827
 828
 829
 830
 831
 832
 833
 834
 835
 836
 837
 838
 839
 840
 841
 842
 843
 844
 845
 846
 847
 848
 849
 850
 851
 852
 853
 854
 855
 856
 857
 858
 859
 860
 861
 862
 863
 864
 865
 866
 867
 868
 869
 870
 871
 872
 873
 874
 875
 876
 877
 878
 879
 880
 881
 882
 883
 884
 885
 886
 887
 888
 889
 890
 891
 892
 893
 894
 895
 896
 897
 898
 899
 900
 901
 902
 903
 904
 905
 906
 907
 908
 909
 910
 911
 912
 913
 914
 915
 916
 917
 918
 919
 920
 921
 922
 923
 924
 925
 926
 927
 928
 929
 930
 931
 932
 933
 934
 935
 936
 937
 938
 939
 940
 941
 942
 943
 944
 945
 946
 947
 948
 949
 950
 951
 952
 953
 954
 955
 956
 957
 958
 959
 960
 961
 962
 963
 964
 965
 966
 967
 968
 969
 970
 971
 972
 973
 974
 975
 976
 977
 978
 979
 980
 981
 982
 983
 984
 985
 986
 987
 988
 989
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
class ExpectElement(AssertionMixin):
    """Assertions for WebElement state, text, attributes, CSS, identity, position."""

    def __init__(
        self,
        target: WebElement,
        config: ExpectConfig | None = None,
        message: str | None = None,
        negate: bool = False,
    ) -> None:
        super().__init__(target=target, config=config, message=message, negate=negate)

    # --- State ---

    def to_be_visible(
        self,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert element.is_displayed() == True."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            displayed = el.is_displayed()
            return (displayed, displayed)

        self._run_assertion(
            condition=condition,
            condition_name="to be visible",
            expected=True,
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_be_hidden(
        self,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert element.is_displayed() == False."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            displayed = el.is_displayed()
            return (not displayed, displayed)

        self._run_assertion(
            condition=condition,
            condition_name="to be hidden",
            expected=False,
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_be_enabled(
        self,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert element.is_enabled() == True."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            enabled = el.is_enabled()
            return (enabled, enabled)

        self._run_assertion(
            condition=condition,
            condition_name="to be enabled",
            expected=True,
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_be_disabled(
        self,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert element.is_enabled() == False."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            enabled = el.is_enabled()
            return (not enabled, enabled)

        self._run_assertion(
            condition=condition,
            condition_name="to be disabled",
            expected=False,
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_be_checked(
        self,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert element.is_selected() == True (checkbox/radio)."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            selected = el.is_selected()
            return (selected, selected)

        self._run_assertion(
            condition=condition,
            condition_name="to be checked",
            expected=True,
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_be_selected(
        self,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert element.is_selected() == True (option/checkbox/radio)."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            selected = el.is_selected()
            return (selected, selected)

        self._run_assertion(
            condition=condition,
            condition_name="to be selected",
            expected=True,
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_be_present(
        self,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert element exists in DOM (element.tag_name doesn't raise)."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            try:
                tag = el.tag_name
                return (True, tag)
            except Exception as exc:
                return (False, str(exc))

        self._run_assertion(
            condition=condition,
            condition_name="to be present",
            expected=True,
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_be_absent(
        self,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert element doesn't exist (raises StaleElementReferenceException
        or NoSuchElementException)."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            try:
                el.tag_name  # noqa: B018
                return (False, "present")
            except Exception:
                return (True, "absent")

        self._run_assertion(
            condition=condition,
            condition_name="to be absent",
            expected=True,
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_be_clickable(
        self,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert element.is_displayed() and element.is_enabled()."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            displayed = el.is_displayed()
            enabled = el.is_enabled()
            clickable = displayed and enabled
            return (clickable, {"displayed": displayed, "enabled": enabled})

        self._run_assertion(
            condition=condition,
            condition_name="to be clickable",
            expected=True,
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_be_stale(
        self,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert element is stale (any access raises StaleElementReferenceException)."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            try:
                el.tag_name  # noqa: B018
                return (False, "not stale")
            except Exception:
                return (True, "stale")

        self._run_assertion(
            condition=condition,
            condition_name="to be stale",
            expected=True,
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_be_unselected(
        self,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert element.is_selected() == False (semantic alias for not_.to_be_selected())."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            selected = el.is_selected()
            return (not selected, selected)

        self._run_assertion(
            condition=condition,
            condition_name="to be unselected",
            expected=False,
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_be_unchecked(
        self,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert element.is_selected() == False (semantic alias for not_.to_be_checked())."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            selected = el.is_selected()
            return (not selected, selected)

        self._run_assertion(
            condition=condition,
            condition_name="to be unchecked",
            expected=False,
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_be_focused(
        self,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert element is the active element (driver.switch_to.active_element == element)."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            driver = getattr(el, "parent", None)
            if driver is None:
                return (False, "no driver")
            active = driver.switch_to.active_element
            return (active.id == el.id, active)

        self._run_assertion(
            condition=condition,
            condition_name="to be focused",
            expected=True,
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_be_editable(
        self,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert element is editable (input/textarea, not readonly, not disabled)."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            tag = el.tag_name
            if tag not in ("input", "textarea"):
                return (False, f"tag={tag!r}")
            if not el.is_enabled():
                return (False, "disabled")
            readonly = el.get_attribute("readonly")
            if readonly is not None:
                return (False, "readonly")
            return (True, "editable")

        self._run_assertion(
            condition=condition,
            condition_name="to be editable",
            expected=True,
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_be_readonly(
        self,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert element is readonly (get_attribute('readonly') is not None)."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            actual = el.get_attribute("readonly")
            return (actual is not None, actual)

        self._run_assertion(
            condition=condition,
            condition_name="to be readonly",
            expected="not None",
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_be_empty(
        self,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert element.text.strip() == '' (no visible text)."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            actual = el.text
            return ((actual or "").strip() == "", actual)

        self._run_assertion(
            condition=condition,
            condition_name="to be empty",
            expected="",
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    # --- Text ---

    def to_have_text(
        self,
        text: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert element.text == text."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            actual = el.text
            return (actual == text, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have text {text!r}",
            expected=text,
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_text_contains(
        self,
        text: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert text in element.text."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            actual = el.text
            return (text in (actual or ""), actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have text containing {text!r}",
            expected=text,
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_text_matches(
        self,
        pattern: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert re.search(pattern, element.text)."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            actual = el.text
            return (re.search(pattern, actual or "") is not None, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have text matching {pattern!r}",
            expected=pattern,
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_text_empty(
        self,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert element.text == ''."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            actual = el.text
            return (actual == "", actual)

        self._run_assertion(
            condition=condition,
            condition_name="to have text empty",
            expected="",
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_text_not_empty(
        self,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert element.text != ''."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            actual = el.text
            return (bool(actual), actual)

        self._run_assertion(
            condition=condition,
            condition_name="to have text not empty",
            expected="non-empty",
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_text_starting_with(
        self,
        prefix: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert element.text.startswith(prefix)."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            actual = el.text
            return ((actual or "").startswith(prefix), actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have text starting with {prefix!r}",
            expected=prefix,
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_text_ending_with(
        self,
        suffix: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert element.text.endswith(suffix)."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            actual = el.text
            return ((actual or "").endswith(suffix), actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have text ending with {suffix!r}",
            expected=suffix,
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_text_in_list(
        self,
        *texts: str,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert element.text is one of *texts."""
        if not texts:
            raise ValueError("At least one text must be provided")
        el = self._target

        def condition() -> tuple[bool, Any]:
            actual = el.text
            return (actual in texts, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have text in {list(texts)!r}",
            expected=list(texts),
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_value(
        self,
        value: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert element.get_attribute('value') == value."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            actual = el.get_attribute("value")
            return (actual == value, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have value {value!r}",
            expected=value,
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_value_contains(
        self,
        value: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert value in element.get_attribute('value')."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            actual = el.get_attribute("value")
            return (value in (actual or ""), actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have value containing {value!r}",
            expected=value,
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_value_matches(
        self,
        pattern: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert re.search(pattern, element.get_attribute('value'))."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            actual = el.get_attribute("value")
            return (re.search(pattern, actual or "") is not None, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have value matching {pattern!r}",
            expected=pattern,
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_value_in_list(
        self,
        values: list[str],
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert element.get_attribute('value') in values."""
        if not values:
            raise ValueError("values list must not be empty")
        el = self._target

        def condition() -> tuple[bool, Any]:
            actual = el.get_attribute("value")
            return (actual in values, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have value in {values!r}",
            expected=values,
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    # --- Attributes ---

    def to_have_attribute(
        self,
        name: str,
        value: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert element.get_attribute(name) == value."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            actual = el.get_attribute(name)
            return (actual == value, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have attribute {name!r}={value!r}",
            expected=value,
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_attribute_contains(
        self,
        name: str,
        value: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert value in element.get_attribute(name)."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            actual = el.get_attribute(name)
            return (value in (actual or ""), actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have attribute {name!r} containing {value!r}",
            expected=value,
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_attribute_matches(
        self,
        name: str,
        pattern: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert re.search(pattern, element.get_attribute(name))."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            actual = el.get_attribute(name)
            return (re.search(pattern, actual or "") is not None, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have attribute {name!r} matching {pattern!r}",
            expected=pattern,
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_attribute_empty(
        self,
        name: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert element.get_attribute(name) == '' or None."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            actual = el.get_attribute(name)
            return (actual is None or actual == "", actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have attribute {name!r} empty",
            expected="empty or None",
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_attribute_present(
        self,
        name: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert element.get_attribute(name) is not None."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            actual = el.get_attribute(name)
            return (actual is not None, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have attribute {name!r} present",
            expected="present",
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_attribute_absent(
        self,
        name: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert element.get_attribute(name) is None."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            actual = el.get_attribute(name)
            return (actual is None, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have attribute {name!r} absent",
            expected="absent",
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_attribute_in_list(
        self,
        name: str,
        values: list[str],
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert element.get_attribute(name) in values."""
        if not values:
            raise ValueError("values list must not be empty")
        el = self._target

        def condition() -> tuple[bool, Any]:
            actual = el.get_attribute(name)
            return (actual in values, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have attribute {name!r} in {values!r}",
            expected=values,
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_dom_attribute(
        self,
        name: str,
        value: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert element.get_dom_attribute(name) == value."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            actual = el.get_dom_attribute(name)
            return (actual == value, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have DOM attribute {name!r}={value!r}",
            expected=value,
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_dom_attribute_contains(
        self,
        name: str,
        value: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert value in element.get_dom_attribute(name)."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            actual = el.get_dom_attribute(name)
            return (value in (actual or ""), actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have DOM attribute {name!r} containing {value!r}",
            expected=value,
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_property(
        self,
        name: str,
        value: Any,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert element.get_property(name) == value."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            actual = el.get_property(name)
            return (actual == value, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have property {name!r}={value!r}",
            expected=value,
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_property_contains(
        self,
        name: str,
        value: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert value in str(element.get_property(name))."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            actual = el.get_property(name)
            if actual is None:
                return (False, actual)
            return (value in str(actual), actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have property {name!r} containing {value!r}",
            expected=value,
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    # --- CSS properties ---

    def to_have_css_property(
        self,
        name: str,
        value: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert element.value_of_css_property(name) == value."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            actual = el.value_of_css_property(name)
            return (actual == value, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have CSS {name!r}={value!r}",
            expected=value,
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_css_property_contains(
        self,
        name: str,
        value: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert value in element.value_of_css_property(name)."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            actual = el.value_of_css_property(name)
            return (value in (actual or ""), actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have CSS {name!r} containing {value!r}",
            expected=value,
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_css_property_matches(
        self,
        name: str,
        pattern: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert re.search(pattern, element.value_of_css_property(name))."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            actual = el.value_of_css_property(name)
            return (re.search(pattern, actual or "") is not None, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have CSS {name!r} matching {pattern!r}",
            expected=pattern,
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    # --- Identity / DOM ---

    def to_have_tag(
        self,
        tag: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert element.tag_name == tag."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            actual = el.tag_name
            return (actual == tag, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have tag {tag!r}",
            expected=tag,
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_id(
        self,
        id: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert element.get_attribute('id') == id."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            actual = el.get_attribute("id")
            return (actual == id, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have id {id!r}",
            expected=id,
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_class(
        self,
        class_name: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert class_name in element.get_attribute('class').split()."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            actual = el.get_attribute("class")
            classes = (actual or "").split()
            return (class_name in classes, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have class {class_name!r}",
            expected=class_name,
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_class_contains(
        self,
        class_name: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert class_name in element.get_attribute('class') (substring)."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            actual = el.get_attribute("class")
            return (class_name in (actual or ""), actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have class containing {class_name!r}",
            expected=class_name,
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_contain_class(
        self,
        class_name: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert class_name in element.get_attribute('class').split() (alias of to_have_class)."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            actual = el.get_attribute("class")
            classes = (actual or "").split()
            return (class_name in classes, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to contain class {class_name!r}",
            expected=class_name,
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_class_matching(
        self,
        pattern: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert any class in element.get_attribute('class').split() matches pattern."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            actual = el.get_attribute("class")
            classes = (actual or "").split()
            return (any(re.search(pattern, c) for c in classes), actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have class matching {pattern!r}",
            expected=pattern,
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_all_classes(
        self,
        *classes: str,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert element has all specified classes."""
        if not classes:
            raise ValueError("At least one class must be provided")
        el = self._target

        def condition() -> tuple[bool, Any]:
            actual = el.get_attribute("class")
            elem_classes = set((actual or "").split())
            return (set(classes).issubset(elem_classes), actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have all classes {list(classes)!r}",
            expected=list(classes),
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_class_in_list(
        self,
        *classes: str,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert element has at least one of the specified classes."""
        if not classes:
            raise ValueError("At least one class must be provided")
        el = self._target

        def condition() -> tuple[bool, Any]:
            actual = el.get_attribute("class")
            elem_classes = set((actual or "").split())
            return (bool(elem_classes & set(classes)), actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have class in {list(classes)!r}",
            expected=list(classes),
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    # --- Position / dimensions ---

    def to_have_location(
        self,
        x: int,
        y: int,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert element.location == {'x': x, 'y': y}."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            loc = el.location
            actual = {"x": loc["x"], "y": loc["y"]}
            return (actual == {"x": x, "y": y}, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have location ({x}, {y})",
            expected={"x": x, "y": y},
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_location_x(
        self,
        x: int,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert element.location['x'] == x."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            actual = el.location["x"]
            return (actual == x, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have location x={x}",
            expected=x,
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_location_y(
        self,
        y: int,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert element.location['y'] == y."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            actual = el.location["y"]
            return (actual == y, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have location y={y}",
            expected=y,
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_size(
        self,
        width: int,
        height: int,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert element.size == {'width': width, 'height': height}."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            sz = el.size
            actual = {"width": sz["width"], "height": sz["height"]}
            return (actual == {"width": width, "height": height}, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have size ({width}x{height})",
            expected={"width": width, "height": height},
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_size_width(
        self,
        width: int,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert element.size['width'] == width."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            actual = el.size["width"]
            return (actual == width, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have size width={width}",
            expected=width,
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_size_height(
        self,
        height: int,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert element.size['height'] == height."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            actual = el.size["height"]
            return (actual == height, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have size height={height}",
            expected=height,
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_rect(
        self,
        x: int,
        y: int,
        width: int,
        height: int,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert element.rect matches all four values."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            rect = el.rect
            actual = {
                "x": rect["x"],
                "y": rect["y"],
                "width": rect["width"],
                "height": rect["height"],
            }
            expected = {"x": x, "y": y, "width": width, "height": height}
            return (actual == expected, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have rect ({x}, {y}, {width}x{height})",
            expected={"x": x, "y": y, "width": width, "height": height},
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_location_greater_than(
        self,
        x: int | None = None,
        y: int | None = None,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert element.location x and/or y are greater than given values."""
        if x is None and y is None:
            raise ValueError("At least one of x or y must be provided")
        el = self._target

        def condition() -> tuple[bool, Any]:
            loc = el.location
            actual = {"x": loc["x"], "y": loc["y"]}
            checks = []
            if x is not None:
                checks.append(loc["x"] > x)
            if y is not None:
                checks.append(loc["y"] > y)
            return (all(checks), actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have location > ({x}, {y})",
            expected=f"x>{x}, y>{y}",
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_location_less_than(
        self,
        x: int | None = None,
        y: int | None = None,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert element.location x and/or y are less than given values."""
        if x is None and y is None:
            raise ValueError("At least one of x or y must be provided")
        el = self._target

        def condition() -> tuple[bool, Any]:
            loc = el.location
            actual = {"x": loc["x"], "y": loc["y"]}
            checks = []
            if x is not None:
                checks.append(loc["x"] < x)
            if y is not None:
                checks.append(loc["y"] < y)
            return (all(checks), actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have location < ({x}, {y})",
            expected=f"x<{x}, y<{y}",
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_size_greater_than(
        self,
        width: int | None = None,
        height: int | None = None,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert element.size width and/or height are greater than given values."""
        if width is None and height is None:
            raise ValueError("At least one of width or height must be provided")
        el = self._target

        def condition() -> tuple[bool, Any]:
            sz = el.size
            actual = {"width": sz["width"], "height": sz["height"]}
            checks = []
            if width is not None:
                checks.append(sz["width"] > width)
            if height is not None:
                checks.append(sz["height"] > height)
            return (all(checks), actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have size > ({width}, {height})",
            expected=f"w>{width}, h>{height}",
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_size_less_than(
        self,
        width: int | None = None,
        height: int | None = None,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert element.size width and/or height are less than given values."""
        if width is None and height is None:
            raise ValueError("At least one of width or height must be provided")
        el = self._target

        def condition() -> tuple[bool, Any]:
            sz = el.size
            actual = {"width": sz["width"], "height": sz["height"]}
            checks = []
            if width is not None:
                checks.append(sz["width"] < width)
            if height is not None:
                checks.append(sz["height"] < height)
            return (all(checks), actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have size < ({width}, {height})",
            expected=f"w<{width}, h<{height}",
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_location_once_scrolled_into_view(
        self,
        x: int,
        y: int,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert element.location_once_scrolled_into_view == {'x': x, 'y': y}."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            loc = el.location_once_scrolled_into_view
            actual = {"x": loc["x"], "y": loc["y"]}
            return (actual == {"x": x, "y": y}, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have location once scrolled into view ({x}, {y})",
            expected={"x": x, "y": y},
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    # --- Accessibility (Selenium 4+) ---

    def to_have_aria_role(
        self,
        role: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert element.aria_role == role."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            actual = el.aria_role
            return (actual == role, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have aria role {role!r}",
            expected=role,
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_aria_role_contains(
        self,
        role: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert role in element.aria_role."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            actual = el.aria_role
            return (role in (actual or ""), actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have aria role containing {role!r}",
            expected=role,
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_aria_role_in_list(
        self,
        *roles: str,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert element.aria_role is one of *roles."""
        if not roles:
            raise ValueError("At least one role must be provided")
        el = self._target

        def condition() -> tuple[bool, Any]:
            actual = el.aria_role
            return (actual in roles, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have aria role in {list(roles)!r}",
            expected=list(roles),
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_accessible_name(
        self,
        name: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert element.accessible_name == name."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            actual = el.accessible_name
            return (actual == name, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have accessible name {name!r}",
            expected=name,
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_accessible_name_contains(
        self,
        name: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert name in element.accessible_name."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            actual = el.accessible_name
            return (name in (actual or ""), actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have accessible name containing {name!r}",
            expected=name,
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    # --- JavaScript property ---

    def to_have_js_property(
        self,
        name: str,
        value: Any,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert element JS property == value via execute_script."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            driver = getattr(el, "parent", None)
            if driver is None:
                return (False, "no driver")
            actual = driver.execute_script("return arguments[0][arguments[1]];", el, name)
            return (actual == value, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have JS property {name!r}={value!r}",
            expected=value,
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    # --- Shadow DOM ---

    def to_have_shadow_root(
        self,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert element.shadow_root is not None."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            actual = el.shadow_root
            return (actual is not None, actual)

        self._run_assertion(
            condition=condition,
            condition_name="to have shadow root",
            expected="not None",
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_shadow_root_absent(
        self,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert element.shadow_root is None."""
        el = self._target

        def condition() -> tuple[bool, Any]:
            actual = el.shadow_root
            return (actual is None, actual)

        self._run_assertion(
            condition=condition,
            condition_name="to have shadow root absent",
            expected="None",
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    # --- Overrides ---

    def _entity_description(self) -> str:
        el = self._target
        try:
            tag = el.tag_name
            elem_id = el.get_attribute("id")
            if elem_id:
                return f"<{tag} id={elem_id!r}>"
            return f"<{tag}>"
        except Exception:
            return repr(el)

    def _get_element_html(self) -> str | None:
        el = self._target
        try:
            html = el.get_attribute("outerHTML")
            return html if html else None
        except Exception:
            return None

to_be_absent

to_be_absent(*, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert element doesn't exist (raises StaleElementReferenceException or NoSuchElementException).

Source code in selenium_expect/assertions/element.py
def to_be_absent(
    self,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert element doesn't exist (raises StaleElementReferenceException
    or NoSuchElementException)."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        try:
            el.tag_name  # noqa: B018
            return (False, "present")
        except Exception:
            return (True, "absent")

    self._run_assertion(
        condition=condition,
        condition_name="to be absent",
        expected=True,
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_be_checked

to_be_checked(*, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert element.is_selected() == True (checkbox/radio).

Source code in selenium_expect/assertions/element.py
def to_be_checked(
    self,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert element.is_selected() == True (checkbox/radio)."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        selected = el.is_selected()
        return (selected, selected)

    self._run_assertion(
        condition=condition,
        condition_name="to be checked",
        expected=True,
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_be_clickable

to_be_clickable(*, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert element.is_displayed() and element.is_enabled().

Source code in selenium_expect/assertions/element.py
def to_be_clickable(
    self,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert element.is_displayed() and element.is_enabled()."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        displayed = el.is_displayed()
        enabled = el.is_enabled()
        clickable = displayed and enabled
        return (clickable, {"displayed": displayed, "enabled": enabled})

    self._run_assertion(
        condition=condition,
        condition_name="to be clickable",
        expected=True,
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_be_disabled

to_be_disabled(*, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert element.is_enabled() == False.

Source code in selenium_expect/assertions/element.py
def to_be_disabled(
    self,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert element.is_enabled() == False."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        enabled = el.is_enabled()
        return (not enabled, enabled)

    self._run_assertion(
        condition=condition,
        condition_name="to be disabled",
        expected=False,
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_be_editable

to_be_editable(*, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert element is editable (input/textarea, not readonly, not disabled).

Source code in selenium_expect/assertions/element.py
def to_be_editable(
    self,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert element is editable (input/textarea, not readonly, not disabled)."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        tag = el.tag_name
        if tag not in ("input", "textarea"):
            return (False, f"tag={tag!r}")
        if not el.is_enabled():
            return (False, "disabled")
        readonly = el.get_attribute("readonly")
        if readonly is not None:
            return (False, "readonly")
        return (True, "editable")

    self._run_assertion(
        condition=condition,
        condition_name="to be editable",
        expected=True,
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_be_empty

to_be_empty(*, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert element.text.strip() == '' (no visible text).

Source code in selenium_expect/assertions/element.py
def to_be_empty(
    self,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert element.text.strip() == '' (no visible text)."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        actual = el.text
        return ((actual or "").strip() == "", actual)

    self._run_assertion(
        condition=condition,
        condition_name="to be empty",
        expected="",
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_be_enabled

to_be_enabled(*, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert element.is_enabled() == True.

Source code in selenium_expect/assertions/element.py
def to_be_enabled(
    self,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert element.is_enabled() == True."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        enabled = el.is_enabled()
        return (enabled, enabled)

    self._run_assertion(
        condition=condition,
        condition_name="to be enabled",
        expected=True,
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_be_focused

to_be_focused(*, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert element is the active element (driver.switch_to.active_element == element).

Source code in selenium_expect/assertions/element.py
def to_be_focused(
    self,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert element is the active element (driver.switch_to.active_element == element)."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        driver = getattr(el, "parent", None)
        if driver is None:
            return (False, "no driver")
        active = driver.switch_to.active_element
        return (active.id == el.id, active)

    self._run_assertion(
        condition=condition,
        condition_name="to be focused",
        expected=True,
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_be_hidden

to_be_hidden(*, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert element.is_displayed() == False.

Source code in selenium_expect/assertions/element.py
def to_be_hidden(
    self,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert element.is_displayed() == False."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        displayed = el.is_displayed()
        return (not displayed, displayed)

    self._run_assertion(
        condition=condition,
        condition_name="to be hidden",
        expected=False,
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_be_present

to_be_present(*, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert element exists in DOM (element.tag_name doesn't raise).

Source code in selenium_expect/assertions/element.py
def to_be_present(
    self,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert element exists in DOM (element.tag_name doesn't raise)."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        try:
            tag = el.tag_name
            return (True, tag)
        except Exception as exc:
            return (False, str(exc))

    self._run_assertion(
        condition=condition,
        condition_name="to be present",
        expected=True,
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_be_readonly

to_be_readonly(*, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert element is readonly (get_attribute('readonly') is not None).

Source code in selenium_expect/assertions/element.py
def to_be_readonly(
    self,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert element is readonly (get_attribute('readonly') is not None)."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        actual = el.get_attribute("readonly")
        return (actual is not None, actual)

    self._run_assertion(
        condition=condition,
        condition_name="to be readonly",
        expected="not None",
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_be_selected

to_be_selected(*, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert element.is_selected() == True (option/checkbox/radio).

Source code in selenium_expect/assertions/element.py
def to_be_selected(
    self,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert element.is_selected() == True (option/checkbox/radio)."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        selected = el.is_selected()
        return (selected, selected)

    self._run_assertion(
        condition=condition,
        condition_name="to be selected",
        expected=True,
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_be_stale

to_be_stale(*, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert element is stale (any access raises StaleElementReferenceException).

Source code in selenium_expect/assertions/element.py
def to_be_stale(
    self,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert element is stale (any access raises StaleElementReferenceException)."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        try:
            el.tag_name  # noqa: B018
            return (False, "not stale")
        except Exception:
            return (True, "stale")

    self._run_assertion(
        condition=condition,
        condition_name="to be stale",
        expected=True,
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_be_unchecked

to_be_unchecked(*, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert element.is_selected() == False (semantic alias for not_.to_be_checked()).

Source code in selenium_expect/assertions/element.py
def to_be_unchecked(
    self,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert element.is_selected() == False (semantic alias for not_.to_be_checked())."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        selected = el.is_selected()
        return (not selected, selected)

    self._run_assertion(
        condition=condition,
        condition_name="to be unchecked",
        expected=False,
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_be_unselected

to_be_unselected(*, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert element.is_selected() == False (semantic alias for not_.to_be_selected()).

Source code in selenium_expect/assertions/element.py
def to_be_unselected(
    self,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert element.is_selected() == False (semantic alias for not_.to_be_selected())."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        selected = el.is_selected()
        return (not selected, selected)

    self._run_assertion(
        condition=condition,
        condition_name="to be unselected",
        expected=False,
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_be_visible

to_be_visible(*, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert element.is_displayed() == True.

Source code in selenium_expect/assertions/element.py
def to_be_visible(
    self,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert element.is_displayed() == True."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        displayed = el.is_displayed()
        return (displayed, displayed)

    self._run_assertion(
        condition=condition,
        condition_name="to be visible",
        expected=True,
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_contain_class

to_contain_class(class_name: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert class_name in element.get_attribute('class').split() (alias of to_have_class).

Source code in selenium_expect/assertions/element.py
def to_contain_class(
    self,
    class_name: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert class_name in element.get_attribute('class').split() (alias of to_have_class)."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        actual = el.get_attribute("class")
        classes = (actual or "").split()
        return (class_name in classes, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to contain class {class_name!r}",
        expected=class_name,
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_accessible_name

to_have_accessible_name(name: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert element.accessible_name == name.

Source code in selenium_expect/assertions/element.py
def to_have_accessible_name(
    self,
    name: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert element.accessible_name == name."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        actual = el.accessible_name
        return (actual == name, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have accessible name {name!r}",
        expected=name,
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_accessible_name_contains

to_have_accessible_name_contains(name: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert name in element.accessible_name.

Source code in selenium_expect/assertions/element.py
def to_have_accessible_name_contains(
    self,
    name: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert name in element.accessible_name."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        actual = el.accessible_name
        return (name in (actual or ""), actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have accessible name containing {name!r}",
        expected=name,
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_all_classes

to_have_all_classes(*classes: str, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert element has all specified classes.

Source code in selenium_expect/assertions/element.py
def to_have_all_classes(
    self,
    *classes: str,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert element has all specified classes."""
    if not classes:
        raise ValueError("At least one class must be provided")
    el = self._target

    def condition() -> tuple[bool, Any]:
        actual = el.get_attribute("class")
        elem_classes = set((actual or "").split())
        return (set(classes).issubset(elem_classes), actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have all classes {list(classes)!r}",
        expected=list(classes),
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_aria_role

to_have_aria_role(role: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert element.aria_role == role.

Source code in selenium_expect/assertions/element.py
def to_have_aria_role(
    self,
    role: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert element.aria_role == role."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        actual = el.aria_role
        return (actual == role, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have aria role {role!r}",
        expected=role,
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_aria_role_contains

to_have_aria_role_contains(role: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert role in element.aria_role.

Source code in selenium_expect/assertions/element.py
def to_have_aria_role_contains(
    self,
    role: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert role in element.aria_role."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        actual = el.aria_role
        return (role in (actual or ""), actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have aria role containing {role!r}",
        expected=role,
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_aria_role_in_list

to_have_aria_role_in_list(*roles: str, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert element.aria_role is one of *roles.

Source code in selenium_expect/assertions/element.py
def to_have_aria_role_in_list(
    self,
    *roles: str,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert element.aria_role is one of *roles."""
    if not roles:
        raise ValueError("At least one role must be provided")
    el = self._target

    def condition() -> tuple[bool, Any]:
        actual = el.aria_role
        return (actual in roles, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have aria role in {list(roles)!r}",
        expected=list(roles),
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_attribute

to_have_attribute(name: str, value: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert element.get_attribute(name) == value.

Source code in selenium_expect/assertions/element.py
def to_have_attribute(
    self,
    name: str,
    value: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert element.get_attribute(name) == value."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        actual = el.get_attribute(name)
        return (actual == value, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have attribute {name!r}={value!r}",
        expected=value,
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_attribute_absent

to_have_attribute_absent(name: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert element.get_attribute(name) is None.

Source code in selenium_expect/assertions/element.py
def to_have_attribute_absent(
    self,
    name: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert element.get_attribute(name) is None."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        actual = el.get_attribute(name)
        return (actual is None, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have attribute {name!r} absent",
        expected="absent",
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_attribute_contains

to_have_attribute_contains(name: str, value: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert value in element.get_attribute(name).

Source code in selenium_expect/assertions/element.py
def to_have_attribute_contains(
    self,
    name: str,
    value: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert value in element.get_attribute(name)."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        actual = el.get_attribute(name)
        return (value in (actual or ""), actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have attribute {name!r} containing {value!r}",
        expected=value,
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_attribute_empty

to_have_attribute_empty(name: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert element.get_attribute(name) == '' or None.

Source code in selenium_expect/assertions/element.py
def to_have_attribute_empty(
    self,
    name: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert element.get_attribute(name) == '' or None."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        actual = el.get_attribute(name)
        return (actual is None or actual == "", actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have attribute {name!r} empty",
        expected="empty or None",
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_attribute_in_list

to_have_attribute_in_list(name: str, values: list[str], *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert element.get_attribute(name) in values.

Source code in selenium_expect/assertions/element.py
def to_have_attribute_in_list(
    self,
    name: str,
    values: list[str],
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert element.get_attribute(name) in values."""
    if not values:
        raise ValueError("values list must not be empty")
    el = self._target

    def condition() -> tuple[bool, Any]:
        actual = el.get_attribute(name)
        return (actual in values, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have attribute {name!r} in {values!r}",
        expected=values,
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_attribute_matches

to_have_attribute_matches(name: str, pattern: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert re.search(pattern, element.get_attribute(name)).

Source code in selenium_expect/assertions/element.py
def to_have_attribute_matches(
    self,
    name: str,
    pattern: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert re.search(pattern, element.get_attribute(name))."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        actual = el.get_attribute(name)
        return (re.search(pattern, actual or "") is not None, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have attribute {name!r} matching {pattern!r}",
        expected=pattern,
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_attribute_present

to_have_attribute_present(name: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert element.get_attribute(name) is not None.

Source code in selenium_expect/assertions/element.py
def to_have_attribute_present(
    self,
    name: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert element.get_attribute(name) is not None."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        actual = el.get_attribute(name)
        return (actual is not None, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have attribute {name!r} present",
        expected="present",
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_class

to_have_class(class_name: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert class_name in element.get_attribute('class').split().

Source code in selenium_expect/assertions/element.py
def to_have_class(
    self,
    class_name: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert class_name in element.get_attribute('class').split()."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        actual = el.get_attribute("class")
        classes = (actual or "").split()
        return (class_name in classes, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have class {class_name!r}",
        expected=class_name,
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_class_contains

to_have_class_contains(class_name: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert class_name in element.get_attribute('class') (substring).

Source code in selenium_expect/assertions/element.py
def to_have_class_contains(
    self,
    class_name: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert class_name in element.get_attribute('class') (substring)."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        actual = el.get_attribute("class")
        return (class_name in (actual or ""), actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have class containing {class_name!r}",
        expected=class_name,
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_class_in_list

to_have_class_in_list(*classes: str, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert element has at least one of the specified classes.

Source code in selenium_expect/assertions/element.py
def to_have_class_in_list(
    self,
    *classes: str,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert element has at least one of the specified classes."""
    if not classes:
        raise ValueError("At least one class must be provided")
    el = self._target

    def condition() -> tuple[bool, Any]:
        actual = el.get_attribute("class")
        elem_classes = set((actual or "").split())
        return (bool(elem_classes & set(classes)), actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have class in {list(classes)!r}",
        expected=list(classes),
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_class_matching

to_have_class_matching(pattern: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert any class in element.get_attribute('class').split() matches pattern.

Source code in selenium_expect/assertions/element.py
def to_have_class_matching(
    self,
    pattern: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert any class in element.get_attribute('class').split() matches pattern."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        actual = el.get_attribute("class")
        classes = (actual or "").split()
        return (any(re.search(pattern, c) for c in classes), actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have class matching {pattern!r}",
        expected=pattern,
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_css_property

to_have_css_property(name: str, value: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert element.value_of_css_property(name) == value.

Source code in selenium_expect/assertions/element.py
def to_have_css_property(
    self,
    name: str,
    value: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert element.value_of_css_property(name) == value."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        actual = el.value_of_css_property(name)
        return (actual == value, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have CSS {name!r}={value!r}",
        expected=value,
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_css_property_contains

to_have_css_property_contains(name: str, value: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert value in element.value_of_css_property(name).

Source code in selenium_expect/assertions/element.py
def to_have_css_property_contains(
    self,
    name: str,
    value: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert value in element.value_of_css_property(name)."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        actual = el.value_of_css_property(name)
        return (value in (actual or ""), actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have CSS {name!r} containing {value!r}",
        expected=value,
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_css_property_matches

to_have_css_property_matches(name: str, pattern: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert re.search(pattern, element.value_of_css_property(name)).

Source code in selenium_expect/assertions/element.py
def to_have_css_property_matches(
    self,
    name: str,
    pattern: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert re.search(pattern, element.value_of_css_property(name))."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        actual = el.value_of_css_property(name)
        return (re.search(pattern, actual or "") is not None, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have CSS {name!r} matching {pattern!r}",
        expected=pattern,
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_dom_attribute

to_have_dom_attribute(name: str, value: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert element.get_dom_attribute(name) == value.

Source code in selenium_expect/assertions/element.py
def to_have_dom_attribute(
    self,
    name: str,
    value: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert element.get_dom_attribute(name) == value."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        actual = el.get_dom_attribute(name)
        return (actual == value, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have DOM attribute {name!r}={value!r}",
        expected=value,
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_dom_attribute_contains

to_have_dom_attribute_contains(name: str, value: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert value in element.get_dom_attribute(name).

Source code in selenium_expect/assertions/element.py
def to_have_dom_attribute_contains(
    self,
    name: str,
    value: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert value in element.get_dom_attribute(name)."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        actual = el.get_dom_attribute(name)
        return (value in (actual or ""), actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have DOM attribute {name!r} containing {value!r}",
        expected=value,
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_id

to_have_id(id: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert element.get_attribute('id') == id.

Source code in selenium_expect/assertions/element.py
def to_have_id(
    self,
    id: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert element.get_attribute('id') == id."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        actual = el.get_attribute("id")
        return (actual == id, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have id {id!r}",
        expected=id,
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_js_property

to_have_js_property(name: str, value: Any, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert element JS property == value via execute_script.

Source code in selenium_expect/assertions/element.py
def to_have_js_property(
    self,
    name: str,
    value: Any,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert element JS property == value via execute_script."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        driver = getattr(el, "parent", None)
        if driver is None:
            return (False, "no driver")
        actual = driver.execute_script("return arguments[0][arguments[1]];", el, name)
        return (actual == value, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have JS property {name!r}={value!r}",
        expected=value,
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_location

to_have_location(x: int, y: int, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert element.location == {'x': x, 'y': y}.

Source code in selenium_expect/assertions/element.py
def to_have_location(
    self,
    x: int,
    y: int,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert element.location == {'x': x, 'y': y}."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        loc = el.location
        actual = {"x": loc["x"], "y": loc["y"]}
        return (actual == {"x": x, "y": y}, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have location ({x}, {y})",
        expected={"x": x, "y": y},
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_location_greater_than

to_have_location_greater_than(x: int | None = None, y: int | None = None, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert element.location x and/or y are greater than given values.

Source code in selenium_expect/assertions/element.py
def to_have_location_greater_than(
    self,
    x: int | None = None,
    y: int | None = None,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert element.location x and/or y are greater than given values."""
    if x is None and y is None:
        raise ValueError("At least one of x or y must be provided")
    el = self._target

    def condition() -> tuple[bool, Any]:
        loc = el.location
        actual = {"x": loc["x"], "y": loc["y"]}
        checks = []
        if x is not None:
            checks.append(loc["x"] > x)
        if y is not None:
            checks.append(loc["y"] > y)
        return (all(checks), actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have location > ({x}, {y})",
        expected=f"x>{x}, y>{y}",
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_location_less_than

to_have_location_less_than(x: int | None = None, y: int | None = None, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert element.location x and/or y are less than given values.

Source code in selenium_expect/assertions/element.py
def to_have_location_less_than(
    self,
    x: int | None = None,
    y: int | None = None,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert element.location x and/or y are less than given values."""
    if x is None and y is None:
        raise ValueError("At least one of x or y must be provided")
    el = self._target

    def condition() -> tuple[bool, Any]:
        loc = el.location
        actual = {"x": loc["x"], "y": loc["y"]}
        checks = []
        if x is not None:
            checks.append(loc["x"] < x)
        if y is not None:
            checks.append(loc["y"] < y)
        return (all(checks), actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have location < ({x}, {y})",
        expected=f"x<{x}, y<{y}",
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_location_once_scrolled_into_view

to_have_location_once_scrolled_into_view(x: int, y: int, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert element.location_once_scrolled_into_view == {'x': x, 'y': y}.

Source code in selenium_expect/assertions/element.py
def to_have_location_once_scrolled_into_view(
    self,
    x: int,
    y: int,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert element.location_once_scrolled_into_view == {'x': x, 'y': y}."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        loc = el.location_once_scrolled_into_view
        actual = {"x": loc["x"], "y": loc["y"]}
        return (actual == {"x": x, "y": y}, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have location once scrolled into view ({x}, {y})",
        expected={"x": x, "y": y},
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_location_x

to_have_location_x(x: int, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert element.location['x'] == x.

Source code in selenium_expect/assertions/element.py
def to_have_location_x(
    self,
    x: int,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert element.location['x'] == x."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        actual = el.location["x"]
        return (actual == x, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have location x={x}",
        expected=x,
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_location_y

to_have_location_y(y: int, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert element.location['y'] == y.

Source code in selenium_expect/assertions/element.py
def to_have_location_y(
    self,
    y: int,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert element.location['y'] == y."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        actual = el.location["y"]
        return (actual == y, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have location y={y}",
        expected=y,
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_property

to_have_property(name: str, value: Any, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert element.get_property(name) == value.

Source code in selenium_expect/assertions/element.py
def to_have_property(
    self,
    name: str,
    value: Any,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert element.get_property(name) == value."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        actual = el.get_property(name)
        return (actual == value, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have property {name!r}={value!r}",
        expected=value,
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_property_contains

to_have_property_contains(name: str, value: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert value in str(element.get_property(name)).

Source code in selenium_expect/assertions/element.py
def to_have_property_contains(
    self,
    name: str,
    value: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert value in str(element.get_property(name))."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        actual = el.get_property(name)
        if actual is None:
            return (False, actual)
        return (value in str(actual), actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have property {name!r} containing {value!r}",
        expected=value,
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_rect

to_have_rect(x: int, y: int, width: int, height: int, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert element.rect matches all four values.

Source code in selenium_expect/assertions/element.py
def to_have_rect(
    self,
    x: int,
    y: int,
    width: int,
    height: int,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert element.rect matches all four values."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        rect = el.rect
        actual = {
            "x": rect["x"],
            "y": rect["y"],
            "width": rect["width"],
            "height": rect["height"],
        }
        expected = {"x": x, "y": y, "width": width, "height": height}
        return (actual == expected, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have rect ({x}, {y}, {width}x{height})",
        expected={"x": x, "y": y, "width": width, "height": height},
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_shadow_root

to_have_shadow_root(*, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert element.shadow_root is not None.

Source code in selenium_expect/assertions/element.py
def to_have_shadow_root(
    self,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert element.shadow_root is not None."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        actual = el.shadow_root
        return (actual is not None, actual)

    self._run_assertion(
        condition=condition,
        condition_name="to have shadow root",
        expected="not None",
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_shadow_root_absent

to_have_shadow_root_absent(*, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert element.shadow_root is None.

Source code in selenium_expect/assertions/element.py
def to_have_shadow_root_absent(
    self,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert element.shadow_root is None."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        actual = el.shadow_root
        return (actual is None, actual)

    self._run_assertion(
        condition=condition,
        condition_name="to have shadow root absent",
        expected="None",
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_size

to_have_size(width: int, height: int, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert element.size == {'width': width, 'height': height}.

Source code in selenium_expect/assertions/element.py
def to_have_size(
    self,
    width: int,
    height: int,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert element.size == {'width': width, 'height': height}."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        sz = el.size
        actual = {"width": sz["width"], "height": sz["height"]}
        return (actual == {"width": width, "height": height}, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have size ({width}x{height})",
        expected={"width": width, "height": height},
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_size_greater_than

to_have_size_greater_than(width: int | None = None, height: int | None = None, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert element.size width and/or height are greater than given values.

Source code in selenium_expect/assertions/element.py
def to_have_size_greater_than(
    self,
    width: int | None = None,
    height: int | None = None,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert element.size width and/or height are greater than given values."""
    if width is None and height is None:
        raise ValueError("At least one of width or height must be provided")
    el = self._target

    def condition() -> tuple[bool, Any]:
        sz = el.size
        actual = {"width": sz["width"], "height": sz["height"]}
        checks = []
        if width is not None:
            checks.append(sz["width"] > width)
        if height is not None:
            checks.append(sz["height"] > height)
        return (all(checks), actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have size > ({width}, {height})",
        expected=f"w>{width}, h>{height}",
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_size_height

to_have_size_height(height: int, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert element.size['height'] == height.

Source code in selenium_expect/assertions/element.py
def to_have_size_height(
    self,
    height: int,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert element.size['height'] == height."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        actual = el.size["height"]
        return (actual == height, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have size height={height}",
        expected=height,
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_size_less_than

to_have_size_less_than(width: int | None = None, height: int | None = None, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert element.size width and/or height are less than given values.

Source code in selenium_expect/assertions/element.py
def to_have_size_less_than(
    self,
    width: int | None = None,
    height: int | None = None,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert element.size width and/or height are less than given values."""
    if width is None and height is None:
        raise ValueError("At least one of width or height must be provided")
    el = self._target

    def condition() -> tuple[bool, Any]:
        sz = el.size
        actual = {"width": sz["width"], "height": sz["height"]}
        checks = []
        if width is not None:
            checks.append(sz["width"] < width)
        if height is not None:
            checks.append(sz["height"] < height)
        return (all(checks), actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have size < ({width}, {height})",
        expected=f"w<{width}, h<{height}",
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_size_width

to_have_size_width(width: int, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert element.size['width'] == width.

Source code in selenium_expect/assertions/element.py
def to_have_size_width(
    self,
    width: int,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert element.size['width'] == width."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        actual = el.size["width"]
        return (actual == width, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have size width={width}",
        expected=width,
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_tag

to_have_tag(tag: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert element.tag_name == tag.

Source code in selenium_expect/assertions/element.py
def to_have_tag(
    self,
    tag: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert element.tag_name == tag."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        actual = el.tag_name
        return (actual == tag, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have tag {tag!r}",
        expected=tag,
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_text

to_have_text(text: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert element.text == text.

Source code in selenium_expect/assertions/element.py
def to_have_text(
    self,
    text: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert element.text == text."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        actual = el.text
        return (actual == text, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have text {text!r}",
        expected=text,
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_text_contains

to_have_text_contains(text: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert text in element.text.

Source code in selenium_expect/assertions/element.py
def to_have_text_contains(
    self,
    text: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert text in element.text."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        actual = el.text
        return (text in (actual or ""), actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have text containing {text!r}",
        expected=text,
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_text_empty

to_have_text_empty(*, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert element.text == ''.

Source code in selenium_expect/assertions/element.py
def to_have_text_empty(
    self,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert element.text == ''."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        actual = el.text
        return (actual == "", actual)

    self._run_assertion(
        condition=condition,
        condition_name="to have text empty",
        expected="",
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_text_ending_with

to_have_text_ending_with(suffix: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert element.text.endswith(suffix).

Source code in selenium_expect/assertions/element.py
def to_have_text_ending_with(
    self,
    suffix: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert element.text.endswith(suffix)."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        actual = el.text
        return ((actual or "").endswith(suffix), actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have text ending with {suffix!r}",
        expected=suffix,
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_text_in_list

to_have_text_in_list(*texts: str, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert element.text is one of *texts.

Source code in selenium_expect/assertions/element.py
def to_have_text_in_list(
    self,
    *texts: str,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert element.text is one of *texts."""
    if not texts:
        raise ValueError("At least one text must be provided")
    el = self._target

    def condition() -> tuple[bool, Any]:
        actual = el.text
        return (actual in texts, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have text in {list(texts)!r}",
        expected=list(texts),
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_text_matches

to_have_text_matches(pattern: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert re.search(pattern, element.text).

Source code in selenium_expect/assertions/element.py
def to_have_text_matches(
    self,
    pattern: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert re.search(pattern, element.text)."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        actual = el.text
        return (re.search(pattern, actual or "") is not None, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have text matching {pattern!r}",
        expected=pattern,
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_text_not_empty

to_have_text_not_empty(*, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert element.text != ''.

Source code in selenium_expect/assertions/element.py
def to_have_text_not_empty(
    self,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert element.text != ''."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        actual = el.text
        return (bool(actual), actual)

    self._run_assertion(
        condition=condition,
        condition_name="to have text not empty",
        expected="non-empty",
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_text_starting_with

to_have_text_starting_with(prefix: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert element.text.startswith(prefix).

Source code in selenium_expect/assertions/element.py
def to_have_text_starting_with(
    self,
    prefix: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert element.text.startswith(prefix)."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        actual = el.text
        return ((actual or "").startswith(prefix), actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have text starting with {prefix!r}",
        expected=prefix,
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_value

to_have_value(value: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert element.get_attribute('value') == value.

Source code in selenium_expect/assertions/element.py
def to_have_value(
    self,
    value: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert element.get_attribute('value') == value."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        actual = el.get_attribute("value")
        return (actual == value, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have value {value!r}",
        expected=value,
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_value_contains

to_have_value_contains(value: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert value in element.get_attribute('value').

Source code in selenium_expect/assertions/element.py
def to_have_value_contains(
    self,
    value: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert value in element.get_attribute('value')."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        actual = el.get_attribute("value")
        return (value in (actual or ""), actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have value containing {value!r}",
        expected=value,
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_value_in_list

to_have_value_in_list(values: list[str], *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert element.get_attribute('value') in values.

Source code in selenium_expect/assertions/element.py
def to_have_value_in_list(
    self,
    values: list[str],
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert element.get_attribute('value') in values."""
    if not values:
        raise ValueError("values list must not be empty")
    el = self._target

    def condition() -> tuple[bool, Any]:
        actual = el.get_attribute("value")
        return (actual in values, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have value in {values!r}",
        expected=values,
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_value_matches

to_have_value_matches(pattern: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert re.search(pattern, element.get_attribute('value')).

Source code in selenium_expect/assertions/element.py
def to_have_value_matches(
    self,
    pattern: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert re.search(pattern, element.get_attribute('value'))."""
    el = self._target

    def condition() -> tuple[bool, Any]:
        actual = el.get_attribute("value")
        return (re.search(pattern, actual or "") is not None, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have value matching {pattern!r}",
        expected=pattern,
        entity=self._entity_description(),
        timeout=timeout,
        polling=polling,
    )

    return self

ExpectDriver

Assertions for WebDriver and page-level state.

Key method categories:

  • Title: to_have_title, to_have_title_contains, to_have_title_matches
  • URL: to_have_url, to_have_url_contains, to_have_url_matches
  • State: to_have_ready_state
  • Windows: to_have_window_count, to_have_window_count_greater_than, to_have_window_count_less_than, to_have_window_handle, to_have_new_window_opened
  • Browser: to_have_browser_name, to_have_capability, to_have_capability_contains, to_have_orientation
  • Page source: to_have_page_source_contains, to_have_page_source_matches, to_have_page_source_not_contains
  • Window geometry: to_have_window_position, to_have_window_size, to_have_window_rect, to_have_position, to_have_size, to_have_rect
  • Active element: to_have_active_element_tag, to_have_active_element_id, to_have_active_element_class

selenium_expect.assertions.driver.ExpectDriver

Bases: ExpectCookie, ExpectJS, ExpectIframe, ExpectWindow, AssertionMixin

Assertions for WebDriver / page-level state.

Inherits cookie, JS, iframe, and window assertions via multiple inheritance so all driver-level assertions are available via expect(driver).

Source code in selenium_expect/assertions/driver.py
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
class ExpectDriver(ExpectCookie, ExpectJS, ExpectIframe, ExpectWindow, AssertionMixin):
    """Assertions for WebDriver / page-level state.

    Inherits cookie, JS, iframe, and window assertions via multiple
    inheritance so all driver-level assertions are available via
    ``expect(driver)``.
    """

    def __init__(
        self,
        target: WebDriver,
        config: ExpectConfig | None = None,
        message: str | None = None,
        negate: bool = False,
    ) -> None:
        super().__init__(target=target, config=config, message=message, negate=negate)

    # --- Title ---

    def to_have_title(
        self,
        title: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert driver.title == title."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            actual = driver.title
            return (actual == title, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have title {title!r}",
            expected=title,
            entity="page",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_title_contains(
        self,
        title: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert title in driver.title."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            actual = driver.title
            return (title in (actual or ""), actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have title containing {title!r}",
            expected=title,
            entity="page",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_title_matches(
        self,
        pattern: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert re.search(pattern, driver.title)."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            actual = driver.title
            return (re.search(pattern, actual or "") is not None, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have title matching {pattern!r}",
            expected=pattern,
            entity="page",
            timeout=timeout,
            polling=polling,
        )

        return self

    # --- URL ---

    def to_have_url(
        self,
        url: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert driver.current_url == url."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            actual = driver.current_url
            return (actual == url, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have URL {url!r}",
            expected=url,
            entity="page",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_url_contains(
        self,
        url: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert url in driver.current_url."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            actual = driver.current_url
            return (url in (actual or ""), actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have URL containing {url!r}",
            expected=url,
            entity="page",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_url_matches(
        self,
        pattern: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert re.search(pattern, driver.current_url)."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            actual = driver.current_url
            return (re.search(pattern, actual or "") is not None, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have URL matching {pattern!r}",
            expected=pattern,
            entity="page",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_url_changes(
        self,
        url: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert driver.current_url != url (URL has changed from the given value)."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            actual = driver.current_url
            return (actual != url, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have URL changed from {url!r}",
            expected=f"!= {url!r}",
            entity="page",
            timeout=timeout,
            polling=polling,
        )

        return self

    # --- Ready state ---

    def to_have_ready_state(
        self,
        state: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert document.readyState == state (e.g. 'complete', 'interactive', 'loading')."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            actual = driver.execute_script("return document.readyState;")
            return (actual == state, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have ready state {state!r}",
            expected=state,
            entity="page",
            timeout=timeout,
            polling=polling,
        )

        return self

    # --- Windows / tabs ---

    def to_have_window_count(
        self,
        count: int,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert len(driver.window_handles) == count."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            actual = len(driver.window_handles)
            return (actual == count, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have window count {count}",
            expected=count,
            entity="browser",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_window_count_greater_than(
        self,
        n: int,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert len(driver.window_handles) > n."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            actual = len(driver.window_handles)
            return (actual > n, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have window count > {n}",
            expected=f">{n}",
            entity="browser",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_window_count_less_than(
        self,
        n: int,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert len(driver.window_handles) < n."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            actual = len(driver.window_handles)
            return (actual < n, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have window count < {n}",
            expected=f"<{n}",
            entity="browser",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_window_handle(
        self,
        handle: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert driver.current_window_handle == handle."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            actual = driver.current_window_handle
            return (actual == handle, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have window handle {handle!r}",
            expected=handle,
            entity="browser",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_new_window_opened(
        self,
        previous_handles: list[str],
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert that a new window has opened (current handles > previous handles)."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            current = driver.window_handles
            new_handles = [h for h in current if h not in previous_handles]
            return (len(new_handles) > 0, new_handles)

        self._run_assertion(
            condition=condition,
            condition_name="to have new window opened",
            expected="new handle",
            entity="browser",
            timeout=timeout,
            polling=polling,
        )

        return self

    # --- Browser / capabilities ---

    def to_have_browser_name(
        self,
        name: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert driver.name == name."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            actual = driver.name
            return (actual == name, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have browser name {name!r}",
            expected=name,
            entity="browser",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_orientation(
        self,
        orientation: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert driver.orientation == orientation."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            actual = driver.orientation
            return (actual == orientation, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have orientation {orientation!r}",
            expected=orientation,
            entity="browser",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_capability(
        self,
        key: str,
        value: Any,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert driver.capabilities[key] == value."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            caps = driver.capabilities
            actual = caps.get(key) if caps else None
            return (actual == value, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have capability {key!r}={value!r}",
            expected=value,
            entity="browser",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_capability_contains(
        self,
        key: str,
        value: Any,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert value in driver.capabilities[key]."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            caps = driver.capabilities
            actual = caps.get(key) if caps else None
            if actual is None:
                return (False, actual)
            return (value in str(actual), actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have capability {key!r} containing {value!r}",
            expected=value,
            entity="browser",
            timeout=timeout,
            polling=polling,
        )

        return self

    # --- Page source ---

    def to_have_page_source_contains(
        self,
        text: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert text in driver.page_source."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            actual = driver.page_source
            return (text in (actual or ""), len(actual) if actual else 0)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have page source containing {text!r}",
            expected=text,
            entity="page",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_page_source_matches(
        self,
        pattern: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert re.search(pattern, driver.page_source)."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            actual = driver.page_source
            return (re.search(pattern, actual or "") is not None, len(actual) if actual else 0)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have page source matching {pattern!r}",
            expected=pattern,
            entity="page",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_page_source_not_contains(
        self,
        text: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert text not in driver.page_source."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            actual = driver.page_source
            return (text not in (actual or ""), len(actual) if actual else 0)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have page source not containing {text!r}",
            expected=f"not {text!r}",
            entity="page",
            timeout=timeout,
            polling=polling,
        )

        return self

    # --- Window position / size / rect ---

    def to_have_window_position(
        self,
        x: int,
        y: int,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert driver.get_window_position() == {'x': x, 'y': y}."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            pos = driver.get_window_position()
            actual = {"x": pos["x"], "y": pos["y"]}
            return (actual == {"x": x, "y": y}, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have window position ({x}, {y})",
            expected={"x": x, "y": y},
            entity="browser",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_window_size(
        self,
        width: int,
        height: int,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert driver.get_window_size() == {'width': width, 'height': height}."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            sz = driver.get_window_size()
            actual = {"width": sz["width"], "height": sz["height"]}
            return (actual == {"width": width, "height": height}, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have window size ({width}x{height})",
            expected={"width": width, "height": height},
            entity="browser",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_window_rect(
        self,
        x: int,
        y: int,
        width: int,
        height: int,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert driver.get_window_rect() matches all four values."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            rect = driver.get_window_rect()
            actual = {
                "x": rect["x"],
                "y": rect["y"],
                "width": rect["width"],
                "height": rect["height"],
            }
            expected = {"x": x, "y": y, "width": width, "height": height}
            return (actual == expected, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have window rect ({x}, {y}, {width}x{height})",
            expected={"x": x, "y": y, "width": width, "height": height},
            entity="browser",
            timeout=timeout,
            polling=polling,
        )

        return self

    # --- Active element ---

    def to_have_active_element_tag(
        self,
        tag: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert driver.switch_to.active_element.tag_name == tag."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            actual = driver.switch_to.active_element.tag_name
            return (actual == tag, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have active element tag {tag!r}",
            expected=tag,
            entity="page",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_active_element_id(
        self,
        id: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert driver.switch_to.active_element.get_attribute('id') == id."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            actual = driver.switch_to.active_element.get_attribute("id")
            return (actual == id, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have active element id {id!r}",
            expected=id,
            entity="page",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_active_element_class(
        self,
        class_name: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert class_name in active_element.get_attribute('class')."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            actual = driver.switch_to.active_element.get_attribute("class")
            classes = (actual or "").split()
            return (class_name in classes, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have active element class {class_name!r}",
            expected=class_name,
            entity="page",
            timeout=timeout,
            polling=polling,
        )

        return self

    # --- Overrides ---

    def _entity_description(self) -> str:
        return "WebDriver"

    def _get_element_html(self) -> str | None:
        return None

to_have_active_element_class

to_have_active_element_class(class_name: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert class_name in active_element.get_attribute('class').

Source code in selenium_expect/assertions/driver.py
def to_have_active_element_class(
    self,
    class_name: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert class_name in active_element.get_attribute('class')."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        actual = driver.switch_to.active_element.get_attribute("class")
        classes = (actual or "").split()
        return (class_name in classes, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have active element class {class_name!r}",
        expected=class_name,
        entity="page",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_active_element_id

to_have_active_element_id(id: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert driver.switch_to.active_element.get_attribute('id') == id.

Source code in selenium_expect/assertions/driver.py
def to_have_active_element_id(
    self,
    id: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert driver.switch_to.active_element.get_attribute('id') == id."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        actual = driver.switch_to.active_element.get_attribute("id")
        return (actual == id, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have active element id {id!r}",
        expected=id,
        entity="page",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_active_element_tag

to_have_active_element_tag(tag: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert driver.switch_to.active_element.tag_name == tag.

Source code in selenium_expect/assertions/driver.py
def to_have_active_element_tag(
    self,
    tag: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert driver.switch_to.active_element.tag_name == tag."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        actual = driver.switch_to.active_element.tag_name
        return (actual == tag, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have active element tag {tag!r}",
        expected=tag,
        entity="page",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_browser_name

to_have_browser_name(name: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert driver.name == name.

Source code in selenium_expect/assertions/driver.py
def to_have_browser_name(
    self,
    name: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert driver.name == name."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        actual = driver.name
        return (actual == name, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have browser name {name!r}",
        expected=name,
        entity="browser",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_capability

to_have_capability(key: str, value: Any, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert driver.capabilities[key] == value.

Source code in selenium_expect/assertions/driver.py
def to_have_capability(
    self,
    key: str,
    value: Any,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert driver.capabilities[key] == value."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        caps = driver.capabilities
        actual = caps.get(key) if caps else None
        return (actual == value, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have capability {key!r}={value!r}",
        expected=value,
        entity="browser",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_capability_contains

to_have_capability_contains(key: str, value: Any, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert value in driver.capabilities[key].

Source code in selenium_expect/assertions/driver.py
def to_have_capability_contains(
    self,
    key: str,
    value: Any,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert value in driver.capabilities[key]."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        caps = driver.capabilities
        actual = caps.get(key) if caps else None
        if actual is None:
            return (False, actual)
        return (value in str(actual), actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have capability {key!r} containing {value!r}",
        expected=value,
        entity="browser",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_new_window_opened

to_have_new_window_opened(previous_handles: list[str], *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert that a new window has opened (current handles > previous handles).

Source code in selenium_expect/assertions/driver.py
def to_have_new_window_opened(
    self,
    previous_handles: list[str],
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert that a new window has opened (current handles > previous handles)."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        current = driver.window_handles
        new_handles = [h for h in current if h not in previous_handles]
        return (len(new_handles) > 0, new_handles)

    self._run_assertion(
        condition=condition,
        condition_name="to have new window opened",
        expected="new handle",
        entity="browser",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_orientation

to_have_orientation(orientation: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert driver.orientation == orientation.

Source code in selenium_expect/assertions/driver.py
def to_have_orientation(
    self,
    orientation: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert driver.orientation == orientation."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        actual = driver.orientation
        return (actual == orientation, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have orientation {orientation!r}",
        expected=orientation,
        entity="browser",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_page_source_contains

to_have_page_source_contains(text: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert text in driver.page_source.

Source code in selenium_expect/assertions/driver.py
def to_have_page_source_contains(
    self,
    text: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert text in driver.page_source."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        actual = driver.page_source
        return (text in (actual or ""), len(actual) if actual else 0)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have page source containing {text!r}",
        expected=text,
        entity="page",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_page_source_matches

to_have_page_source_matches(pattern: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert re.search(pattern, driver.page_source).

Source code in selenium_expect/assertions/driver.py
def to_have_page_source_matches(
    self,
    pattern: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert re.search(pattern, driver.page_source)."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        actual = driver.page_source
        return (re.search(pattern, actual or "") is not None, len(actual) if actual else 0)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have page source matching {pattern!r}",
        expected=pattern,
        entity="page",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_page_source_not_contains

to_have_page_source_not_contains(text: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert text not in driver.page_source.

Source code in selenium_expect/assertions/driver.py
def to_have_page_source_not_contains(
    self,
    text: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert text not in driver.page_source."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        actual = driver.page_source
        return (text not in (actual or ""), len(actual) if actual else 0)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have page source not containing {text!r}",
        expected=f"not {text!r}",
        entity="page",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_ready_state

to_have_ready_state(state: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert document.readyState == state (e.g. 'complete', 'interactive', 'loading').

Source code in selenium_expect/assertions/driver.py
def to_have_ready_state(
    self,
    state: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert document.readyState == state (e.g. 'complete', 'interactive', 'loading')."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        actual = driver.execute_script("return document.readyState;")
        return (actual == state, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have ready state {state!r}",
        expected=state,
        entity="page",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_title

to_have_title(title: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert driver.title == title.

Source code in selenium_expect/assertions/driver.py
def to_have_title(
    self,
    title: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert driver.title == title."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        actual = driver.title
        return (actual == title, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have title {title!r}",
        expected=title,
        entity="page",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_title_contains

to_have_title_contains(title: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert title in driver.title.

Source code in selenium_expect/assertions/driver.py
def to_have_title_contains(
    self,
    title: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert title in driver.title."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        actual = driver.title
        return (title in (actual or ""), actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have title containing {title!r}",
        expected=title,
        entity="page",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_title_matches

to_have_title_matches(pattern: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert re.search(pattern, driver.title).

Source code in selenium_expect/assertions/driver.py
def to_have_title_matches(
    self,
    pattern: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert re.search(pattern, driver.title)."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        actual = driver.title
        return (re.search(pattern, actual or "") is not None, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have title matching {pattern!r}",
        expected=pattern,
        entity="page",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_url

to_have_url(url: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert driver.current_url == url.

Source code in selenium_expect/assertions/driver.py
def to_have_url(
    self,
    url: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert driver.current_url == url."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        actual = driver.current_url
        return (actual == url, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have URL {url!r}",
        expected=url,
        entity="page",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_url_changes

to_have_url_changes(url: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert driver.current_url != url (URL has changed from the given value).

Source code in selenium_expect/assertions/driver.py
def to_have_url_changes(
    self,
    url: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert driver.current_url != url (URL has changed from the given value)."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        actual = driver.current_url
        return (actual != url, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have URL changed from {url!r}",
        expected=f"!= {url!r}",
        entity="page",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_url_contains

to_have_url_contains(url: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert url in driver.current_url.

Source code in selenium_expect/assertions/driver.py
def to_have_url_contains(
    self,
    url: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert url in driver.current_url."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        actual = driver.current_url
        return (url in (actual or ""), actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have URL containing {url!r}",
        expected=url,
        entity="page",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_url_matches

to_have_url_matches(pattern: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert re.search(pattern, driver.current_url).

Source code in selenium_expect/assertions/driver.py
def to_have_url_matches(
    self,
    pattern: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert re.search(pattern, driver.current_url)."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        actual = driver.current_url
        return (re.search(pattern, actual or "") is not None, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have URL matching {pattern!r}",
        expected=pattern,
        entity="page",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_window_count

to_have_window_count(count: int, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert len(driver.window_handles) == count.

Source code in selenium_expect/assertions/driver.py
def to_have_window_count(
    self,
    count: int,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert len(driver.window_handles) == count."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        actual = len(driver.window_handles)
        return (actual == count, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have window count {count}",
        expected=count,
        entity="browser",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_window_count_greater_than

to_have_window_count_greater_than(n: int, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert len(driver.window_handles) > n.

Source code in selenium_expect/assertions/driver.py
def to_have_window_count_greater_than(
    self,
    n: int,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert len(driver.window_handles) > n."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        actual = len(driver.window_handles)
        return (actual > n, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have window count > {n}",
        expected=f">{n}",
        entity="browser",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_window_count_less_than

to_have_window_count_less_than(n: int, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert len(driver.window_handles) < n.

Source code in selenium_expect/assertions/driver.py
def to_have_window_count_less_than(
    self,
    n: int,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert len(driver.window_handles) < n."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        actual = len(driver.window_handles)
        return (actual < n, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have window count < {n}",
        expected=f"<{n}",
        entity="browser",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_window_handle

to_have_window_handle(handle: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert driver.current_window_handle == handle.

Source code in selenium_expect/assertions/driver.py
def to_have_window_handle(
    self,
    handle: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert driver.current_window_handle == handle."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        actual = driver.current_window_handle
        return (actual == handle, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have window handle {handle!r}",
        expected=handle,
        entity="browser",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_window_position

to_have_window_position(x: int, y: int, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert driver.get_window_position() == {'x': x, 'y': y}.

Source code in selenium_expect/assertions/driver.py
def to_have_window_position(
    self,
    x: int,
    y: int,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert driver.get_window_position() == {'x': x, 'y': y}."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        pos = driver.get_window_position()
        actual = {"x": pos["x"], "y": pos["y"]}
        return (actual == {"x": x, "y": y}, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have window position ({x}, {y})",
        expected={"x": x, "y": y},
        entity="browser",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_window_rect

to_have_window_rect(x: int, y: int, width: int, height: int, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert driver.get_window_rect() matches all four values.

Source code in selenium_expect/assertions/driver.py
def to_have_window_rect(
    self,
    x: int,
    y: int,
    width: int,
    height: int,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert driver.get_window_rect() matches all four values."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        rect = driver.get_window_rect()
        actual = {
            "x": rect["x"],
            "y": rect["y"],
            "width": rect["width"],
            "height": rect["height"],
        }
        expected = {"x": x, "y": y, "width": width, "height": height}
        return (actual == expected, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have window rect ({x}, {y}, {width}x{height})",
        expected={"x": x, "y": y, "width": width, "height": height},
        entity="browser",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_window_size

to_have_window_size(width: int, height: int, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert driver.get_window_size() == {'width': width, 'height': height}.

Source code in selenium_expect/assertions/driver.py
def to_have_window_size(
    self,
    width: int,
    height: int,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert driver.get_window_size() == {'width': width, 'height': height}."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        sz = driver.get_window_size()
        actual = {"width": sz["width"], "height": sz["height"]}
        return (actual == {"width": width, "height": height}, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have window size ({width}x{height})",
        expected={"width": width, "height": height},
        entity="browser",
        timeout=timeout,
        polling=polling,
    )

    return self

ExpectList

Assertions for lists of WebElement objects.

Key method categories:

  • Count: to_have_count, to_have_count_greater_than, to_have_count_less_than, to_have_count_greater_than_or_equal, to_have_count_less_than_or_equal, to_be_empty, to_be_not_empty
  • Text: to_have_texts, to_have_texts_contains, to_have_texts_match, to_have_text_at, to_have_any_text, to_have_all_texts_contain, to_have_any_text_contain, to_have_none_text_contain, to_have_exact_texts, to_have_texts_containing, to_have_texts_in_any_order, to_have_first_text, to_have_last_text, to_have_nth_text_contains
  • Values: to_have_values, to_have_value_at, to_have_values_contains
  • State: to_have_all_visible, to_have_any_visible, to_have_none_visible, to_have_all_enabled, to_have_all_selected
  • Attributes: to_have_attribute_at, to_have_all_attribute, to_have_any_attribute

selenium_expect.assertions.list.ExpectList

Bases: AssertionMixin

Assertions for lists of WebElements.

Source code in selenium_expect/assertions/list.py
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
class ExpectList(AssertionMixin):
    """Assertions for lists of WebElements."""

    def __init__(
        self,
        target: list[WebElement],
        config: ExpectConfig | None = None,
        message: str | None = None,
        negate: bool = False,
    ) -> None:
        super().__init__(target=target, config=config, message=message, negate=negate)

    # --- Count ---

    def to_have_count(
        self,
        count: int,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert len(elements) == count."""
        elements = self._target

        def condition() -> tuple[bool, Any]:
            actual = len(elements)
            return (actual == count, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have count {count}",
            expected=count,
            entity="list",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_count_greater_than(
        self,
        n: int,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert len(elements) > n."""
        elements = self._target

        def condition() -> tuple[bool, Any]:
            actual = len(elements)
            return (actual > n, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have count > {n}",
            expected=f">{n}",
            entity="list",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_count_less_than(
        self,
        n: int,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert len(elements) < n."""
        elements = self._target

        def condition() -> tuple[bool, Any]:
            actual = len(elements)
            return (actual < n, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have count < {n}",
            expected=f"<{n}",
            entity="list",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_count_greater_than_or_equal(
        self,
        n: int,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert len(elements) >= n."""
        elements = self._target

        def condition() -> tuple[bool, Any]:
            actual = len(elements)
            return (actual >= n, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have count >= {n}",
            expected=f">={n}",
            entity="list",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_count_less_than_or_equal(
        self,
        n: int,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert len(elements) <= n."""
        elements = self._target

        def condition() -> tuple[bool, Any]:
            actual = len(elements)
            return (actual <= n, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have count <= {n}",
            expected=f"<={n}",
            entity="list",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_be_empty(
        self,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert len(elements) == 0."""
        elements = self._target

        def condition() -> tuple[bool, Any]:
            actual = len(elements)
            return (actual == 0, actual)

        self._run_assertion(
            condition=condition,
            condition_name="to be empty",
            expected=0,
            entity="list",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_be_not_empty(
        self,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert len(elements) > 0."""
        elements = self._target

        def condition() -> tuple[bool, Any]:
            actual = len(elements)
            return (actual > 0, actual)

        self._run_assertion(
            condition=condition,
            condition_name="to be not empty",
            expected=">0",
            entity="list",
            timeout=timeout,
            polling=polling,
        )

        return self

    # --- Text ---

    def to_have_texts(
        self,
        texts: list[str],
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert [el.text for el in elements] == texts (exact, ordered)."""
        if not texts:
            raise ValueError("texts list must not be empty")
        elements = self._target

        def condition() -> tuple[bool, Any]:
            actual = [el.text for el in elements]
            return (actual == texts, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have texts {texts!r}",
            expected=texts,
            entity="list",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_texts_contains(
        self,
        texts: list[str],
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert each text in texts is in corresponding element.text."""
        if not texts:
            raise ValueError("texts list must not be empty")
        elements = self._target

        def condition() -> tuple[bool, Any]:
            actual = [el.text for el in elements]
            if len(actual) != len(texts):
                return (False, actual)
            return (all(t in (a or "") for a, t in zip(actual, texts, strict=False)), actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have texts containing {texts!r}",
            expected=texts,
            entity="list",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_texts_match(
        self,
        patterns: list[str],
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert each element's text matches the corresponding regex pattern."""
        if not patterns:
            raise ValueError("patterns list must not be empty")
        elements = self._target

        def condition() -> tuple[bool, Any]:
            actual = [el.text for el in elements]
            if len(actual) != len(patterns):
                return (False, actual)
            return (
                all(
                    re.search(p, a or "") is not None
                    for a, p in zip(actual, patterns, strict=False)
                ),
                actual,
            )

        self._run_assertion(
            condition=condition,
            condition_name=f"to have texts matching {patterns!r}",
            expected=patterns,
            entity="list",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_text_at(
        self,
        index: int,
        text: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert elements[index].text == text."""
        elements = self._target

        def condition() -> tuple[bool, Any]:
            if index >= len(elements) or index < -len(elements):
                return (False, f"index {index} out of range")
            actual = elements[index].text
            return (actual == text, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have text at [{index}]={text!r}",
            expected=text,
            entity="list",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_any_text(
        self,
        text: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert any element has text == text."""
        elements = self._target

        def condition() -> tuple[bool, Any]:
            actual = [el.text for el in elements]
            return (text in actual, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have any text {text!r}",
            expected=text,
            entity="list",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_all_texts_contain(
        self,
        text: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert all elements contain text."""
        elements = self._target

        def condition() -> tuple[bool, Any]:
            actual = [el.text for el in elements]
            return (all(text in (t or "") for t in actual) and len(actual) > 0, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have all texts containing {text!r}",
            expected=text,
            entity="list",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_any_text_contain(
        self,
        text: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert any element contains text."""
        elements = self._target

        def condition() -> tuple[bool, Any]:
            actual = [el.text for el in elements]
            return (any(text in (t or "") for t in actual), actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have any text containing {text!r}",
            expected=text,
            entity="list",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_none_text_contain(
        self,
        text: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert no element contains text."""
        elements = self._target

        def condition() -> tuple[bool, Any]:
            actual = [el.text for el in elements]
            return (not any(text in (t or "") for t in actual) and len(actual) > 0, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have no text containing {text!r}",
            expected=f"none containing {text!r}",
            entity="list",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_exact_texts(
        self,
        *texts: str,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert [el.text for el in elements] == list(texts) (exact, ordered, varargs)."""
        if not texts:
            raise ValueError("At least one text must be provided")
        elements = self._target
        expected = list(texts)

        def condition() -> tuple[bool, Any]:
            actual = [el.text for el in elements]
            return (actual == expected, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have exact texts {expected!r}",
            expected=expected,
            entity="list",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_texts_containing(
        self,
        *texts: str,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert each element.text contains the corresponding text (varargs)."""
        if not texts:
            raise ValueError("At least one text must be provided")
        elements = self._target
        expected = list(texts)

        def condition() -> tuple[bool, Any]:
            actual = [el.text for el in elements]
            if len(actual) != len(expected):
                return (False, actual)
            return (all(t in (a or "") for a, t in zip(actual, expected, strict=False)), actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have texts containing {expected!r}",
            expected=expected,
            entity="list",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_texts_in_any_order(
        self,
        *texts: str,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert element texts match texts in any order (varargs)."""
        if not texts:
            raise ValueError("At least one text must be provided")
        elements = self._target
        expected = sorted(texts)

        def condition() -> tuple[bool, Any]:
            actual = sorted(el.text for el in elements)
            return (actual == expected, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have texts in any order {list(texts)!r}",
            expected=list(texts),
            entity="list",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_first_text(
        self,
        text: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert elements[0].text == text."""
        elements = self._target

        def condition() -> tuple[bool, Any]:
            if not elements:
                return (False, "empty list")
            actual = elements[0].text
            return (actual == text, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have first text {text!r}",
            expected=text,
            entity="list",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_last_text(
        self,
        text: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert elements[-1].text == text."""
        elements = self._target

        def condition() -> tuple[bool, Any]:
            if not elements:
                return (False, "empty list")
            actual = elements[-1].text
            return (actual == text, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have last text {text!r}",
            expected=text,
            entity="list",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_nth_text_contains(
        self,
        index: int,
        text: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert text in elements[index].text."""
        elements = self._target

        def condition() -> tuple[bool, Any]:
            if index >= len(elements) or index < -len(elements):
                return (False, f"index {index} out of range")
            actual = elements[index].text
            return (text in (actual or ""), actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have text at [{index}] containing {text!r}",
            expected=text,
            entity="list",
            timeout=timeout,
            polling=polling,
        )

        return self

    # --- Values ---

    def to_have_values(
        self,
        values: list[str],
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert [el.get_attribute('value') for el in elements] == values."""
        if not values:
            raise ValueError("values list must not be empty")
        elements = self._target

        def condition() -> tuple[bool, Any]:
            actual = [el.get_attribute("value") for el in elements]
            return (actual == values, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have values {values!r}",
            expected=values,
            entity="list",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_values_contains(
        self,
        values: list[str],
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert each value is a substring of the corresponding element's value."""
        if not values:
            raise ValueError("values list must not be empty")
        elements = self._target

        def condition() -> tuple[bool, Any]:
            actual = [el.get_attribute("value") for el in elements]
            if len(actual) != len(values):
                return (False, actual)
            return (all(v in (a or "") for a, v in zip(actual, values, strict=False)), actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have values containing {values!r}",
            expected=values,
            entity="list",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_value_at(
        self,
        index: int,
        value: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert elements[index].get_attribute('value') == value."""
        elements = self._target

        def condition() -> tuple[bool, Any]:
            if index >= len(elements) or index < -len(elements):
                return (False, f"index {index} out of range")
            actual = elements[index].get_attribute("value")
            return (actual == value, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have value at [{index}]={value!r}",
            expected=value,
            entity="list",
            timeout=timeout,
            polling=polling,
        )

        return self

    # --- State (aggregate) ---

    def to_have_all_visible(
        self,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert all elements are visible."""
        elements = self._target

        def condition() -> tuple[bool, Any]:
            actual = [el.is_displayed() for el in elements]
            return (all(actual) and len(actual) > 0, actual)

        self._run_assertion(
            condition=condition,
            condition_name="to have all visible",
            expected="all visible",
            entity="list",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_any_visible(
        self,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert at least one element is visible."""
        elements = self._target

        def condition() -> tuple[bool, Any]:
            actual = [el.is_displayed() for el in elements]
            return (any(actual), actual)

        self._run_assertion(
            condition=condition,
            condition_name="to have any visible",
            expected="any visible",
            entity="list",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_none_visible(
        self,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert no element is visible."""
        elements = self._target

        def condition() -> tuple[bool, Any]:
            actual = [el.is_displayed() for el in elements]
            return (not any(actual) and len(actual) > 0, actual)

        self._run_assertion(
            condition=condition,
            condition_name="to have none visible",
            expected="none visible",
            entity="list",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_all_enabled(
        self,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert all elements are enabled."""
        elements = self._target

        def condition() -> tuple[bool, Any]:
            actual = [el.is_enabled() for el in elements]
            return (all(actual) and len(actual) > 0, actual)

        self._run_assertion(
            condition=condition,
            condition_name="to have all enabled",
            expected="all enabled",
            entity="list",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_all_selected(
        self,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert all elements are selected."""
        elements = self._target

        def condition() -> tuple[bool, Any]:
            actual = [el.is_selected() for el in elements]
            return (all(actual) and len(actual) > 0, actual)

        self._run_assertion(
            condition=condition,
            condition_name="to have all selected",
            expected="all selected",
            entity="list",
            timeout=timeout,
            polling=polling,
        )

        return self

    # --- Attributes ---

    def to_have_attribute_at(
        self,
        index: int,
        name: str,
        value: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert elements[index].get_attribute(name) == value."""
        elements = self._target

        def condition() -> tuple[bool, Any]:
            if index >= len(elements) or index < -len(elements):
                return (False, f"index {index} out of range")
            actual = elements[index].get_attribute(name)
            return (actual == value, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have attribute {name!r}={value!r} at [{index}]",
            expected=value,
            entity="list",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_all_attribute(
        self,
        name: str,
        value: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert all elements have attribute == value."""
        elements = self._target

        def condition() -> tuple[bool, Any]:
            actual = [el.get_attribute(name) for el in elements]
            return (all(a == value for a in actual) and len(actual) > 0, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have all attribute {name!r}={value!r}",
            expected=value,
            entity="list",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_any_attribute(
        self,
        name: str,
        value: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert any element has attribute == value."""
        elements = self._target

        def condition() -> tuple[bool, Any]:
            actual = [el.get_attribute(name) for el in elements]
            return (any(a == value for a in actual), actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have any attribute {name!r}={value!r}",
            expected=value,
            entity="list",
            timeout=timeout,
            polling=polling,
        )

        return self

    # --- Overrides ---

    def _entity_description(self) -> str:
        return f"list[{len(self._target)}]"

    def _get_element_html(self) -> str | None:
        return None

to_be_empty

to_be_empty(*, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert len(elements) == 0.

Source code in selenium_expect/assertions/list.py
def to_be_empty(
    self,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert len(elements) == 0."""
    elements = self._target

    def condition() -> tuple[bool, Any]:
        actual = len(elements)
        return (actual == 0, actual)

    self._run_assertion(
        condition=condition,
        condition_name="to be empty",
        expected=0,
        entity="list",
        timeout=timeout,
        polling=polling,
    )

    return self

to_be_not_empty

to_be_not_empty(*, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert len(elements) > 0.

Source code in selenium_expect/assertions/list.py
def to_be_not_empty(
    self,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert len(elements) > 0."""
    elements = self._target

    def condition() -> tuple[bool, Any]:
        actual = len(elements)
        return (actual > 0, actual)

    self._run_assertion(
        condition=condition,
        condition_name="to be not empty",
        expected=">0",
        entity="list",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_all_attribute

to_have_all_attribute(name: str, value: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert all elements have attribute == value.

Source code in selenium_expect/assertions/list.py
def to_have_all_attribute(
    self,
    name: str,
    value: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert all elements have attribute == value."""
    elements = self._target

    def condition() -> tuple[bool, Any]:
        actual = [el.get_attribute(name) for el in elements]
        return (all(a == value for a in actual) and len(actual) > 0, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have all attribute {name!r}={value!r}",
        expected=value,
        entity="list",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_all_enabled

to_have_all_enabled(*, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert all elements are enabled.

Source code in selenium_expect/assertions/list.py
def to_have_all_enabled(
    self,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert all elements are enabled."""
    elements = self._target

    def condition() -> tuple[bool, Any]:
        actual = [el.is_enabled() for el in elements]
        return (all(actual) and len(actual) > 0, actual)

    self._run_assertion(
        condition=condition,
        condition_name="to have all enabled",
        expected="all enabled",
        entity="list",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_all_selected

to_have_all_selected(*, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert all elements are selected.

Source code in selenium_expect/assertions/list.py
def to_have_all_selected(
    self,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert all elements are selected."""
    elements = self._target

    def condition() -> tuple[bool, Any]:
        actual = [el.is_selected() for el in elements]
        return (all(actual) and len(actual) > 0, actual)

    self._run_assertion(
        condition=condition,
        condition_name="to have all selected",
        expected="all selected",
        entity="list",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_all_texts_contain

to_have_all_texts_contain(text: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert all elements contain text.

Source code in selenium_expect/assertions/list.py
def to_have_all_texts_contain(
    self,
    text: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert all elements contain text."""
    elements = self._target

    def condition() -> tuple[bool, Any]:
        actual = [el.text for el in elements]
        return (all(text in (t or "") for t in actual) and len(actual) > 0, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have all texts containing {text!r}",
        expected=text,
        entity="list",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_all_visible

to_have_all_visible(*, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert all elements are visible.

Source code in selenium_expect/assertions/list.py
def to_have_all_visible(
    self,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert all elements are visible."""
    elements = self._target

    def condition() -> tuple[bool, Any]:
        actual = [el.is_displayed() for el in elements]
        return (all(actual) and len(actual) > 0, actual)

    self._run_assertion(
        condition=condition,
        condition_name="to have all visible",
        expected="all visible",
        entity="list",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_any_attribute

to_have_any_attribute(name: str, value: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert any element has attribute == value.

Source code in selenium_expect/assertions/list.py
def to_have_any_attribute(
    self,
    name: str,
    value: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert any element has attribute == value."""
    elements = self._target

    def condition() -> tuple[bool, Any]:
        actual = [el.get_attribute(name) for el in elements]
        return (any(a == value for a in actual), actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have any attribute {name!r}={value!r}",
        expected=value,
        entity="list",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_any_text

to_have_any_text(text: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert any element has text == text.

Source code in selenium_expect/assertions/list.py
def to_have_any_text(
    self,
    text: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert any element has text == text."""
    elements = self._target

    def condition() -> tuple[bool, Any]:
        actual = [el.text for el in elements]
        return (text in actual, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have any text {text!r}",
        expected=text,
        entity="list",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_any_text_contain

to_have_any_text_contain(text: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert any element contains text.

Source code in selenium_expect/assertions/list.py
def to_have_any_text_contain(
    self,
    text: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert any element contains text."""
    elements = self._target

    def condition() -> tuple[bool, Any]:
        actual = [el.text for el in elements]
        return (any(text in (t or "") for t in actual), actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have any text containing {text!r}",
        expected=text,
        entity="list",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_any_visible

to_have_any_visible(*, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert at least one element is visible.

Source code in selenium_expect/assertions/list.py
def to_have_any_visible(
    self,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert at least one element is visible."""
    elements = self._target

    def condition() -> tuple[bool, Any]:
        actual = [el.is_displayed() for el in elements]
        return (any(actual), actual)

    self._run_assertion(
        condition=condition,
        condition_name="to have any visible",
        expected="any visible",
        entity="list",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_attribute_at

to_have_attribute_at(index: int, name: str, value: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert elements[index].get_attribute(name) == value.

Source code in selenium_expect/assertions/list.py
def to_have_attribute_at(
    self,
    index: int,
    name: str,
    value: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert elements[index].get_attribute(name) == value."""
    elements = self._target

    def condition() -> tuple[bool, Any]:
        if index >= len(elements) or index < -len(elements):
            return (False, f"index {index} out of range")
        actual = elements[index].get_attribute(name)
        return (actual == value, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have attribute {name!r}={value!r} at [{index}]",
        expected=value,
        entity="list",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_count

to_have_count(count: int, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert len(elements) == count.

Source code in selenium_expect/assertions/list.py
def to_have_count(
    self,
    count: int,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert len(elements) == count."""
    elements = self._target

    def condition() -> tuple[bool, Any]:
        actual = len(elements)
        return (actual == count, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have count {count}",
        expected=count,
        entity="list",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_count_greater_than

to_have_count_greater_than(n: int, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert len(elements) > n.

Source code in selenium_expect/assertions/list.py
def to_have_count_greater_than(
    self,
    n: int,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert len(elements) > n."""
    elements = self._target

    def condition() -> tuple[bool, Any]:
        actual = len(elements)
        return (actual > n, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have count > {n}",
        expected=f">{n}",
        entity="list",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_count_greater_than_or_equal

to_have_count_greater_than_or_equal(n: int, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert len(elements) >= n.

Source code in selenium_expect/assertions/list.py
def to_have_count_greater_than_or_equal(
    self,
    n: int,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert len(elements) >= n."""
    elements = self._target

    def condition() -> tuple[bool, Any]:
        actual = len(elements)
        return (actual >= n, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have count >= {n}",
        expected=f">={n}",
        entity="list",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_count_less_than

to_have_count_less_than(n: int, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert len(elements) < n.

Source code in selenium_expect/assertions/list.py
def to_have_count_less_than(
    self,
    n: int,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert len(elements) < n."""
    elements = self._target

    def condition() -> tuple[bool, Any]:
        actual = len(elements)
        return (actual < n, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have count < {n}",
        expected=f"<{n}",
        entity="list",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_count_less_than_or_equal

to_have_count_less_than_or_equal(n: int, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert len(elements) <= n.

Source code in selenium_expect/assertions/list.py
def to_have_count_less_than_or_equal(
    self,
    n: int,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert len(elements) <= n."""
    elements = self._target

    def condition() -> tuple[bool, Any]:
        actual = len(elements)
        return (actual <= n, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have count <= {n}",
        expected=f"<={n}",
        entity="list",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_exact_texts

to_have_exact_texts(*texts: str, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert [el.text for el in elements] == list(texts) (exact, ordered, varargs).

Source code in selenium_expect/assertions/list.py
def to_have_exact_texts(
    self,
    *texts: str,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert [el.text for el in elements] == list(texts) (exact, ordered, varargs)."""
    if not texts:
        raise ValueError("At least one text must be provided")
    elements = self._target
    expected = list(texts)

    def condition() -> tuple[bool, Any]:
        actual = [el.text for el in elements]
        return (actual == expected, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have exact texts {expected!r}",
        expected=expected,
        entity="list",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_first_text

to_have_first_text(text: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert elements[0].text == text.

Source code in selenium_expect/assertions/list.py
def to_have_first_text(
    self,
    text: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert elements[0].text == text."""
    elements = self._target

    def condition() -> tuple[bool, Any]:
        if not elements:
            return (False, "empty list")
        actual = elements[0].text
        return (actual == text, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have first text {text!r}",
        expected=text,
        entity="list",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_last_text

to_have_last_text(text: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert elements[-1].text == text.

Source code in selenium_expect/assertions/list.py
def to_have_last_text(
    self,
    text: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert elements[-1].text == text."""
    elements = self._target

    def condition() -> tuple[bool, Any]:
        if not elements:
            return (False, "empty list")
        actual = elements[-1].text
        return (actual == text, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have last text {text!r}",
        expected=text,
        entity="list",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_none_text_contain

to_have_none_text_contain(text: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert no element contains text.

Source code in selenium_expect/assertions/list.py
def to_have_none_text_contain(
    self,
    text: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert no element contains text."""
    elements = self._target

    def condition() -> tuple[bool, Any]:
        actual = [el.text for el in elements]
        return (not any(text in (t or "") for t in actual) and len(actual) > 0, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have no text containing {text!r}",
        expected=f"none containing {text!r}",
        entity="list",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_none_visible

to_have_none_visible(*, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert no element is visible.

Source code in selenium_expect/assertions/list.py
def to_have_none_visible(
    self,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert no element is visible."""
    elements = self._target

    def condition() -> tuple[bool, Any]:
        actual = [el.is_displayed() for el in elements]
        return (not any(actual) and len(actual) > 0, actual)

    self._run_assertion(
        condition=condition,
        condition_name="to have none visible",
        expected="none visible",
        entity="list",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_nth_text_contains

to_have_nth_text_contains(index: int, text: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert text in elements[index].text.

Source code in selenium_expect/assertions/list.py
def to_have_nth_text_contains(
    self,
    index: int,
    text: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert text in elements[index].text."""
    elements = self._target

    def condition() -> tuple[bool, Any]:
        if index >= len(elements) or index < -len(elements):
            return (False, f"index {index} out of range")
        actual = elements[index].text
        return (text in (actual or ""), actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have text at [{index}] containing {text!r}",
        expected=text,
        entity="list",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_text_at

to_have_text_at(index: int, text: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert elements[index].text == text.

Source code in selenium_expect/assertions/list.py
def to_have_text_at(
    self,
    index: int,
    text: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert elements[index].text == text."""
    elements = self._target

    def condition() -> tuple[bool, Any]:
        if index >= len(elements) or index < -len(elements):
            return (False, f"index {index} out of range")
        actual = elements[index].text
        return (actual == text, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have text at [{index}]={text!r}",
        expected=text,
        entity="list",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_texts

to_have_texts(texts: list[str], *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert [el.text for el in elements] == texts (exact, ordered).

Source code in selenium_expect/assertions/list.py
def to_have_texts(
    self,
    texts: list[str],
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert [el.text for el in elements] == texts (exact, ordered)."""
    if not texts:
        raise ValueError("texts list must not be empty")
    elements = self._target

    def condition() -> tuple[bool, Any]:
        actual = [el.text for el in elements]
        return (actual == texts, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have texts {texts!r}",
        expected=texts,
        entity="list",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_texts_containing

to_have_texts_containing(*texts: str, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert each element.text contains the corresponding text (varargs).

Source code in selenium_expect/assertions/list.py
def to_have_texts_containing(
    self,
    *texts: str,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert each element.text contains the corresponding text (varargs)."""
    if not texts:
        raise ValueError("At least one text must be provided")
    elements = self._target
    expected = list(texts)

    def condition() -> tuple[bool, Any]:
        actual = [el.text for el in elements]
        if len(actual) != len(expected):
            return (False, actual)
        return (all(t in (a or "") for a, t in zip(actual, expected, strict=False)), actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have texts containing {expected!r}",
        expected=expected,
        entity="list",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_texts_contains

to_have_texts_contains(texts: list[str], *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert each text in texts is in corresponding element.text.

Source code in selenium_expect/assertions/list.py
def to_have_texts_contains(
    self,
    texts: list[str],
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert each text in texts is in corresponding element.text."""
    if not texts:
        raise ValueError("texts list must not be empty")
    elements = self._target

    def condition() -> tuple[bool, Any]:
        actual = [el.text for el in elements]
        if len(actual) != len(texts):
            return (False, actual)
        return (all(t in (a or "") for a, t in zip(actual, texts, strict=False)), actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have texts containing {texts!r}",
        expected=texts,
        entity="list",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_texts_in_any_order

to_have_texts_in_any_order(*texts: str, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert element texts match texts in any order (varargs).

Source code in selenium_expect/assertions/list.py
def to_have_texts_in_any_order(
    self,
    *texts: str,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert element texts match texts in any order (varargs)."""
    if not texts:
        raise ValueError("At least one text must be provided")
    elements = self._target
    expected = sorted(texts)

    def condition() -> tuple[bool, Any]:
        actual = sorted(el.text for el in elements)
        return (actual == expected, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have texts in any order {list(texts)!r}",
        expected=list(texts),
        entity="list",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_texts_match

to_have_texts_match(patterns: list[str], *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert each element's text matches the corresponding regex pattern.

Source code in selenium_expect/assertions/list.py
def to_have_texts_match(
    self,
    patterns: list[str],
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert each element's text matches the corresponding regex pattern."""
    if not patterns:
        raise ValueError("patterns list must not be empty")
    elements = self._target

    def condition() -> tuple[bool, Any]:
        actual = [el.text for el in elements]
        if len(actual) != len(patterns):
            return (False, actual)
        return (
            all(
                re.search(p, a or "") is not None
                for a, p in zip(actual, patterns, strict=False)
            ),
            actual,
        )

    self._run_assertion(
        condition=condition,
        condition_name=f"to have texts matching {patterns!r}",
        expected=patterns,
        entity="list",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_value_at

to_have_value_at(index: int, value: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert elements[index].get_attribute('value') == value.

Source code in selenium_expect/assertions/list.py
def to_have_value_at(
    self,
    index: int,
    value: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert elements[index].get_attribute('value') == value."""
    elements = self._target

    def condition() -> tuple[bool, Any]:
        if index >= len(elements) or index < -len(elements):
            return (False, f"index {index} out of range")
        actual = elements[index].get_attribute("value")
        return (actual == value, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have value at [{index}]={value!r}",
        expected=value,
        entity="list",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_values

to_have_values(values: list[str], *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert [el.get_attribute('value') for el in elements] == values.

Source code in selenium_expect/assertions/list.py
def to_have_values(
    self,
    values: list[str],
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert [el.get_attribute('value') for el in elements] == values."""
    if not values:
        raise ValueError("values list must not be empty")
    elements = self._target

    def condition() -> tuple[bool, Any]:
        actual = [el.get_attribute("value") for el in elements]
        return (actual == values, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have values {values!r}",
        expected=values,
        entity="list",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_values_contains

to_have_values_contains(values: list[str], *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert each value is a substring of the corresponding element's value.

Source code in selenium_expect/assertions/list.py
def to_have_values_contains(
    self,
    values: list[str],
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert each value is a substring of the corresponding element's value."""
    if not values:
        raise ValueError("values list must not be empty")
    elements = self._target

    def condition() -> tuple[bool, Any]:
        actual = [el.get_attribute("value") for el in elements]
        if len(actual) != len(values):
            return (False, actual)
        return (all(v in (a or "") for a, v in zip(actual, values, strict=False)), actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have values containing {values!r}",
        expected=values,
        entity="list",
        timeout=timeout,
        polling=polling,
    )

    return self

ExpectAlert

Assertions for JavaScript Alert objects.

Methods: to_be_present, to_have_text, to_have_text_contains, to_have_text_matches

Waiting for an alert

driver.switch_to.alert raises NoAlertPresentException immediately if no alert is present, which bypasses the retry loop. To poll until an alert appears, pass a lazy Alert object:

from selenium.webdriver.common.alert import Alert

expect(Alert(driver)).to_be_present()  # polls until the alert shows up

selenium_expect.assertions.alert.ExpectAlert

Bases: AssertionMixin

Assertions for JavaScript alerts/confirms/prompts.

Source code in selenium_expect/assertions/alert.py
class ExpectAlert(AssertionMixin):
    """Assertions for JavaScript alerts/confirms/prompts."""

    def __init__(
        self,
        target: Alert,
        config: ExpectConfig | None = None,
        message: str | None = None,
        negate: bool = False,
    ) -> None:
        super().__init__(target=target, config=config, message=message, negate=negate)

    def to_be_present(
        self,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert alert is present (accessing .text doesn't raise)."""
        alert = self._target

        def condition() -> tuple[bool, Any]:
            try:
                _ = alert.text
                return (True, "present")
            except NoAlertPresentException:
                return (False, "not present")

        self._run_assertion(
            condition=condition,
            condition_name="to be present",
            expected="present",
            entity="alert",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_text(
        self,
        text: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert alert.text == text."""
        alert = self._target

        def condition() -> tuple[bool, Any]:
            actual = alert.text
            return (actual == text, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have text {text!r}",
            expected=text,
            entity="alert",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_text_contains(
        self,
        text: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert text in alert.text."""
        alert = self._target

        def condition() -> tuple[bool, Any]:
            actual = alert.text
            return (text in (actual or ""), actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have text containing {text!r}",
            expected=text,
            entity="alert",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_text_matches(
        self,
        pattern: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert re.search(pattern, alert.text)."""
        alert = self._target

        def condition() -> tuple[bool, Any]:
            actual = alert.text
            return (re.search(pattern, actual or "") is not None, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have text matching {pattern!r}",
            expected=pattern,
            entity="alert",
            timeout=timeout,
            polling=polling,
        )

        return self

    # --- Overrides ---

    def _entity_description(self) -> str:
        return "Alert"

    def _get_element_html(self) -> str | None:
        return None

to_be_present

to_be_present(*, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert alert is present (accessing .text doesn't raise).

Source code in selenium_expect/assertions/alert.py
def to_be_present(
    self,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert alert is present (accessing .text doesn't raise)."""
    alert = self._target

    def condition() -> tuple[bool, Any]:
        try:
            _ = alert.text
            return (True, "present")
        except NoAlertPresentException:
            return (False, "not present")

    self._run_assertion(
        condition=condition,
        condition_name="to be present",
        expected="present",
        entity="alert",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_text

to_have_text(text: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert alert.text == text.

Source code in selenium_expect/assertions/alert.py
def to_have_text(
    self,
    text: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert alert.text == text."""
    alert = self._target

    def condition() -> tuple[bool, Any]:
        actual = alert.text
        return (actual == text, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have text {text!r}",
        expected=text,
        entity="alert",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_text_contains

to_have_text_contains(text: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert text in alert.text.

Source code in selenium_expect/assertions/alert.py
def to_have_text_contains(
    self,
    text: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert text in alert.text."""
    alert = self._target

    def condition() -> tuple[bool, Any]:
        actual = alert.text
        return (text in (actual or ""), actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have text containing {text!r}",
        expected=text,
        entity="alert",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_text_matches

to_have_text_matches(pattern: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert re.search(pattern, alert.text).

Source code in selenium_expect/assertions/alert.py
def to_have_text_matches(
    self,
    pattern: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert re.search(pattern, alert.text)."""
    alert = self._target

    def condition() -> tuple[bool, Any]:
        actual = alert.text
        return (re.search(pattern, actual or "") is not None, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have text matching {pattern!r}",
        expected=pattern,
        entity="alert",
        timeout=timeout,
        polling=polling,
    )

    return self

ExpectCookie

Assertions for browser cookies.

Key method categories:

  • Presence: to_have_cookie, to_have_no_cookies, to_have_cookie_count, to_have_cookie_count_greater_than
  • Value: to_have_cookie_value, to_have_cookie_domain, to_have_cookie_path, to_have_cookie_expiry
  • Security: to_have_cookie_secure, to_have_cookie_http_only, to_have_cookie_same_site

selenium_expect.assertions.cookie.ExpectCookie

Bases: AssertionMixin

Assertions for browser cookies.

Initialized with a WebDriver — uses driver.get_cookie() and driver.get_cookies() to inspect cookies. Not dispatched via expect() (which maps WebDriver to ExpectDriver); instantiate directly or via a helper.

Source code in selenium_expect/assertions/cookie.py
class ExpectCookie(AssertionMixin):
    """Assertions for browser cookies.

    Initialized with a ``WebDriver`` — uses ``driver.get_cookie()`` and
    ``driver.get_cookies()`` to inspect cookies.  Not dispatched via
    ``expect()`` (which maps ``WebDriver`` to ``ExpectDriver``); instantiate
    directly or via a helper.
    """

    def __init__(
        self,
        target: WebDriver,
        config: ExpectConfig | None = None,
        message: str | None = None,
        negate: bool = False,
    ) -> None:
        super().__init__(target=target, config=config, message=message, negate=negate)

    # --- Cookie presence ---

    def to_have_cookie(
        self,
        name: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert driver.get_cookie(name) is not None."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            cookie = driver.get_cookie(name)
            return (cookie is not None, cookie)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have cookie {name!r}",
            expected=name,
            entity="cookies",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_cookie_value(
        self,
        name: str,
        value: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert driver.get_cookie(name)['value'] == value."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            cookie = driver.get_cookie(name)
            actual = cookie.get("value") if cookie else None
            return (actual == value, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have cookie {name!r} value {value!r}",
            expected=value,
            entity="cookies",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_cookie_value_contains(
        self,
        name: str,
        value: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert value in driver.get_cookie(name)['value']."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            cookie = driver.get_cookie(name)
            actual = cookie.get("value") if cookie else None
            return (value in (actual or ""), actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have cookie {name!r} value containing {value!r}",
            expected=value,
            entity="cookies",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_cookie_domain(
        self,
        name: str,
        domain: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert driver.get_cookie(name)['domain'] == domain."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            cookie = driver.get_cookie(name)
            actual = cookie.get("domain") if cookie else None
            return (actual == domain, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have cookie {name!r} domain {domain!r}",
            expected=domain,
            entity="cookies",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_cookie_path(
        self,
        name: str,
        path: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert driver.get_cookie(name)['path'] == path."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            cookie = driver.get_cookie(name)
            actual = cookie.get("path") if cookie else None
            return (actual == path, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have cookie {name!r} path {path!r}",
            expected=path,
            entity="cookies",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_cookie_http_only(
        self,
        name: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert driver.get_cookie(name)['httpOnly'] == True."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            cookie = driver.get_cookie(name)
            actual = cookie.get("httpOnly") if cookie else None
            return (actual is True, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have cookie {name!r} httpOnly=True",
            expected=True,
            entity="cookies",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_cookie_secure(
        self,
        name: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert driver.get_cookie(name)['secure'] == True."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            cookie = driver.get_cookie(name)
            actual = cookie.get("secure") if cookie else None
            return (actual is True, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have cookie {name!r} secure=True",
            expected=True,
            entity="cookies",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_cookie_same_site(
        self,
        name: str,
        same_site: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert driver.get_cookie(name)['sameSite'] == same_site."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            cookie = driver.get_cookie(name)
            actual = cookie.get("sameSite") if cookie else None
            return (actual == same_site, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have cookie {name!r} sameSite={same_site!r}",
            expected=same_site,
            entity="cookies",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_cookie_count(
        self,
        count: int,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert len(driver.get_cookies()) == count."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            actual = len(driver.get_cookies())
            return (actual == count, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have cookie count {count}",
            expected=count,
            entity="cookies",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_cookie_count_greater_than(
        self,
        n: int,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert len(driver.get_cookies()) > n."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            actual = len(driver.get_cookies())
            return (actual > n, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have cookie count > {n}",
            expected=f">{n}",
            entity="cookies",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_cookie_expiry(
        self,
        name: str,
        expiry: int,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert driver.get_cookie(name)['expiry'] == expiry."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            cookie = driver.get_cookie(name)
            if cookie is None:
                return (False, "cookie not found")
            actual = cookie.get("expiry")
            return (actual == expiry, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have cookie {name!r} expiry {expiry}",
            expected=expiry,
            entity="cookies",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_no_cookies(
        self,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert len(driver.get_cookies()) == 0."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            actual = len(driver.get_cookies())
            return (actual == 0, actual)

        self._run_assertion(
            condition=condition,
            condition_name="to have no cookies",
            expected=0,
            entity="cookies",
            timeout=timeout,
            polling=polling,
        )

        return self

    # --- Overrides ---

    def _entity_description(self) -> str:
        return "cookies"

    def _get_element_html(self) -> str | None:
        return None
to_have_cookie(name: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert driver.get_cookie(name) is not None.

Source code in selenium_expect/assertions/cookie.py
def to_have_cookie(
    self,
    name: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert driver.get_cookie(name) is not None."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        cookie = driver.get_cookie(name)
        return (cookie is not None, cookie)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have cookie {name!r}",
        expected=name,
        entity="cookies",
        timeout=timeout,
        polling=polling,
    )

    return self
to_have_cookie_count(count: int, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert len(driver.get_cookies()) == count.

Source code in selenium_expect/assertions/cookie.py
def to_have_cookie_count(
    self,
    count: int,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert len(driver.get_cookies()) == count."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        actual = len(driver.get_cookies())
        return (actual == count, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have cookie count {count}",
        expected=count,
        entity="cookies",
        timeout=timeout,
        polling=polling,
    )

    return self
to_have_cookie_count_greater_than(n: int, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert len(driver.get_cookies()) > n.

Source code in selenium_expect/assertions/cookie.py
def to_have_cookie_count_greater_than(
    self,
    n: int,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert len(driver.get_cookies()) > n."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        actual = len(driver.get_cookies())
        return (actual > n, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have cookie count > {n}",
        expected=f">{n}",
        entity="cookies",
        timeout=timeout,
        polling=polling,
    )

    return self
to_have_cookie_domain(name: str, domain: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert driver.get_cookie(name)['domain'] == domain.

Source code in selenium_expect/assertions/cookie.py
def to_have_cookie_domain(
    self,
    name: str,
    domain: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert driver.get_cookie(name)['domain'] == domain."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        cookie = driver.get_cookie(name)
        actual = cookie.get("domain") if cookie else None
        return (actual == domain, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have cookie {name!r} domain {domain!r}",
        expected=domain,
        entity="cookies",
        timeout=timeout,
        polling=polling,
    )

    return self
to_have_cookie_expiry(name: str, expiry: int, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert driver.get_cookie(name)['expiry'] == expiry.

Source code in selenium_expect/assertions/cookie.py
def to_have_cookie_expiry(
    self,
    name: str,
    expiry: int,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert driver.get_cookie(name)['expiry'] == expiry."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        cookie = driver.get_cookie(name)
        if cookie is None:
            return (False, "cookie not found")
        actual = cookie.get("expiry")
        return (actual == expiry, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have cookie {name!r} expiry {expiry}",
        expected=expiry,
        entity="cookies",
        timeout=timeout,
        polling=polling,
    )

    return self
to_have_cookie_http_only(name: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert driver.get_cookie(name)['httpOnly'] == True.

Source code in selenium_expect/assertions/cookie.py
def to_have_cookie_http_only(
    self,
    name: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert driver.get_cookie(name)['httpOnly'] == True."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        cookie = driver.get_cookie(name)
        actual = cookie.get("httpOnly") if cookie else None
        return (actual is True, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have cookie {name!r} httpOnly=True",
        expected=True,
        entity="cookies",
        timeout=timeout,
        polling=polling,
    )

    return self
to_have_cookie_path(name: str, path: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert driver.get_cookie(name)['path'] == path.

Source code in selenium_expect/assertions/cookie.py
def to_have_cookie_path(
    self,
    name: str,
    path: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert driver.get_cookie(name)['path'] == path."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        cookie = driver.get_cookie(name)
        actual = cookie.get("path") if cookie else None
        return (actual == path, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have cookie {name!r} path {path!r}",
        expected=path,
        entity="cookies",
        timeout=timeout,
        polling=polling,
    )

    return self
to_have_cookie_same_site(name: str, same_site: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert driver.get_cookie(name)['sameSite'] == same_site.

Source code in selenium_expect/assertions/cookie.py
def to_have_cookie_same_site(
    self,
    name: str,
    same_site: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert driver.get_cookie(name)['sameSite'] == same_site."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        cookie = driver.get_cookie(name)
        actual = cookie.get("sameSite") if cookie else None
        return (actual == same_site, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have cookie {name!r} sameSite={same_site!r}",
        expected=same_site,
        entity="cookies",
        timeout=timeout,
        polling=polling,
    )

    return self
to_have_cookie_secure(name: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert driver.get_cookie(name)['secure'] == True.

Source code in selenium_expect/assertions/cookie.py
def to_have_cookie_secure(
    self,
    name: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert driver.get_cookie(name)['secure'] == True."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        cookie = driver.get_cookie(name)
        actual = cookie.get("secure") if cookie else None
        return (actual is True, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have cookie {name!r} secure=True",
        expected=True,
        entity="cookies",
        timeout=timeout,
        polling=polling,
    )

    return self
to_have_cookie_value(name: str, value: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert driver.get_cookie(name)['value'] == value.

Source code in selenium_expect/assertions/cookie.py
def to_have_cookie_value(
    self,
    name: str,
    value: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert driver.get_cookie(name)['value'] == value."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        cookie = driver.get_cookie(name)
        actual = cookie.get("value") if cookie else None
        return (actual == value, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have cookie {name!r} value {value!r}",
        expected=value,
        entity="cookies",
        timeout=timeout,
        polling=polling,
    )

    return self
to_have_cookie_value_contains(name: str, value: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert value in driver.get_cookie(name)['value'].

Source code in selenium_expect/assertions/cookie.py
def to_have_cookie_value_contains(
    self,
    name: str,
    value: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert value in driver.get_cookie(name)['value']."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        cookie = driver.get_cookie(name)
        actual = cookie.get("value") if cookie else None
        return (value in (actual or ""), actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have cookie {name!r} value containing {value!r}",
        expected=value,
        entity="cookies",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_no_cookies

to_have_no_cookies(*, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert len(driver.get_cookies()) == 0.

Source code in selenium_expect/assertions/cookie.py
def to_have_no_cookies(
    self,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert len(driver.get_cookies()) == 0."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        actual = len(driver.get_cookies())
        return (actual == 0, actual)

    self._run_assertion(
        condition=condition,
        condition_name="to have no cookies",
        expected=0,
        entity="cookies",
        timeout=timeout,
        polling=polling,
    )

    return self

ExpectSelect

Assertions for HTML <select> elements.

Key method categories:

  • Selection: to_have_value, to_have_first_selected_value, to_have_selected_text, to_have_selected_index, to_have_selected_values, to_have_selected_texts, to_have_selected_count, to_have_no_selection
  • Options: to_have_option_count, to_have_option_count_greater_than, to_have_option, to_have_option_text, to_have_option_at_index
  • Type: to_be_multiple, to_be_single_select

selenium_expect.assertions.select.ExpectSelect

Bases: AssertionMixin

Assertions for Select/dropdown elements.

Source code in selenium_expect/assertions/select.py
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
class ExpectSelect(AssertionMixin):
    """Assertions for Select/dropdown elements."""

    def __init__(
        self,
        target: Select,
        config: ExpectConfig | None = None,
        message: str | None = None,
        negate: bool = False,
    ) -> None:
        super().__init__(target=target, config=config, message=message, negate=negate)

    def to_have_value(
        self,
        value: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert select.first_selected_option.get_attribute('value') == value."""
        select = self._target

        def condition() -> tuple[bool, Any]:
            actual = select.first_selected_option.get_attribute("value")
            return (actual == value, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have value {value!r}",
            expected=value,
            entity="select",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_first_selected_value(
        self,
        value: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert select.first_selected_option.get_attribute('value') == value (alias)."""
        select = self._target

        def condition() -> tuple[bool, Any]:
            actual = select.first_selected_option.get_attribute("value")
            return (actual == value, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have first selected value {value!r}",
            expected=value,
            entity="select",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_selected_text(
        self,
        text: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert select.first_selected_option.text == text."""
        select = self._target

        def condition() -> tuple[bool, Any]:
            actual = select.first_selected_option.text
            return (actual == text, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have selected text {text!r}",
            expected=text,
            entity="select",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_selected_values(
        self,
        values: list[str],
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert [opt.get_attribute('value') for opt in all_selected_options] == values."""
        if not values:
            raise ValueError("values list must not be empty")
        select = self._target

        def condition() -> tuple[bool, Any]:
            actual = [opt.get_attribute("value") for opt in select.all_selected_options]
            return (actual == values, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have selected values {values!r}",
            expected=values,
            entity="select",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_selected_texts(
        self,
        texts: list[str],
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert [opt.text for opt in all_selected_options] == texts."""
        if not texts:
            raise ValueError("texts list must not be empty")
        select = self._target

        def condition() -> tuple[bool, Any]:
            actual = [opt.text for opt in select.all_selected_options]
            return (actual == texts, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have selected texts {texts!r}",
            expected=texts,
            entity="select",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_selected_count(
        self,
        count: int,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert len(select.all_selected_options) == count."""
        select = self._target

        def condition() -> tuple[bool, Any]:
            actual = len(select.all_selected_options)
            return (actual == count, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have selected count {count}",
            expected=count,
            entity="select",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_option_count(
        self,
        count: int,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert len(select.options) == count."""
        select = self._target

        def condition() -> tuple[bool, Any]:
            actual = len(select.options)
            return (actual == count, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have option count {count}",
            expected=count,
            entity="select",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_option_count_greater_than(
        self,
        n: int,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert len(select.options) > n."""
        select = self._target

        def condition() -> tuple[bool, Any]:
            actual = len(select.options)
            return (actual > n, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have option count > {n}",
            expected=f">{n}",
            entity="select",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_option_at_index(
        self,
        index: int,
        text: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert select.options[index].text == text."""
        select = self._target

        def condition() -> tuple[bool, Any]:
            if index >= len(select.options) or index < -len(select.options):
                return (False, f"index {index} out of range")
            actual = select.options[index].text
            return (actual == text, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have option at [{index}]={text!r}",
            expected=text,
            entity="select",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_option(
        self,
        value: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert value exists in select options (by value attribute)."""
        select = self._target

        def condition() -> tuple[bool, Any]:
            actual = [opt.get_attribute("value") for opt in select.options]
            return (value in actual, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have option with value {value!r}",
            expected=value,
            entity="select",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_option_text(
        self,
        text: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert text exists in select options (by visible text)."""
        select = self._target

        def condition() -> tuple[bool, Any]:
            actual = [opt.text for opt in select.options]
            return (text in actual, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have option with text {text!r}",
            expected=text,
            entity="select",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_be_multiple(
        self,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert select.is_multiple == True."""
        select = self._target

        def condition() -> tuple[bool, Any]:
            actual = select.is_multiple
            return (actual is True, actual)

        self._run_assertion(
            condition=condition,
            condition_name="to be multiple",
            expected=True,
            entity="select",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_be_single_select(
        self,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert select.is_multiple == False."""
        select = self._target

        def condition() -> tuple[bool, Any]:
            actual = select.is_multiple
            return (actual is False, actual)

        self._run_assertion(
            condition=condition,
            condition_name="to be single select",
            expected=False,
            entity="select",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_selected_index(
        self,
        index: int,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert select.options[index].is_selected() == True."""
        select = self._target

        def condition() -> tuple[bool, Any]:
            if index >= len(select.options) or index < -len(select.options):
                return (False, f"index {index} out of range")
            actual = select.options[index].is_selected()
            return (actual is True, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have selected index {index}",
            expected=True,
            entity="select",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_no_selection(
        self,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert select.all_selected_options is empty."""
        select = self._target

        def condition() -> tuple[bool, Any]:
            actual = len(select.all_selected_options)
            return (actual == 0, actual)

        self._run_assertion(
            condition=condition,
            condition_name="to have no selection",
            expected=0,
            entity="select",
            timeout=timeout,
            polling=polling,
        )

        return self

    # --- Overrides ---

    def _entity_description(self) -> str:
        return "Select"

    def _get_element_html(self) -> str | None:
        return None

to_be_multiple

to_be_multiple(*, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert select.is_multiple == True.

Source code in selenium_expect/assertions/select.py
def to_be_multiple(
    self,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert select.is_multiple == True."""
    select = self._target

    def condition() -> tuple[bool, Any]:
        actual = select.is_multiple
        return (actual is True, actual)

    self._run_assertion(
        condition=condition,
        condition_name="to be multiple",
        expected=True,
        entity="select",
        timeout=timeout,
        polling=polling,
    )

    return self

to_be_single_select

to_be_single_select(*, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert select.is_multiple == False.

Source code in selenium_expect/assertions/select.py
def to_be_single_select(
    self,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert select.is_multiple == False."""
    select = self._target

    def condition() -> tuple[bool, Any]:
        actual = select.is_multiple
        return (actual is False, actual)

    self._run_assertion(
        condition=condition,
        condition_name="to be single select",
        expected=False,
        entity="select",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_first_selected_value

to_have_first_selected_value(value: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert select.first_selected_option.get_attribute('value') == value (alias).

Source code in selenium_expect/assertions/select.py
def to_have_first_selected_value(
    self,
    value: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert select.first_selected_option.get_attribute('value') == value (alias)."""
    select = self._target

    def condition() -> tuple[bool, Any]:
        actual = select.first_selected_option.get_attribute("value")
        return (actual == value, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have first selected value {value!r}",
        expected=value,
        entity="select",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_no_selection

to_have_no_selection(*, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert select.all_selected_options is empty.

Source code in selenium_expect/assertions/select.py
def to_have_no_selection(
    self,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert select.all_selected_options is empty."""
    select = self._target

    def condition() -> tuple[bool, Any]:
        actual = len(select.all_selected_options)
        return (actual == 0, actual)

    self._run_assertion(
        condition=condition,
        condition_name="to have no selection",
        expected=0,
        entity="select",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_option

to_have_option(value: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert value exists in select options (by value attribute).

Source code in selenium_expect/assertions/select.py
def to_have_option(
    self,
    value: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert value exists in select options (by value attribute)."""
    select = self._target

    def condition() -> tuple[bool, Any]:
        actual = [opt.get_attribute("value") for opt in select.options]
        return (value in actual, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have option with value {value!r}",
        expected=value,
        entity="select",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_option_at_index

to_have_option_at_index(index: int, text: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert select.options[index].text == text.

Source code in selenium_expect/assertions/select.py
def to_have_option_at_index(
    self,
    index: int,
    text: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert select.options[index].text == text."""
    select = self._target

    def condition() -> tuple[bool, Any]:
        if index >= len(select.options) or index < -len(select.options):
            return (False, f"index {index} out of range")
        actual = select.options[index].text
        return (actual == text, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have option at [{index}]={text!r}",
        expected=text,
        entity="select",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_option_count

to_have_option_count(count: int, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert len(select.options) == count.

Source code in selenium_expect/assertions/select.py
def to_have_option_count(
    self,
    count: int,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert len(select.options) == count."""
    select = self._target

    def condition() -> tuple[bool, Any]:
        actual = len(select.options)
        return (actual == count, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have option count {count}",
        expected=count,
        entity="select",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_option_count_greater_than

to_have_option_count_greater_than(n: int, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert len(select.options) > n.

Source code in selenium_expect/assertions/select.py
def to_have_option_count_greater_than(
    self,
    n: int,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert len(select.options) > n."""
    select = self._target

    def condition() -> tuple[bool, Any]:
        actual = len(select.options)
        return (actual > n, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have option count > {n}",
        expected=f">{n}",
        entity="select",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_option_text

to_have_option_text(text: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert text exists in select options (by visible text).

Source code in selenium_expect/assertions/select.py
def to_have_option_text(
    self,
    text: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert text exists in select options (by visible text)."""
    select = self._target

    def condition() -> tuple[bool, Any]:
        actual = [opt.text for opt in select.options]
        return (text in actual, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have option with text {text!r}",
        expected=text,
        entity="select",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_selected_count

to_have_selected_count(count: int, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert len(select.all_selected_options) == count.

Source code in selenium_expect/assertions/select.py
def to_have_selected_count(
    self,
    count: int,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert len(select.all_selected_options) == count."""
    select = self._target

    def condition() -> tuple[bool, Any]:
        actual = len(select.all_selected_options)
        return (actual == count, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have selected count {count}",
        expected=count,
        entity="select",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_selected_index

to_have_selected_index(index: int, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert select.options[index].is_selected() == True.

Source code in selenium_expect/assertions/select.py
def to_have_selected_index(
    self,
    index: int,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert select.options[index].is_selected() == True."""
    select = self._target

    def condition() -> tuple[bool, Any]:
        if index >= len(select.options) or index < -len(select.options):
            return (False, f"index {index} out of range")
        actual = select.options[index].is_selected()
        return (actual is True, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have selected index {index}",
        expected=True,
        entity="select",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_selected_text

to_have_selected_text(text: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert select.first_selected_option.text == text.

Source code in selenium_expect/assertions/select.py
def to_have_selected_text(
    self,
    text: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert select.first_selected_option.text == text."""
    select = self._target

    def condition() -> tuple[bool, Any]:
        actual = select.first_selected_option.text
        return (actual == text, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have selected text {text!r}",
        expected=text,
        entity="select",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_selected_texts

to_have_selected_texts(texts: list[str], *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert [opt.text for opt in all_selected_options] == texts.

Source code in selenium_expect/assertions/select.py
def to_have_selected_texts(
    self,
    texts: list[str],
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert [opt.text for opt in all_selected_options] == texts."""
    if not texts:
        raise ValueError("texts list must not be empty")
    select = self._target

    def condition() -> tuple[bool, Any]:
        actual = [opt.text for opt in select.all_selected_options]
        return (actual == texts, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have selected texts {texts!r}",
        expected=texts,
        entity="select",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_selected_values

to_have_selected_values(values: list[str], *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert [opt.get_attribute('value') for opt in all_selected_options] == values.

Source code in selenium_expect/assertions/select.py
def to_have_selected_values(
    self,
    values: list[str],
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert [opt.get_attribute('value') for opt in all_selected_options] == values."""
    if not values:
        raise ValueError("values list must not be empty")
    select = self._target

    def condition() -> tuple[bool, Any]:
        actual = [opt.get_attribute("value") for opt in select.all_selected_options]
        return (actual == values, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have selected values {values!r}",
        expected=values,
        entity="select",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_value

to_have_value(value: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert select.first_selected_option.get_attribute('value') == value.

Source code in selenium_expect/assertions/select.py
def to_have_value(
    self,
    value: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert select.first_selected_option.get_attribute('value') == value."""
    select = self._target

    def condition() -> tuple[bool, Any]:
        actual = select.first_selected_option.get_attribute("value")
        return (actual == value, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have value {value!r}",
        expected=value,
        entity="select",
        timeout=timeout,
        polling=polling,
    )

    return self

ExpectShadow

Assertions for ShadowRoot elements.

Methods: to_have_element, to_have_element_count, to_have_element_text, to_have_element_attribute, to_have_element_visible

selenium_expect.assertions.shadow.ExpectShadow

Bases: AssertionMixin

Assertions for ShadowRoot elements.

Source code in selenium_expect/assertions/shadow.py
class ExpectShadow(AssertionMixin):
    """Assertions for ShadowRoot elements."""

    def __init__(
        self,
        target: ShadowRoot,
        config: ExpectConfig | None = None,
        message: str | None = None,
        negate: bool = False,
    ) -> None:
        super().__init__(target=target, config=config, message=message, negate=negate)

    def to_have_element(
        self,
        by: str,
        value: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert shadow_root.find_element(by, value) doesn't raise."""
        shadow = self._target

        def condition() -> tuple[bool, Any]:
            try:
                el = shadow.find_element(by, value)
                return (True, el)
            except NoSuchElementException:
                return (False, "not found")

        self._run_assertion(
            condition=condition,
            condition_name=f"to have element ({by}={value!r})",
            expected="present",
            entity="shadow",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_element_count(
        self,
        by: str,
        value: str,
        count: int,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert len(shadow_root.find_elements(by, value)) == count."""
        shadow = self._target

        def condition() -> tuple[bool, Any]:
            actual = len(shadow.find_elements(by, value))
            return (actual == count, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have element count {count} ({by}={value!r})",
            expected=count,
            entity="shadow",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_element_text(
        self,
        by: str,
        value: str,
        text: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert shadow_root.find_element(by, value).text == text."""
        shadow = self._target

        def condition() -> tuple[bool, Any]:
            try:
                el = shadow.find_element(by, value)
                actual = el.text
                return (actual == text, actual)
            except NoSuchElementException:
                return (False, "not found")

        self._run_assertion(
            condition=condition,
            condition_name=f"to have element text {text!r} ({by}={value!r})",
            expected=text,
            entity="shadow",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_element_attribute(
        self,
        by: str,
        value: str,
        attr: str,
        attr_value: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert shadow_root.find_element(by, value).get_attribute(attr) == attr_value."""
        shadow = self._target

        def condition() -> tuple[bool, Any]:
            try:
                el = shadow.find_element(by, value)
                actual = el.get_attribute(attr)
                return (actual == attr_value, actual)
            except NoSuchElementException:
                return (False, "not found")

        self._run_assertion(
            condition=condition,
            condition_name=f"to have element attribute {attr!r}={attr_value!r} ({by}={value!r})",
            expected=attr_value,
            entity="shadow",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_element_visible(
        self,
        by: str,
        value: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert shadow_root.find_element(by, value).is_displayed() == True."""
        shadow = self._target

        def condition() -> tuple[bool, Any]:
            try:
                el = shadow.find_element(by, value)
                actual = el.is_displayed()
                return (actual is True, actual)
            except NoSuchElementException:
                return (False, "not found")

        self._run_assertion(
            condition=condition,
            condition_name=f"to have element visible ({by}={value!r})",
            expected=True,
            entity="shadow",
            timeout=timeout,
            polling=polling,
        )

        return self

    # --- Overrides ---

    def _entity_description(self) -> str:
        return "ShadowRoot"

    def _get_element_html(self) -> str | None:
        return None

to_have_element

to_have_element(by: str, value: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert shadow_root.find_element(by, value) doesn't raise.

Source code in selenium_expect/assertions/shadow.py
def to_have_element(
    self,
    by: str,
    value: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert shadow_root.find_element(by, value) doesn't raise."""
    shadow = self._target

    def condition() -> tuple[bool, Any]:
        try:
            el = shadow.find_element(by, value)
            return (True, el)
        except NoSuchElementException:
            return (False, "not found")

    self._run_assertion(
        condition=condition,
        condition_name=f"to have element ({by}={value!r})",
        expected="present",
        entity="shadow",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_element_attribute

to_have_element_attribute(by: str, value: str, attr: str, attr_value: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert shadow_root.find_element(by, value).get_attribute(attr) == attr_value.

Source code in selenium_expect/assertions/shadow.py
def to_have_element_attribute(
    self,
    by: str,
    value: str,
    attr: str,
    attr_value: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert shadow_root.find_element(by, value).get_attribute(attr) == attr_value."""
    shadow = self._target

    def condition() -> tuple[bool, Any]:
        try:
            el = shadow.find_element(by, value)
            actual = el.get_attribute(attr)
            return (actual == attr_value, actual)
        except NoSuchElementException:
            return (False, "not found")

    self._run_assertion(
        condition=condition,
        condition_name=f"to have element attribute {attr!r}={attr_value!r} ({by}={value!r})",
        expected=attr_value,
        entity="shadow",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_element_count

to_have_element_count(by: str, value: str, count: int, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert len(shadow_root.find_elements(by, value)) == count.

Source code in selenium_expect/assertions/shadow.py
def to_have_element_count(
    self,
    by: str,
    value: str,
    count: int,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert len(shadow_root.find_elements(by, value)) == count."""
    shadow = self._target

    def condition() -> tuple[bool, Any]:
        actual = len(shadow.find_elements(by, value))
        return (actual == count, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have element count {count} ({by}={value!r})",
        expected=count,
        entity="shadow",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_element_text

to_have_element_text(by: str, value: str, text: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert shadow_root.find_element(by, value).text == text.

Source code in selenium_expect/assertions/shadow.py
def to_have_element_text(
    self,
    by: str,
    value: str,
    text: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert shadow_root.find_element(by, value).text == text."""
    shadow = self._target

    def condition() -> tuple[bool, Any]:
        try:
            el = shadow.find_element(by, value)
            actual = el.text
            return (actual == text, actual)
        except NoSuchElementException:
            return (False, "not found")

    self._run_assertion(
        condition=condition,
        condition_name=f"to have element text {text!r} ({by}={value!r})",
        expected=text,
        entity="shadow",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_element_visible

to_have_element_visible(by: str, value: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert shadow_root.find_element(by, value).is_displayed() == True.

Source code in selenium_expect/assertions/shadow.py
def to_have_element_visible(
    self,
    by: str,
    value: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert shadow_root.find_element(by, value).is_displayed() == True."""
    shadow = self._target

    def condition() -> tuple[bool, Any]:
        try:
            el = shadow.find_element(by, value)
            actual = el.is_displayed()
            return (actual is True, actual)
        except NoSuchElementException:
            return (False, "not found")

    self._run_assertion(
        condition=condition,
        condition_name=f"to have element visible ({by}={value!r})",
        expected=True,
        entity="shadow",
        timeout=timeout,
        polling=polling,
    )

    return self

ExpectJS

Assertions for JavaScript and browser state.

Key method categories:

  • JS execution: to_have_js_result, to_have_js_result_contains, to_have_async_js_result, to_have_js_variable
  • localStorage: to_have_local_storage_item, to_have_local_storage_item_present, to_have_local_storage_item_absent, to_have_local_storage_length
  • sessionStorage: to_have_session_storage_item, to_have_session_storage_item_present, to_have_session_storage_item_absent, to_have_session_storage_length

selenium_expect.assertions.js.ExpectJS

Bases: AssertionMixin

Assertions for JavaScript / browser state via driver.execute_script.

Not dispatched via expect() (which maps WebDriver to ExpectDriver); instantiate directly with a driver.

Source code in selenium_expect/assertions/js.py
class ExpectJS(AssertionMixin):
    """Assertions for JavaScript / browser state via ``driver.execute_script``.

    Not dispatched via ``expect()`` (which maps ``WebDriver`` to
    ``ExpectDriver``); instantiate directly with a driver.
    """

    def __init__(
        self,
        target: WebDriver,
        config: ExpectConfig | None = None,
        message: str | None = None,
        negate: bool = False,
    ) -> None:
        super().__init__(target=target, config=config, message=message, negate=negate)

    # --- JS result ---

    def to_have_js_result(
        self,
        script: str,
        expected: Any,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert driver.execute_script(script) == expected."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            actual = driver.execute_script(script)
            return (actual == expected, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have JS result {expected!r}",
            expected=expected,
            entity="js",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_js_result_contains(
        self,
        script: str,
        expected: Any,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert expected in driver.execute_script(script)."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            actual = driver.execute_script(script)
            if actual is None:
                return (False, actual)
            try:
                return (expected in actual, actual)
            except TypeError:
                return (False, f"not iterable: {actual!r}")

        self._run_assertion(
            condition=condition,
            condition_name=f"to have JS result containing {expected!r}",
            expected=expected,
            entity="js",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_js_result_matches(
        self,
        script: str,
        pattern: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert re.search(pattern, str(driver.execute_script(script)))."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            actual = driver.execute_script(script)
            return (re.search(pattern, str(actual)) is not None, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have JS result matching {pattern!r}",
            expected=pattern,
            entity="js",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_async_js_result(
        self,
        script: str,
        expected: Any,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert driver.execute_async_script(script) == expected."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            actual = driver.execute_async_script(script)
            return (actual == expected, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have async JS result {expected!r}",
            expected=expected,
            entity="js",
            timeout=timeout,
            polling=polling,
        )

        return self

    # --- localStorage ---

    def to_have_local_storage_item(
        self,
        key: str,
        value: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert localStorage.getItem(key) == value via execute_script."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            actual = driver.execute_script("return localStorage.getItem(arguments[0]);", key)
            return (actual == value, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have localStorage item {key!r}={value!r}",
            expected=value,
            entity="js",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_local_storage_item_present(
        self,
        key: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert localStorage.getItem(key) is not None."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            actual = driver.execute_script("return localStorage.getItem(arguments[0]);", key)
            return (actual is not None, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have localStorage item {key!r} present",
            expected="not None",
            entity="js",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_local_storage_item_absent(
        self,
        key: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert localStorage.getItem(key) is None."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            actual = driver.execute_script("return localStorage.getItem(arguments[0]);", key)
            return (actual is None, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have localStorage item {key!r} absent",
            expected="None",
            entity="js",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_local_storage_length(
        self,
        length: int,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert localStorage.length == length."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            actual = driver.execute_script("return localStorage.length;")
            return (actual == length, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have localStorage length {length}",
            expected=length,
            entity="js",
            timeout=timeout,
            polling=polling,
        )

        return self

    # --- sessionStorage ---

    def to_have_session_storage_item(
        self,
        key: str,
        value: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert sessionStorage.getItem(key) == value."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            actual = driver.execute_script("return sessionStorage.getItem(arguments[0]);", key)
            return (actual == value, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have sessionStorage item {key!r}={value!r}",
            expected=value,
            entity="js",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_session_storage_item_present(
        self,
        key: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert sessionStorage.getItem(key) is not None."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            actual = driver.execute_script("return sessionStorage.getItem(arguments[0]);", key)
            return (actual is not None, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have sessionStorage item {key!r} present",
            expected="not None",
            entity="js",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_session_storage_item_absent(
        self,
        key: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert sessionStorage.getItem(key) is None."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            actual = driver.execute_script("return sessionStorage.getItem(arguments[0]);", key)
            return (actual is None, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have sessionStorage item {key!r} absent",
            expected="None",
            entity="js",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_session_storage_length(
        self,
        length: int,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert sessionStorage.length == length."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            actual = driver.execute_script("return sessionStorage.length;")
            return (actual == length, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have sessionStorage length {length}",
            expected=length,
            entity="js",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_js_variable(
        self,
        name: str,
        value: Any,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert driver.execute_script('return window[name]') == value."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            actual = driver.execute_script("return window[arguments[0]];", name)
            return (actual == value, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have JS variable {name!r}={value!r}",
            expected=value,
            entity="js",
            timeout=timeout,
            polling=polling,
        )

        return self

    # --- Overrides ---

    def _entity_description(self) -> str:
        return "JS"

    def _get_element_html(self) -> str | None:
        return None

to_have_async_js_result

to_have_async_js_result(script: str, expected: Any, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert driver.execute_async_script(script) == expected.

Source code in selenium_expect/assertions/js.py
def to_have_async_js_result(
    self,
    script: str,
    expected: Any,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert driver.execute_async_script(script) == expected."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        actual = driver.execute_async_script(script)
        return (actual == expected, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have async JS result {expected!r}",
        expected=expected,
        entity="js",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_js_result

to_have_js_result(script: str, expected: Any, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert driver.execute_script(script) == expected.

Source code in selenium_expect/assertions/js.py
def to_have_js_result(
    self,
    script: str,
    expected: Any,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert driver.execute_script(script) == expected."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        actual = driver.execute_script(script)
        return (actual == expected, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have JS result {expected!r}",
        expected=expected,
        entity="js",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_js_result_contains

to_have_js_result_contains(script: str, expected: Any, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert expected in driver.execute_script(script).

Source code in selenium_expect/assertions/js.py
def to_have_js_result_contains(
    self,
    script: str,
    expected: Any,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert expected in driver.execute_script(script)."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        actual = driver.execute_script(script)
        if actual is None:
            return (False, actual)
        try:
            return (expected in actual, actual)
        except TypeError:
            return (False, f"not iterable: {actual!r}")

    self._run_assertion(
        condition=condition,
        condition_name=f"to have JS result containing {expected!r}",
        expected=expected,
        entity="js",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_js_result_matches

to_have_js_result_matches(script: str, pattern: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert re.search(pattern, str(driver.execute_script(script))).

Source code in selenium_expect/assertions/js.py
def to_have_js_result_matches(
    self,
    script: str,
    pattern: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert re.search(pattern, str(driver.execute_script(script)))."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        actual = driver.execute_script(script)
        return (re.search(pattern, str(actual)) is not None, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have JS result matching {pattern!r}",
        expected=pattern,
        entity="js",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_js_variable

to_have_js_variable(name: str, value: Any, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert driver.execute_script('return window[name]') == value.

Source code in selenium_expect/assertions/js.py
def to_have_js_variable(
    self,
    name: str,
    value: Any,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert driver.execute_script('return window[name]') == value."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        actual = driver.execute_script("return window[arguments[0]];", name)
        return (actual == value, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have JS variable {name!r}={value!r}",
        expected=value,
        entity="js",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_local_storage_item

to_have_local_storage_item(key: str, value: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert localStorage.getItem(key) == value via execute_script.

Source code in selenium_expect/assertions/js.py
def to_have_local_storage_item(
    self,
    key: str,
    value: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert localStorage.getItem(key) == value via execute_script."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        actual = driver.execute_script("return localStorage.getItem(arguments[0]);", key)
        return (actual == value, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have localStorage item {key!r}={value!r}",
        expected=value,
        entity="js",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_local_storage_item_absent

to_have_local_storage_item_absent(key: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert localStorage.getItem(key) is None.

Source code in selenium_expect/assertions/js.py
def to_have_local_storage_item_absent(
    self,
    key: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert localStorage.getItem(key) is None."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        actual = driver.execute_script("return localStorage.getItem(arguments[0]);", key)
        return (actual is None, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have localStorage item {key!r} absent",
        expected="None",
        entity="js",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_local_storage_item_present

to_have_local_storage_item_present(key: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert localStorage.getItem(key) is not None.

Source code in selenium_expect/assertions/js.py
def to_have_local_storage_item_present(
    self,
    key: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert localStorage.getItem(key) is not None."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        actual = driver.execute_script("return localStorage.getItem(arguments[0]);", key)
        return (actual is not None, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have localStorage item {key!r} present",
        expected="not None",
        entity="js",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_local_storage_length

to_have_local_storage_length(length: int, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert localStorage.length == length.

Source code in selenium_expect/assertions/js.py
def to_have_local_storage_length(
    self,
    length: int,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert localStorage.length == length."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        actual = driver.execute_script("return localStorage.length;")
        return (actual == length, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have localStorage length {length}",
        expected=length,
        entity="js",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_session_storage_item

to_have_session_storage_item(key: str, value: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert sessionStorage.getItem(key) == value.

Source code in selenium_expect/assertions/js.py
def to_have_session_storage_item(
    self,
    key: str,
    value: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert sessionStorage.getItem(key) == value."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        actual = driver.execute_script("return sessionStorage.getItem(arguments[0]);", key)
        return (actual == value, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have sessionStorage item {key!r}={value!r}",
        expected=value,
        entity="js",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_session_storage_item_absent

to_have_session_storage_item_absent(key: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert sessionStorage.getItem(key) is None.

Source code in selenium_expect/assertions/js.py
def to_have_session_storage_item_absent(
    self,
    key: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert sessionStorage.getItem(key) is None."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        actual = driver.execute_script("return sessionStorage.getItem(arguments[0]);", key)
        return (actual is None, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have sessionStorage item {key!r} absent",
        expected="None",
        entity="js",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_session_storage_item_present

to_have_session_storage_item_present(key: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert sessionStorage.getItem(key) is not None.

Source code in selenium_expect/assertions/js.py
def to_have_session_storage_item_present(
    self,
    key: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert sessionStorage.getItem(key) is not None."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        actual = driver.execute_script("return sessionStorage.getItem(arguments[0]);", key)
        return (actual is not None, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have sessionStorage item {key!r} present",
        expected="not None",
        entity="js",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_session_storage_length

to_have_session_storage_length(length: int, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert sessionStorage.length == length.

Source code in selenium_expect/assertions/js.py
def to_have_session_storage_length(
    self,
    length: int,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert sessionStorage.length == length."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        actual = driver.execute_script("return sessionStorage.length;")
        return (actual == length, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have sessionStorage length {length}",
        expected=length,
        entity="js",
        timeout=timeout,
        polling=polling,
    )

    return self

ExpectIframe

Assertions for iframes.

Methods: to_have_frame_available, to_have_frame_count, to_have_frame_count_greater_than, to_have_frame_text, to_be_in_frame, to_be_in_default_content

selenium_expect.assertions.iframe.ExpectIframe

Bases: AssertionMixin

Assertions for iframe/frame context.

Inherited by ExpectDriver, so these assertions are available via expect(driver).

Source code in selenium_expect/assertions/iframe.py
class ExpectIframe(AssertionMixin):
    """Assertions for iframe/frame context.

    Inherited by ``ExpectDriver``, so these assertions are available
    via ``expect(driver)``.
    """

    def __init__(
        self,
        target: WebDriver,
        config: ExpectConfig | None = None,
        message: str | None = None,
        negate: bool = False,
    ) -> None:
        super().__init__(target=target, config=config, message=message, negate=negate)

    def to_have_frame_available(
        self,
        frame_id: str | int,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert driver.switch_to.frame(frame_id) doesn't raise."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            try:
                driver.switch_to.frame(frame_id)
                driver.switch_to.parent_frame()
                return (True, "available")
            except NoSuchFrameException:
                return (False, "not available")

        self._run_assertion(
            condition=condition,
            condition_name=f"to have frame {frame_id!r} available",
            expected="available",
            entity="iframe",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_frame_count(
        self,
        count: int,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert len(driver.find_elements(By.TAG_NAME, 'iframe')) == count."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            actual = len(driver.find_elements(By.TAG_NAME, "iframe"))
            return (actual == count, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have frame count {count}",
            expected=count,
            entity="iframe",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_frame_count_greater_than(
        self,
        n: int,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert iframe count > n."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            actual = len(driver.find_elements(By.TAG_NAME, "iframe"))
            return (actual > n, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have frame count > {n}",
            expected=f">{n}",
            entity="iframe",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_frame_text(
        self,
        frame_id: str | int,
        text: str,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Switch to frame, assert driver.page_source contains text, switch back."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            try:
                driver.switch_to.frame(frame_id)
                source = driver.page_source or ""
                return (text in source, source[:200])
            except NoSuchFrameException:
                return (False, "frame not available")
            finally:
                driver.switch_to.parent_frame()

        self._run_assertion(
            condition=condition,
            condition_name=f"to have frame {frame_id!r} text containing {text!r}",
            expected=text,
            entity="iframe",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_be_in_frame(
        self,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert driver is currently inside a frame (not in default content)."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            in_frame = bool(driver.execute_script("return window.frameElement !== null;"))
            return (in_frame, "in frame" if in_frame else "default content")

        self._run_assertion(
            condition=condition,
            condition_name="to be in frame",
            expected="in frame",
            entity="iframe",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_be_in_default_content(
        self,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert driver is in default content (not inside any frame)."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            in_frame = bool(driver.execute_script("return window.frameElement !== null;"))
            return (not in_frame, "in frame" if in_frame else "default content")

        self._run_assertion(
            condition=condition,
            condition_name="to be in default content",
            expected="in default content",
            entity="iframe",
            timeout=timeout,
            polling=polling,
        )

        return self

    # --- Overrides ---

    def _entity_description(self) -> str:
        return "iframe"

    def _get_element_html(self) -> str | None:
        return None

to_be_in_default_content

to_be_in_default_content(*, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert driver is in default content (not inside any frame).

Source code in selenium_expect/assertions/iframe.py
def to_be_in_default_content(
    self,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert driver is in default content (not inside any frame)."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        in_frame = bool(driver.execute_script("return window.frameElement !== null;"))
        return (not in_frame, "in frame" if in_frame else "default content")

    self._run_assertion(
        condition=condition,
        condition_name="to be in default content",
        expected="in default content",
        entity="iframe",
        timeout=timeout,
        polling=polling,
    )

    return self

to_be_in_frame

to_be_in_frame(*, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert driver is currently inside a frame (not in default content).

Source code in selenium_expect/assertions/iframe.py
def to_be_in_frame(
    self,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert driver is currently inside a frame (not in default content)."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        in_frame = bool(driver.execute_script("return window.frameElement !== null;"))
        return (in_frame, "in frame" if in_frame else "default content")

    self._run_assertion(
        condition=condition,
        condition_name="to be in frame",
        expected="in frame",
        entity="iframe",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_frame_available

to_have_frame_available(frame_id: str | int, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert driver.switch_to.frame(frame_id) doesn't raise.

Source code in selenium_expect/assertions/iframe.py
def to_have_frame_available(
    self,
    frame_id: str | int,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert driver.switch_to.frame(frame_id) doesn't raise."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        try:
            driver.switch_to.frame(frame_id)
            driver.switch_to.parent_frame()
            return (True, "available")
        except NoSuchFrameException:
            return (False, "not available")

    self._run_assertion(
        condition=condition,
        condition_name=f"to have frame {frame_id!r} available",
        expected="available",
        entity="iframe",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_frame_count

to_have_frame_count(count: int, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert len(driver.find_elements(By.TAG_NAME, 'iframe')) == count.

Source code in selenium_expect/assertions/iframe.py
def to_have_frame_count(
    self,
    count: int,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert len(driver.find_elements(By.TAG_NAME, 'iframe')) == count."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        actual = len(driver.find_elements(By.TAG_NAME, "iframe"))
        return (actual == count, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have frame count {count}",
        expected=count,
        entity="iframe",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_frame_count_greater_than

to_have_frame_count_greater_than(n: int, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert iframe count > n.

Source code in selenium_expect/assertions/iframe.py
def to_have_frame_count_greater_than(
    self,
    n: int,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert iframe count > n."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        actual = len(driver.find_elements(By.TAG_NAME, "iframe"))
        return (actual > n, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have frame count > {n}",
        expected=f">{n}",
        entity="iframe",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_frame_text

to_have_frame_text(frame_id: str | int, text: str, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Switch to frame, assert driver.page_source contains text, switch back.

Source code in selenium_expect/assertions/iframe.py
def to_have_frame_text(
    self,
    frame_id: str | int,
    text: str,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Switch to frame, assert driver.page_source contains text, switch back."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        try:
            driver.switch_to.frame(frame_id)
            source = driver.page_source or ""
            return (text in source, source[:200])
        except NoSuchFrameException:
            return (False, "frame not available")
        finally:
            driver.switch_to.parent_frame()

    self._run_assertion(
        condition=condition,
        condition_name=f"to have frame {frame_id!r} text containing {text!r}",
        expected=text,
        entity="iframe",
        timeout=timeout,
        polling=polling,
    )

    return self

ExpectWindow

Assertions for browser window position, size, and rect.

Methods: to_have_position, to_have_size, to_have_rect

selenium_expect.assertions.window.ExpectWindow

Bases: AssertionMixin

Assertions for window position, size, and rect (driver-level).

Not dispatched via expect() (which maps WebDriver to ExpectDriver); instantiate directly with a driver.

Source code in selenium_expect/assertions/window.py
class ExpectWindow(AssertionMixin):
    """Assertions for window position, size, and rect (driver-level).

    Not dispatched via ``expect()`` (which maps ``WebDriver`` to
    ``ExpectDriver``); instantiate directly with a driver.
    """

    def __init__(
        self,
        target: WebDriver,
        config: ExpectConfig | None = None,
        message: str | None = None,
        negate: bool = False,
    ) -> None:
        super().__init__(target=target, config=config, message=message, negate=negate)

    def to_have_position(
        self,
        x: int,
        y: int,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert driver.get_window_position() == {'x': x, 'y': y}."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            pos = driver.get_window_position()
            actual = {"x": pos["x"], "y": pos["y"]}
            return (actual == {"x": x, "y": y}, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have window position ({x}, {y})",
            expected={"x": x, "y": y},
            entity="window",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_size(
        self,
        width: int,
        height: int,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert driver.get_window_size() == {'width': width, 'height': height}."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            sz = driver.get_window_size()
            actual = {"width": sz["width"], "height": sz["height"]}
            return (actual == {"width": width, "height": height}, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have window size ({width}x{height})",
            expected={"width": width, "height": height},
            entity="window",
            timeout=timeout,
            polling=polling,
        )

        return self

    def to_have_rect(
        self,
        x: int,
        y: int,
        width: int,
        height: int,
        *,
        timeout: float | None = None,
        polling: float | list[float] | None = None,
    ) -> Self:
        """Assert driver.get_window_rect() matches all four values."""
        driver = self._target

        def condition() -> tuple[bool, Any]:
            rect = driver.get_window_rect()
            actual = {
                "x": rect["x"],
                "y": rect["y"],
                "width": rect["width"],
                "height": rect["height"],
            }
            expected = {"x": x, "y": y, "width": width, "height": height}
            return (actual == expected, actual)

        self._run_assertion(
            condition=condition,
            condition_name=f"to have window rect ({x}, {y}, {width}x{height})",
            expected={"x": x, "y": y, "width": width, "height": height},
            entity="window",
            timeout=timeout,
            polling=polling,
        )

        return self

    # --- Overrides ---

    def _entity_description(self) -> str:
        return "window"

    def _get_element_html(self) -> str | None:
        return None

to_have_position

to_have_position(x: int, y: int, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert driver.get_window_position() == {'x': x, 'y': y}.

Source code in selenium_expect/assertions/window.py
def to_have_position(
    self,
    x: int,
    y: int,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert driver.get_window_position() == {'x': x, 'y': y}."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        pos = driver.get_window_position()
        actual = {"x": pos["x"], "y": pos["y"]}
        return (actual == {"x": x, "y": y}, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have window position ({x}, {y})",
        expected={"x": x, "y": y},
        entity="window",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_rect

to_have_rect(x: int, y: int, width: int, height: int, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert driver.get_window_rect() matches all four values.

Source code in selenium_expect/assertions/window.py
def to_have_rect(
    self,
    x: int,
    y: int,
    width: int,
    height: int,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert driver.get_window_rect() matches all four values."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        rect = driver.get_window_rect()
        actual = {
            "x": rect["x"],
            "y": rect["y"],
            "width": rect["width"],
            "height": rect["height"],
        }
        expected = {"x": x, "y": y, "width": width, "height": height}
        return (actual == expected, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have window rect ({x}, {y}, {width}x{height})",
        expected={"x": x, "y": y, "width": width, "height": height},
        entity="window",
        timeout=timeout,
        polling=polling,
    )

    return self

to_have_size

to_have_size(width: int, height: int, *, timeout: float | None = None, polling: float | list[float] | None = None) -> Self

Assert driver.get_window_size() == {'width': width, 'height': height}.

Source code in selenium_expect/assertions/window.py
def to_have_size(
    self,
    width: int,
    height: int,
    *,
    timeout: float | None = None,
    polling: float | list[float] | None = None,
) -> Self:
    """Assert driver.get_window_size() == {'width': width, 'height': height}."""
    driver = self._target

    def condition() -> tuple[bool, Any]:
        sz = driver.get_window_size()
        actual = {"width": sz["width"], "height": sz["height"]}
        return (actual == {"width": width, "height": height}, actual)

    self._run_assertion(
        condition=condition,
        condition_name=f"to have window size ({width}x{height})",
        expected={"width": width, "height": height},
        entity="window",
        timeout=timeout,
        polling=polling,
    )

    return self

LocatorExpect

Locator-based expect that re-finds the element on each poll. All ExpectElement methods are available via delegation.

from selenium.webdriver.common.by import By
from selenium_expect import expect

# Re-finds element on each poll — avoids StaleElementReferenceException
expect(driver, by=By.ID, value="dynamic-element").to_be_visible(timeout=10)
expect(driver, locator=(By.CSS_SELECTOR, ".btn")).to_have_text("Submit")

selenium_expect._locator.LocatorExpect

Bases: AssertionMixin

Locator-based expect that re-finds the element on each poll.

Delegates all ExpectElement assertion methods via __getattr__. Each assertion method is executed with a fresh element obtained from driver.find_element(by, value) on every poll cycle.

Source code in selenium_expect/_locator.py
class LocatorExpect(AssertionMixin):
    """Locator-based expect that re-finds the element on each poll.

    Delegates all ``ExpectElement`` assertion methods via ``__getattr__``.
    Each assertion method is executed with a fresh element obtained from
    ``driver.find_element(by, value)`` on every poll cycle.
    """

    def __init__(
        self,
        driver: WebDriver,
        by: str,
        value: str,
        config: ExpectConfig | None = None,
        message: str | None = None,
        negate: bool = False,
    ) -> None:
        super().__init__(target=driver, config=config, message=message, negate=negate)
        self._driver = driver
        self._by = by
        self._value = value

    def _find_element(self) -> Any:
        """Find the element fresh. Returns None if not found."""
        try:
            return self._driver.find_element(self._by, self._value)
        except NoSuchElementException:
            return None

    @property
    def not_(self) -> LocatorExpect:
        """Return a negated copy."""
        return LocatorExpect(
            driver=self._driver,
            by=self._by,
            value=self._value,
            config=self._config,
            message=self._message,
            negate=not self._negate,
        )

    def to_satisfy_all(self, *conditions: Callable[[Any], None]) -> Self:
        """Assert all conditions pass on the re-found element (AND)."""
        from selenium_expect._compose import satisfy_all

        def condition() -> tuple[bool, Any]:
            el = self._find_element()
            if el is None:
                return (False, "element not found")
            try:
                satisfy_all(el, *conditions, message=self._message)
                return (True, "all pass")
            except AssertionError as exc:
                return (False, str(exc))

        self._run_assertion(
            condition=condition,
            condition_name="to_satisfy_all",
            expected="all pass",
            entity=self._entity_description(),
        )
        return self

    def to_satisfy_any(self, *conditions: Callable[[Any], None]) -> Self:
        """Assert at least one condition passes on the re-found element (OR)."""
        from selenium_expect._compose import satisfy_any

        def condition() -> tuple[bool, Any]:
            el = self._find_element()
            if el is None:
                return (False, "element not found")
            try:
                satisfy_any(el, *conditions, message=self._message)
                return (True, "at least one pass")
            except AssertionError as exc:
                return (False, str(exc))

        self._run_assertion(
            condition=condition,
            condition_name="to_satisfy_any",
            expected="at least one pass",
            entity=self._entity_description(),
        )
        return self

    def to_satisfy_none(self, *conditions: Callable[[Any], None]) -> Self:
        """Assert no condition passes on the re-found element (NOT)."""
        from selenium_expect._compose import satisfy_none

        def condition() -> tuple[bool, Any]:
            el = self._find_element()
            if el is None:
                return (False, "element not found")
            try:
                satisfy_none(el, *conditions, message=self._message)
                return (True, "none pass")
            except AssertionError as exc:
                return (False, str(exc))

        self._run_assertion(
            condition=condition,
            condition_name="to_satisfy_none",
            expected="none pass",
            entity=self._entity_description(),
        )
        return self

    def _entity_description(self) -> str:
        return f"locator({self._by}={self._value!r})"

    def _get_element_html(self) -> str | None:
        el = self._find_element()
        if el is None:
            return None
        try:
            html: str | None = el.get_attribute("outerHTML")
            return html
        except StaleElementReferenceException:
            return None

    def __getattr__(self, name: str) -> Any:
        """Delegate to ExpectElement methods or custom matchers with re-find on each poll.

        For each assertion method call, we wrap the condition so that
        ``find_element`` is called fresh on every retry poll.
        """
        # Avoid recursion for private/dunder attributes
        if name.startswith("_"):
            raise AttributeError(f"{type(self).__name__!r} object has no attribute {name!r}")

        from selenium_expect._matcher import CustomMatcherRegistry
        from selenium_expect.assertions.element import ExpectElement

        # Check for custom matcher first
        matcher_fn = CustomMatcherRegistry.get(name)

        # Get the actual method from ExpectElement
        element_method = getattr(ExpectElement, name, None)

        if matcher_fn is None and (element_method is None or not callable(element_method)):
            raise AttributeError(f"{type(self).__name__!r} object has no attribute {name!r}")

        if matcher_fn is not None:

            def _invoke_matcher(*args: Any, **kwargs: Any) -> LocatorExpect:
                timeout = kwargs.pop("timeout", None)
                polling = kwargs.pop("polling", None)

                def condition() -> tuple[bool, Any]:
                    try:
                        el = self._driver.find_element(self._by, self._value)
                    except NoSuchElementException:
                        return (False, "element not found")
                    try:
                        return matcher_fn(el, *args, **kwargs)
                    except StaleElementReferenceException:
                        return (False, "stale element")

                self._run_assertion(
                    condition=condition,
                    condition_name=name.replace("_", " "),
                    expected=None,
                    entity=self._entity_description(),
                    timeout=timeout,
                    polling=polling,
                )

                return self

            return _invoke_matcher

        def _invoke(*args: Any, **kwargs: Any) -> LocatorExpect:
            timeout = kwargs.pop("timeout", None)
            polling = kwargs.pop("polling", None)

            def condition() -> tuple[bool, Any]:
                try:
                    el = self._driver.find_element(self._by, self._value)
                except NoSuchElementException:
                    return (False, "element not found")
                inner_config = self._config.replace(soft_mode=False, screenshot_on_failure=False)
                temp = ExpectElement(
                    target=el,
                    config=inner_config,
                    message=self._message,
                    negate=False,
                )
                method = getattr(temp, name)
                try:
                    method(*args, timeout=0.001, **kwargs)
                    return (True, "passed")
                except AssertionError as exc:
                    first_line = str(exc).splitlines()[0] if str(exc) else "failed"
                    return (False, first_line)
                except StaleElementReferenceException:
                    return (False, "stale element")

            self._run_assertion(
                condition=condition,
                condition_name=name.replace("_", " "),
                expected=None,
                entity=self._entity_description(),
                timeout=timeout,
                polling=polling,
            )

            return self

        return _invoke

not_ property

not_: LocatorExpect

Return a negated copy.

__getattr__

__getattr__(name: str) -> Any

Delegate to ExpectElement methods or custom matchers with re-find on each poll.

For each assertion method call, we wrap the condition so that find_element is called fresh on every retry poll.

Source code in selenium_expect/_locator.py
def __getattr__(self, name: str) -> Any:
    """Delegate to ExpectElement methods or custom matchers with re-find on each poll.

    For each assertion method call, we wrap the condition so that
    ``find_element`` is called fresh on every retry poll.
    """
    # Avoid recursion for private/dunder attributes
    if name.startswith("_"):
        raise AttributeError(f"{type(self).__name__!r} object has no attribute {name!r}")

    from selenium_expect._matcher import CustomMatcherRegistry
    from selenium_expect.assertions.element import ExpectElement

    # Check for custom matcher first
    matcher_fn = CustomMatcherRegistry.get(name)

    # Get the actual method from ExpectElement
    element_method = getattr(ExpectElement, name, None)

    if matcher_fn is None and (element_method is None or not callable(element_method)):
        raise AttributeError(f"{type(self).__name__!r} object has no attribute {name!r}")

    if matcher_fn is not None:

        def _invoke_matcher(*args: Any, **kwargs: Any) -> LocatorExpect:
            timeout = kwargs.pop("timeout", None)
            polling = kwargs.pop("polling", None)

            def condition() -> tuple[bool, Any]:
                try:
                    el = self._driver.find_element(self._by, self._value)
                except NoSuchElementException:
                    return (False, "element not found")
                try:
                    return matcher_fn(el, *args, **kwargs)
                except StaleElementReferenceException:
                    return (False, "stale element")

            self._run_assertion(
                condition=condition,
                condition_name=name.replace("_", " "),
                expected=None,
                entity=self._entity_description(),
                timeout=timeout,
                polling=polling,
            )

            return self

        return _invoke_matcher

    def _invoke(*args: Any, **kwargs: Any) -> LocatorExpect:
        timeout = kwargs.pop("timeout", None)
        polling = kwargs.pop("polling", None)

        def condition() -> tuple[bool, Any]:
            try:
                el = self._driver.find_element(self._by, self._value)
            except NoSuchElementException:
                return (False, "element not found")
            inner_config = self._config.replace(soft_mode=False, screenshot_on_failure=False)
            temp = ExpectElement(
                target=el,
                config=inner_config,
                message=self._message,
                negate=False,
            )
            method = getattr(temp, name)
            try:
                method(*args, timeout=0.001, **kwargs)
                return (True, "passed")
            except AssertionError as exc:
                first_line = str(exc).splitlines()[0] if str(exc) else "failed"
                return (False, first_line)
            except StaleElementReferenceException:
                return (False, "stale element")

        self._run_assertion(
            condition=condition,
            condition_name=name.replace("_", " "),
            expected=None,
            entity=self._entity_description(),
            timeout=timeout,
            polling=polling,
        )

        return self

    return _invoke

to_satisfy_all

to_satisfy_all(*conditions: Callable[[Any], None]) -> Self

Assert all conditions pass on the re-found element (AND).

Source code in selenium_expect/_locator.py
def to_satisfy_all(self, *conditions: Callable[[Any], None]) -> Self:
    """Assert all conditions pass on the re-found element (AND)."""
    from selenium_expect._compose import satisfy_all

    def condition() -> tuple[bool, Any]:
        el = self._find_element()
        if el is None:
            return (False, "element not found")
        try:
            satisfy_all(el, *conditions, message=self._message)
            return (True, "all pass")
        except AssertionError as exc:
            return (False, str(exc))

    self._run_assertion(
        condition=condition,
        condition_name="to_satisfy_all",
        expected="all pass",
        entity=self._entity_description(),
    )
    return self

to_satisfy_any

to_satisfy_any(*conditions: Callable[[Any], None]) -> Self

Assert at least one condition passes on the re-found element (OR).

Source code in selenium_expect/_locator.py
def to_satisfy_any(self, *conditions: Callable[[Any], None]) -> Self:
    """Assert at least one condition passes on the re-found element (OR)."""
    from selenium_expect._compose import satisfy_any

    def condition() -> tuple[bool, Any]:
        el = self._find_element()
        if el is None:
            return (False, "element not found")
        try:
            satisfy_any(el, *conditions, message=self._message)
            return (True, "at least one pass")
        except AssertionError as exc:
            return (False, str(exc))

    self._run_assertion(
        condition=condition,
        condition_name="to_satisfy_any",
        expected="at least one pass",
        entity=self._entity_description(),
    )
    return self

to_satisfy_none

to_satisfy_none(*conditions: Callable[[Any], None]) -> Self

Assert no condition passes on the re-found element (NOT).

Source code in selenium_expect/_locator.py
def to_satisfy_none(self, *conditions: Callable[[Any], None]) -> Self:
    """Assert no condition passes on the re-found element (NOT)."""
    from selenium_expect._compose import satisfy_none

    def condition() -> tuple[bool, Any]:
        el = self._find_element()
        if el is None:
            return (False, "element not found")
        try:
            satisfy_none(el, *conditions, message=self._message)
            return (True, "none pass")
        except AssertionError as exc:
            return (False, str(exc))

    self._run_assertion(
        condition=condition,
        condition_name="to_satisfy_none",
        expected="none pass",
        entity=self._entity_description(),
    )
    return self