tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

fixtures_http.py (8252B)


      1 import base64
      2 
      3 import pytest
      4 from webdriver.error import NoSuchAlertException, NoSuchWindowException
      5 
      6 from tests.support.image import png_dimensions, ImageDifference
      7 from tests.support.sync import Poll
      8 
      9 
     10 @pytest.fixture
     11 def add_event_listeners():
     12    """Register listeners for tracked events on element."""
     13    def add_event_listeners(element, tracked_events):
     14        element.session.execute_script("""
     15            const element = arguments[0];
     16            const trackedEvents = arguments[1];
     17 
     18            if (!("events" in window)) {
     19              window.events = [];
     20            }
     21 
     22            for (let i = 0; i < trackedEvents.length; i++) {
     23              element.addEventListener(trackedEvents[i], function (event) {
     24                window.events.push(event.type);
     25              });
     26            }
     27            """, args=(element, tracked_events))
     28    return add_event_listeners
     29 
     30 
     31 @pytest.fixture
     32 def closed_frame(session, url):
     33    """Create a frame and remove it after switching to it.
     34 
     35    The removed frame will be kept selected, which allows to test for invalid
     36    browsing context references.
     37    """
     38    original_handle = session.window_handle
     39    new_handle = session.new_window()
     40 
     41    session.window_handle = new_handle
     42 
     43    session.url = url("/webdriver/tests/support/html/frames.html")
     44 
     45    subframe = session.find.css("#sub-frame", all=False)
     46    session.switch_to_frame(subframe)
     47 
     48    deleteframe = session.find.css("#delete-frame", all=False)
     49    session.switch_to_frame(deleteframe)
     50 
     51    button = session.find.css("#remove-parent", all=False)
     52    button.click()
     53 
     54    yield
     55 
     56    session.window.close()
     57    assert new_handle not in session.handles, "Unable to close window {}".format(new_handle)
     58 
     59    session.window_handle = original_handle
     60 
     61 
     62 @pytest.fixture
     63 def closed_window(session, inline):
     64    """Create a window and close it immediately.
     65 
     66    The window handle will be kept selected, which allows to test for invalid
     67    top-level browsing context references.
     68    """
     69    original_handle = session.window_handle
     70    new_handle = session.new_window()
     71 
     72    session.window_handle = new_handle
     73    session.url = inline("<input id='a' value='b'>")
     74    element = session.find.css("input", all=False)
     75 
     76    session.window.close()
     77    assert new_handle not in session.handles, "Unable to close window {}".format(new_handle)
     78 
     79    yield (original_handle, element)
     80 
     81    session.window_handle = original_handle
     82 
     83 
     84 @pytest.fixture
     85 def create_cookie(session, url):
     86    """Create a cookie."""
     87    def create_cookie(name, value, **kwargs):
     88        if kwargs.get("path", None) is not None:
     89            session.url = url(kwargs["path"])
     90 
     91        session.set_cookie(name, value, **kwargs)
     92        return session.cookies(name)
     93 
     94    return create_cookie
     95 
     96 
     97 @pytest.fixture
     98 def create_dialog(session):
     99    """Create a dialog (one of "alert", "prompt", or "confirm").
    100 
    101    Also it provides a function to validate that the dialog has been "handled"
    102    (either accepted or dismissed) by returning some value.
    103    """
    104    def create_dialog(dialog_type, text=None):
    105        assert dialog_type in ("alert", "confirm", "prompt"), (
    106            "Invalid dialog type: '%s'" % dialog_type)
    107 
    108        if text is None:
    109            text = ""
    110 
    111        assert isinstance(text, str), "`text` parameter must be a string"
    112 
    113        # Script completes itself when the user prompt has been opened.
    114        # For prompt() dialogs, add a value for the 'default' argument,
    115        # as some user agents (IE, for example) do not produce consistent
    116        # values for the default.
    117        session.execute_async_script("""
    118            let dialog_type = arguments[0];
    119            let text = arguments[1];
    120 
    121            setTimeout(function() {
    122              if (dialog_type == 'prompt') {
    123                window.dialog_return_value = window[dialog_type](text, '');
    124              } else {
    125                window.dialog_return_value = window[dialog_type](text);
    126              }
    127            }, 0);
    128            """, args=(dialog_type, text))
    129 
    130        def check_alert_text(s):
    131            assert s.alert.text == text, f"No user prompt with text '{text}' detected"
    132 
    133        wait = Poll(session, timeout=15,
    134                    ignored_exceptions=NoSuchAlertException)
    135        wait.until(check_alert_text)
    136 
    137    return create_dialog
    138 
    139 
    140 @pytest.fixture
    141 def create_frame(session):
    142    """Create an `iframe` element.
    143 
    144    The element will be inserted into the document of the current browsing
    145    context. Return a reference to the newly-created element.
    146    """
    147    def create_frame():
    148        append = """
    149            var frame = document.createElement('iframe');
    150            document.body.appendChild(frame);
    151            return frame;
    152        """
    153        return session.execute_script(append)
    154 
    155    return create_frame
    156 
    157 
    158 @pytest.fixture
    159 def http_new_tab(session):
    160    """Create a new tab to run the test isolated."""
    161    original_handle = session.window_handle
    162    new_handle = session.new_window(type_hint="tab")
    163 
    164    session.window_handle = new_handle
    165 
    166    yield
    167 
    168    try:
    169        # Make sure to close the correct tab that we opened before.
    170        session.window_handle = new_handle
    171        session.window.close()
    172    except NoSuchWindowException:
    173        pass
    174 
    175    session.window_handle = original_handle
    176 
    177 
    178 @pytest.fixture
    179 def stale_element(current_session, get_test_page):
    180    """Create a stale element reference
    181 
    182    The document will be loaded in the top-level or child browsing context.
    183    Before the requested element or its shadow root is returned the element
    184    is removed from the document's DOM.
    185    """
    186    def stale_element(css_value, as_frame=False, want_shadow_root=False):
    187        current_session.url = get_test_page(as_frame=as_frame)
    188 
    189        if as_frame:
    190            frame = current_session.find.css("iframe", all=False)
    191            current_session.switch_to_frame(frame)
    192 
    193        element = current_session.find.css(css_value, all=False)
    194        shadow_root = element.shadow_root if want_shadow_root else None
    195 
    196        current_session.execute_script("arguments[0].remove();", args=[element])
    197 
    198        return shadow_root if want_shadow_root else element
    199 
    200    return stale_element
    201 
    202 
    203 @pytest.fixture
    204 def load_pdf_http(current_session, test_page_with_pdf_js):
    205    """Load a PDF document in the browser using pdf.js"""
    206    def load_pdf_http(encoded_pdf_data):
    207        current_session.url = test_page_with_pdf_js(encoded_pdf_data)
    208 
    209    return load_pdf_http
    210 
    211 
    212 @pytest.fixture
    213 def render_pdf_to_png_http(current_session, url):
    214    """Render a PDF document to png"""
    215 
    216    def render_pdf_to_png_http(
    217        encoded_pdf_data, page=1
    218    ):
    219        current_session.url = url(path="/print_pdf_runner.html")
    220        result = current_session.execute_async_script(f"""arguments[0](window.render("{encoded_pdf_data}"))""")
    221        index = page - 1
    222 
    223        assert 0 <= index < len(result)
    224 
    225        image_string = result[index]
    226        image_string_without_data_type = image_string[image_string.find(",") + 1:]
    227 
    228        return base64.b64decode(image_string_without_data_type)
    229 
    230    return render_pdf_to_png_http
    231 
    232 
    233 @pytest.fixture
    234 def compare_png_http(current_session, url):
    235    def compare_png_http(img1, img2):
    236        """Calculate difference statistics between two PNG images.
    237 
    238        :param img1: Bytes of first PNG image
    239        :param img2: Bytes of second PNG image
    240        :returns: ImageDifference representing the total number of different pixels,
    241                and maximum per-channel difference between the images.
    242        """
    243        if img1 == img2:
    244            return ImageDifference(0, 0)
    245 
    246        width, height = png_dimensions(img1)
    247        assert (width, height) == png_dimensions(img2)
    248 
    249        current_session.url = url("/webdriver/tests/support/html/render.html")
    250        result = current_session.execute_async_script(
    251            "const callback = arguments[arguments.length - 1]; callback(compare(arguments[0], arguments[1], arguments[2], arguments[3]))",
    252            args=[base64.encodebytes(img1).decode(), base64.encodebytes(img2).decode(), width, height],
    253        )
    254 
    255        assert "maxDifference" in result
    256        assert "totalPixels" in result
    257 
    258        return ImageDifference(result["totalPixels"], result["maxDifference"])
    259 
    260    return compare_png_http