⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 289467 in webkit


Ignore:
Timestamp:
Feb 9, 2022, 5:49:12 AM (5 years ago)
Author:
Carlos Garcia Campos
Message:

WebDriver: add a javascript atom to get the visible text
​https://bugs.webkit.org/show_bug.cgi?id=174617
<rdar://problem/32307461>

Reviewed by Adrian Perez de Castro.

Source/WebDriver:

Generate the JavaScript atoms using the new command and use the new atom to get element text.

  • CMakeLists.txt:
  • Session.cpp:

(WebDriver::Session::getElementText):

Source/WebKit:

Add a new JavaScript atom to get the visible text according to the spec. The new atom uses code from other atoms
like ElementDisplayed and it's also used now by FindNodes one. The atoms are now autogenerated using a script to
include the duplicated code from a common source utils.js.

  • Scripts/generate-automation-atom.py: Added.

(collect_utils):
(parse_utils):
(append_functions):
(main):

  • UIProcess/Automation/atoms/ElementDisplayed.js:

(isShown.nodeIsElement): Deleted.
(isShown.parentElementForElement): Deleted.
(isShown.enclosingNodeOrSelfMatchingPredicate): Deleted.
(isShown.enclosingElementOrSelfMatchingPredicate): Deleted.
(isShown.cascadedStylePropertyForElement): Deleted.
(isShown.elementSubtreeHasNonZeroDimensions): Deleted.
(isShown): Deleted.
(isShown.isElementSubtreeHiddenByOverflow): Deleted.

  • UIProcess/Automation/atoms/ElementText.js: Added.
  • UIProcess/Automation/atoms/FindNodes.js:

(tryToFindNode):

  • UIProcess/Automation/atoms/utils.js: Added.

(utils.nodeIsElement):
(utils.enclosingNodeOrSelfMatchingPredicate):
(utils.parentElementForElement):
(utils.cascadedStylePropertyForElement):
(elementSubtreeHasNonZeroDimensions):
(isElementSubtreeHiddenByOverflow):
(utils.isShown):
(appendLines.currentLine):
(appendLines):
(utils.getText):

WebDriverTests:

Remove expectations of tests that are now passing.

Location:
trunk
Files:
3 added
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebDriver/CMakeLists.txt

    r275065 r289467  
    2727
    2828set(WebDriver_SCRIPTS
    29     ${WEBKIT_DIR}/UIProcess/Automation/atoms/ElementAttribute.js
    30     ${WEBKIT_DIR}/UIProcess/Automation/atoms/ElementDisplayed.js
    31     ${WEBKIT_DIR}/UIProcess/Automation/atoms/ElementEnabled.js
    32     ${WEBKIT_DIR}/UIProcess/Automation/atoms/EnterFullscreen.js
    33     ${WEBKIT_DIR}/UIProcess/Automation/atoms/FindNodes.js
    34     ${WEBKIT_DIR}/UIProcess/Automation/atoms/FormElementClear.js
    35     ${WEBKIT_DIR}/UIProcess/Automation/atoms/FormSubmit.js
     29    ${WebDriver_DERIVED_SOURCES_DIR}/ElementAttribute.js
     30    ${WebDriver_DERIVED_SOURCES_DIR}/ElementDisplayed.js
     31    ${WebDriver_DERIVED_SOURCES_DIR}/ElementEnabled.js
     32    ${WebDriver_DERIVED_SOURCES_DIR}/ElementText.js
     33    ${WebDriver_DERIVED_SOURCES_DIR}/EnterFullscreen.js
     34    ${WebDriver_DERIVED_SOURCES_DIR}/FindNodes.js
     35    ${WebDriver_DERIVED_SOURCES_DIR}/FormElementClear.js
     36    ${WebDriver_DERIVED_SOURCES_DIR}/FormSubmit.js
    3637)
     38
     39macro(GENERATE_ATOMS _inputs)
     40    foreach (_file IN ITEMS ${_inputs})
     41        get_filename_component(_name ${_file} NAME)
     42        add_custom_command(
     43            OUTPUT ${_file}
     44            MAIN_DEPENDENCY ${WEBKIT_DIR}/Scripts/generate-automation-atom.py
     45            DEPENDS
     46                ${WEBKIT_DIR}/UIProcess/Automation/atoms/${_name}
     47                ${WEBKIT_DIR}/UIProcess/Automation/atoms/utils.js
     48            COMMAND ${PYTHON_EXECUTABLE} ${WEBKIT_DIR}/Scripts/generate-automation-atom.py ${WEBKIT_DIR}/UIProcess/Automation/atoms/${_name} ${_file}
     49            VERBATIM
     50        )
     51    endforeach ()
     52endmacro()
     53
     54GENERATE_ATOMS("${WebDriver_SCRIPTS}")
    3755
    3856MAKE_JS_FILE_ARRAYS(
  • trunk/Source/WebDriver/ChangeLog

    r289202 r289467  
     12022-02-09  Carlos Garcia Campos  <cgarcia@igalia.com>
     2
     3        WebDriver: add a javascript atom to get the visible text
     4        https://bugs.webkit.org/show_bug.cgi?id=174617
     5        <rdar://problem/32307461>
     6
     7        Reviewed by Adrian Perez de Castro.
     8
     9        Generate the JavaScript atoms using the new command and use the new atom to get element text.
     10
     11        * CMakeLists.txt:
     12        * Session.cpp:
     13        (WebDriver::Session::getElementText):
     14
    1152022-02-07  Carlos Garcia Campos  <cgarcia@igalia.com>
    216
  • trunk/Source/WebDriver/Session.cpp

    r289202 r289467  
    13591359            parameters->setString("frameHandle"_s, m_currentBrowsingContext.value());
    13601360        // FIXME: Add an atom to properly implement this instead of just using innerText.
    1361         parameters->setString("function"_s, "function(element) { return element.innerText.replace(/^[^\\S\\xa0]+|[^\\S\\xa0]+$/g, '') }"_s);
     1361        parameters->setString("function"_s, StringImpl::createWithoutCopying(ElementTextJavaScript, sizeof(ElementTextJavaScript)));
    13621362        parameters->setArray("arguments"_s, WTFMove(arguments));
    13631363        m_host->sendCommandToBackend("evaluateJavaScriptFunction"_s, WTFMove(parameters), [protectedThis, completionHandler = WTFMove(completionHandler)](SessionHost::CommandResponse&& response) {
  • trunk/Source/WebKit/ChangeLog

    r289463 r289467  
     12022-02-09  Carlos Garcia Campos  <cgarcia@igalia.com>
     2
     3        WebDriver: add a javascript atom to get the visible text
     4        https://bugs.webkit.org/show_bug.cgi?id=174617
     5        <rdar://problem/32307461>
     6
     7        Reviewed by Adrian Perez de Castro.
     8
     9        Add a new JavaScript atom to get the visible text according to the spec. The new atom uses code from other atoms
     10        like ElementDisplayed and it's also used now by FindNodes one. The atoms are now autogenerated using a script to
     11        include the duplicated code from a common source utils.js.
     12
     13        * Scripts/generate-automation-atom.py: Added.
     14        (collect_utils):
     15        (parse_utils):
     16        (append_functions):
     17        (main):
     18        * UIProcess/Automation/atoms/ElementDisplayed.js:
     19        (isShown.nodeIsElement): Deleted.
     20        (isShown.parentElementForElement): Deleted.
     21        (isShown.enclosingNodeOrSelfMatchingPredicate): Deleted.
     22        (isShown.enclosingElementOrSelfMatchingPredicate): Deleted.
     23        (isShown.cascadedStylePropertyForElement): Deleted.
     24        (isShown.elementSubtreeHasNonZeroDimensions): Deleted.
     25        (isShown): Deleted.
     26        (isShown.isElementSubtreeHiddenByOverflow): Deleted.
     27        * UIProcess/Automation/atoms/ElementText.js: Added.
     28        * UIProcess/Automation/atoms/FindNodes.js:
     29        (tryToFindNode):
     30        * UIProcess/Automation/atoms/utils.js: Added.
     31        (utils.nodeIsElement):
     32        (utils.enclosingNodeOrSelfMatchingPredicate):
     33        (utils.parentElementForElement):
     34        (utils.cascadedStylePropertyForElement):
     35        (elementSubtreeHasNonZeroDimensions):
     36        (isElementSubtreeHiddenByOverflow):
     37        (utils.isShown):
     38        (appendLines.currentLine):
     39        (appendLines):
     40        (utils.getText):
     41
    1422022-02-09  Tim Horton  <timothy_horton@apple.com>
    243
  • trunk/Source/WebKit/UIProcess/Automation/atoms/ElementDisplayed.js

    r267978 r289467  
    2424 */
    2525
    26 function isShown(element) {
     26function(element) {
    2727    "use strict";
    2828
    29     function nodeIsElement(node) {
    30         return !!node && node.nodeType === Node.ELEMENT_NODE;
    31        
    32     }
    33 
    34     function parentElementForElement(element) {
    35         if (!element)
    36             return null;
    37 
    38         return enclosingNodeOrSelfMatchingPredicate(element.parentNode, nodeIsElement);
    39     }
    40 
    41     function enclosingNodeOrSelfMatchingPredicate(targetNode, predicate) {
    42         for (let node = targetNode; node && node !== targetNode.getRootNode(); node = node.parentNode)
    43             if (predicate(node))
    44                 return node;
    45 
    46         return null;
    47     }
    48 
    49     function enclosingElementOrSelfMatchingPredicate(targetElement, predicate) {
    50         for (let element = targetElement; element && element !== targetElement.getRootNode(); element = parentElementForElement(element))
    51             if (predicate(element))
    52                 return element;
    53 
    54         return null;
    55     }
    56 
    57     function cascadedStylePropertyForElement(element, property) {
    58         if (!element || !property)
    59             return null;
    60 
    61         let computedStyle = window.getComputedStyle(element);
    62         let computedStyleProperty = computedStyle.getPropertyValue(property);
    63         if (computedStyleProperty && computedStyleProperty !== "inherit")
    64             return computedStyleProperty;
    65 
    66         // Ideally getPropertyValue would return the 'used' or 'actual' value, but
    67         // it doesn't for legacy reasons. So we need to do our own poor man's cascade.
    68         // Fall back to the first non-'inherit' value found in an ancestor.
    69         // In any case, getPropertyValue will not return 'initial'.
    70 
    71         // FIXME: will this incorrectly inherit non-inheritable CSS properties?
    72         // I think all important non-inheritable properties (width, height, etc.)
    73         // for our purposes here are specially resolved, so this may not be an issue.
    74         // Specification is here: https://drafts.csswg.org/cssom/#resolved-values
    75         let parentElement = parentElementForElement(element);
    76         return cascadedStylePropertyForElement(parentElement, property);
    77     }
    78 
    79     function elementSubtreeHasNonZeroDimensions(element) {
    80         let boundingBox = element.getBoundingClientRect();
    81         if (boundingBox.width > 0 && boundingBox.height > 0)
    82             return true;
    83 
    84         // Paths can have a zero width or height. Treat them as shown if the stroke width is positive.
    85         if (element.tagName.toUpperCase() === "PATH" && boundingBox.width + boundingBox.height > 0) {
    86             let strokeWidth = cascadedStylePropertyForElement(element, "stroke-width");
    87             return !!strokeWidth && (parseInt(strokeWidth, 10) > 0);
    88         }
    89 
    90         let cascadedOverflow = cascadedStylePropertyForElement(element, "overflow");
    91         if (cascadedOverflow === "hidden")
    92             return false;
    93 
    94         // If the container's overflow is not hidden and it has zero size, consider the
    95         // container to have non-zero dimensions if a child node has non-zero dimensions.
    96         return Array.from(element.childNodes).some((childNode) => {
    97             if (childNode.nodeType === Node.TEXT_NODE)
    98                 return true;
    99 
    100             if (nodeIsElement(childNode))
    101                 return elementSubtreeHasNonZeroDimensions(childNode);
    102 
    103             return false;
    104         });
    105     }
    106 
    107     function elementOverflowsContainer(element) {
    108         let cascadedOverflow = cascadedStylePropertyForElement(element, "overflow");
    109         if (cascadedOverflow !== "hidden")
    110             return false;
    111 
    112         // FIXME: this needs to take into account the scroll position of the element,
    113         // the display modes of it and its ancestors, and the container it overflows.
    114         // See Selenium's bot.dom.getOverflowState atom for an exhaustive list of edge cases.
    115         return true;
    116     }
    117 
    118     function isElementSubtreeHiddenByOverflow(element) {
    119         if (!element)
    120             return false;
    121 
    122         if (!elementOverflowsContainer(element))
    123             return false;
    124 
    125         if (!element.childNodes.length)
    126             return false;
    127 
    128         // This element's subtree is hidden by overflow if all child subtrees are as well.
    129         return Array.from(element.childNodes).every((childNode) => {
    130             // Returns true if the child node is overflowed or otherwise hidden.
    131             // Base case: not an element, has zero size, scrolled out, or doesn't overflow container.
    132             if (!nodeIsElement(childNode))
    133                 return true;
    134 
    135             if (!elementSubtreeHasNonZeroDimensions(childNode))
    136                 return true;
    137 
    138             // Recurse.
    139             return isElementSubtreeHiddenByOverflow(childNode);
    140         });
    141     }
    142 
    143     // This is a partial reimplementation of Selenium's "element is displayed" algorithm.
    144     // When the W3C specification's algorithm stabilizes, we should implement that.
    145 
    146     if (!(element instanceof Element))
    147         throw new Error("Cannot check the displayedness of a non-Element argument.");
    148 
    149     // If this command is misdirected to the wrong document, treat it as not shown.
    150     if (!document.contains(element))
    151         return false;
    152 
    153     // Special cases for specific tag names.
    154     switch (element.tagName.toUpperCase()) {
    155     case "BODY":
    156         return true;
    157 
    158     case "SCRIPT":
    159     case "NOSCRIPT":
    160         return false;
    161 
    162     case "OPTGROUP":
    163     case "OPTION":
    164         // Option/optgroup are considered shown if the containing <select> is shown.
    165         let enclosingSelectElement = enclosingNodeOrSelfMatchingPredicate(element, (e) => e.tagName.toUpperCase() === "SELECT");
    166         return isShown(enclosingSelectElement);
    167 
    168     case "INPUT":
    169         // <input type="hidden"> is considered not shown.
    170         if (element.type === "hidden")
    171             return false;
    172         break;
    173 
    174     case "MAP":
    175         // FIXME: Selenium has special handling for <map> elements. We don't do anything now.
    176 
    177     default:
    178         break;
    179     }
    180 
    181     if (cascadedStylePropertyForElement(element, "visibility") !== "visible")
    182         return false;
    183 
    184     let hasAncestorWithZeroOpacity = !!enclosingElementOrSelfMatchingPredicate(element, (e) => {
    185         return Number(cascadedStylePropertyForElement(e, "opacity")) === 0;
    186     });
    187     let hasAncestorWithDisplayNone = !!enclosingElementOrSelfMatchingPredicate(element, (e) => {
    188         return cascadedStylePropertyForElement(e, "display") === "none";
    189     });
    190     if (hasAncestorWithZeroOpacity || hasAncestorWithDisplayNone)
    191         return false;
    192 
    193     if (!elementSubtreeHasNonZeroDimensions(element))
    194         return false;
    195 
    196     if (isElementSubtreeHiddenByOverflow(element))
    197         return false;
    198 
    199     return true;
     29    return utils.isShown(element);
    20030}
  • trunk/Source/WebKit/UIProcess/Automation/atoms/FindNodes.js

    r289202 r289467  
    2525
    2626function(strategy, ancestorElement, query, firstResultOnly, timeoutDuration, callback) {
     27    "use strict";
     28
    2729    ancestorElement = ancestorElement || document;
    2830
    … …  
    6870                let linkTextResult = [];
    6971                for (let link of ancestorElement.querySelectorAll("a")) {
    70                     if (link.text.trim() == query) {
     72                    if (utils.getText(link).trim() == query) {
    7173                        linkTextResult.push(link);
    7274                        if (firstResultOnly)
    … …  
    8183                let partialLinkResult = [];
    8284                for (let link of ancestorElement.querySelectorAll("a")) {
    83                     if (link.text.includes(query)) {
     85                    if (utils.getText(link).includes(query)) {
    8486                        partialLinkResult.push(link);
    8587                        if (firstResultOnly)
  • trunk/WebDriverTests/ChangeLog

    r289202 r289467  
     12022-02-09  Carlos Garcia Campos  <cgarcia@igalia.com>
     2
     3        WebDriver: add a javascript atom to get the visible text
     4        https://bugs.webkit.org/show_bug.cgi?id=174617
     5        <rdar://problem/32307461>
     6
     7        Reviewed by Adrian Perez de Castro.
     8
     9        Remove expectations of tests that are now passing.
     10
     11        * TestExpectations.json:
     12
    1132022-02-07  Carlos Garcia Campos  <cgarcia@igalia.com>
    214
  • trunk/WebDriverTests/TestExpectations.json

    r289202 r289467  
    134134    "imported/selenium/py/test/selenium/webdriver/common/select_class_tests.py": {
    135135        "subtests": {
    136             "testSelectByVisibleTextShouldNormalizeSpaces": {
    137                 "expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/174617"}}
    138             },
    139136            "testSelectByIndexMultiple": {
    140137                "expected": {"all": {"slow": true}}
    … …  
    150147    "imported/selenium/py/test/selenium/webdriver/common/text_handling_tests.py": {
    151148        "subtests": {
    152             "testShouldConvertANonBreakingSpaceIntoANormalSpaceCharacter": {
    153                 "expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/174617"}}
    154             },
    155             "testShouldTreatANonBreakingSpaceAsAnyOtherWhitespaceCharacterWhenCollapsingWhitespace": {
    156                 "expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/174617"}}
    157             },
    158149            "testShouldBeAbleToSetMoreThanOneLineOfTextInATextArea": {
    159150                "expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/174617"}}
    … …  
    161152            "testShouldHandleSiblingBlockLevelElements": {
    162153                "expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/174617"}}
    163             },
    164             "testShouldOnlyIncludeVisibleText": {
    165                 "expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/174617"}}
    166154            }
    167155        }
    … …  
    840828    "imported/w3c/webdriver/tests/find_element/find.py": {
    841829        "subtests": {
    842             "test_find_element_link_text[<a href=#>link<br>text</a>-link\\ntext]": {
    843                 "expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/184964"}}
    844             },
    845             "test_find_element_link_text[<a href=# style='text-transform: uppercase'>link text</a>-LINK TEXT]": {
    846                 "expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/184964"}}
    847             },
    848             "test_find_element_partial_link_text[<a href=#>partial link<br>text</a>-k\\nt]": {
    849                 "expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/184964"}}
    850             },
    851             "test_find_element_partial_link_text[<a href=# style='text-transform: uppercase'>partial link text</a>-LINK]": {
    852                 "expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/184964"}}
    853             },
    854830            "test_no_top_browsing_context": {
    855831                "expected": {"wpe": {"status": ["FAIL"], "bug": "webkit.org/b/212950"}}
    … …  
    862838    "imported/w3c/webdriver/tests/find_elements/find.py": {
    863839        "subtests": {
    864             "test_find_elements_link_text[<a href=#>link<br>text</a>-link\\ntext]": {
    865                 "expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/184964"}}
    866             },
    867             "test_find_elements_link_text[<a href=# style='text-transform: uppercase'>link text</a>-LINK TEXT]": {
    868                 "expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/184964"}}
    869             },
    870             "test_find_elements_partial_link_text[<a href=#>partial link<br>text</a>-k\\nt]": {
    871                 "expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/184964"}}
    872             },
    873             "test_find_elements_partial_link_text[<a href=# style='text-transform: uppercase'>partial link text</a>-LINK]": {
    874                 "expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/184964"}}
    875             },
    876840            "test_no_top_browsing_context": {
    877841                "expected": {"wpe": {"status": ["FAIL"], "bug": "webkit.org/b/212950"}}
    … …  
    884848    "imported/w3c/webdriver/tests/find_elements_from_element/find.py": {
    885849        "subtests": {
    886             "test_find_elements_link_text[<a href=#>link<br>text</a>-link\\ntext]": {
    887                 "expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/184964"}}
    888             },
    889             "test_find_elements_link_text[<a href=# style='text-transform: uppercase'>link text</a>-LINK TEXT]": {
    890                 "expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/184964"}}
    891             },
    892             "test_find_elements_partial_link_text[<a href=#>partial link<br>text</a>-k\\nt]": {
    893                 "expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/184964"}}
    894             },
    895             "test_find_elements_partial_link_text[<a href=# style='text-transform: uppercase'>partial link text</a>-LINK]": {
    896                 "expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/184964"}}
    897             },
    898850            "test_parent_of_document_node_errors": {
    899851                "expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/184964"}}
    … …  
    909861    "imported/w3c/webdriver/tests/find_element_from_element/find.py": {
    910862        "subtests": {
    911             "test_find_element_link_text[<a href=#>link<br>text</a>-link\\ntext]": {
    912                 "expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/184964"}}
    913             },
    914             "test_find_element_link_text[<a href=# style='text-transform: uppercase'>link text</a>-LINK TEXT]": {
    915                 "expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/184964"}}
    916             },
    917             "test_find_element_partial_link_text[<a href=#>partial link<br>text</a>-k\\nt]": {
    918                 "expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/184964"}}
    919             },
    920             "test_find_element_partial_link_text[<a href=# style='text-transform: uppercase'>partial link text</a>-LINK]": {
    921                 "expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/184964"}}
    922             },
    923863            "test_parent_of_document_node_errors": {
    924864                "expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/184964"}}
    … …  
    15761516            "test_find_element[xpath-//a]": {
    15771517                "expected": { "all": { "status": ["SKIP"]}}
    1578             },
    1579             "test_find_element_link_text[<a href=#>link<br>text</a>-link\\ntext]": {
    1580                 "expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/184964"}}
    1581             },
    1582             "test_find_element_link_text[<a href=# style='text-transform: uppercase'>link text</a>-LINK TEXT]": {
    1583                 "expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/184964"}}
    1584             },
    1585             "test_find_element_partial_link_text[<a href=#>partial link<br>text</a>-k\\nt]": {
    1586                 "expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/184964"}}
    1587             },
    1588             "test_find_element_partial_link_text[<a href=# style='text-transform: uppercase'>partial link text</a>-LINK]": {
    1589                 "expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/184964"}}
    15901518            }
    15911519        }
    … …  
    15981526            "test_find_elements[xpath-//a]": {
    15991527                "expected": { "all": { "status": ["SKIP"]}}
    1600             },
    1601             "test_find_elements_link_text[<a href=#>link<br>text</a>-link\\ntext]": {
    1602                 "expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/184964"}}
    1603             },
    1604             "test_find_elements_link_text[<a href=# style='text-transform: uppercase'>link text</a>-LINK TEXT]": {
    1605                 "expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/184964"}}
    1606             },
    1607             "test_find_elements_partial_link_text[<a href=#>partial link<br>text</a>-k\\nt]": {
    1608                 "expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/184964"}}
    1609             },
    1610             "test_find_elements_partial_link_text[<a href=# style='text-transform: uppercase'>partial link text</a>-LINK]": {
    1611                 "expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/184964"}}
    16121528            }
    16131529        }
Note: See TracChangeset for help on using the changeset viewer.