def ensure_element(self, locator: str, selector: str, state: str | None = "present", timeout: float | None = None) -> WebElement | None:
        """
        Wait until an element appears or disappears in the browser.

        The webdriver runs in parallel with our scripts, so we must wait for it everytime it
        runs javascript. Selenium automatically waits till a page loads when GETing it,
        but it doesn't do this when it runs javascript and makes AJAX requests.
        So we must explicitly wait in that case.

        The 'locator' argument defines what strategy we use to search for the element.
        It expects standard names from the By class in selenium.webdriver.common.by.
        https://www.selenium.dev/selenium/docs/api/py/webdriver/selenium.webdriver.common.by.html

        The 'state' argument allows us to chose between waiting for the element to be visible,
        clickable, present, or invisible. Presence is more inclusive, but sometimes we want to
        know if the element is visible. Careful, its not always intuitive what Selenium considers
        to be a visible element. We can also wait for it to be clickable, although this method
        is a bit buggy in selenium, an element can be 'clickable' according to selenium and
        still fail when we try to click it.

        More info at: http://selenium-python.readthedocs.io/waits.html
        """
        locators_compatibility = {
            "link_text": By.LINK_TEXT,
            "partial_link_text": By.PARTIAL_LINK_TEXT,
            "tag_name": By.TAG_NAME,
            "class_name": By.CLASS_NAME,
            "css_selector": By.CSS_SELECTOR,
        }
        if locator in locators_compatibility:
            warnings.warn(
                """
                Support for locator strategy names with underscores is deprecated.
                Use strategies from Selenium's By class (importable from selenium.webdriver.common.by).
                """,
                DeprecationWarning,
                stacklevel=2,
            )
            locator = locators_compatibility[locator]

        if not timeout:
            timeout = self.default_timeout or DEFAULT_TIMEOUT

        if state == "visible":
            element = WebDriverWait(self, timeout).until(expected_conditions.visibility_of_element_located((locator, selector)))
        elif state == "clickable":
            element = WebDriverWait(self, timeout).until(expected_conditions.element_to_be_clickable((locator, selector)))
        elif state == "present":
            element = WebDriverWait(self, timeout).until(expected_conditions.presence_of_element_located((locator, selector)))
        elif state == "invisible":
            WebDriverWait(self, timeout).until(expected_conditions.invisibility_of_element_located((locator, selector)))
            element = None
        else:
            msg = f"The 'state' argument must be 'visible', 'clickable', 'present' or 'invisible', not '{state}'"
            raise ValueError(msg)

        # We add this method to our element to provide a more robust click. Chromedriver
        # sometimes needs some time before it can click an item, specially if it needs to
        # scroll into it first. This method ensures clicks don't fail because of this.
        if element:
            element.ensure_click = functools.partial(_ensure_click, element)  # type: ignore[attr-defined]
        return element

        Wait until an element appears or disappears in the browser.

        The webdriver runs in parallel with our scripts, so we must wait for it everytime it
        runs javascript. Selenium automatically waits till a page loads when GETing it,
        but it doesn't do this when it runs javascript and makes AJAX requests.
        So we must explicitly wait in that case.

        The 'locator' argument defines what strategy we use to search for the element.
        It expects standard names from the By class in selenium.webdriver.common.by.
        https://www.selenium.dev/selenium/docs/api/py/webdriver/selenium.webdriver.common.by.html

        The 'state' argument allows us to chose between waiting for the element to be visible,
        clickable, present, or invisible. Presence is more inclusive, but sometimes we want to
        know if the element is visible. Careful, its not always intuitive what Selenium considers
        to be a visible element. We can also wait for it to be clickable, although this method
        is a bit buggy in selenium, an element can be 'clickable' according to selenium and
        still fail when we try to click it.

        More info at: http://selenium-python.readthedocs.io/waits.html
        
requestium/requestium_mixin.py