tor-browser

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

FormControlRange-offset.html (5197B)


      1 <!DOCTYPE html>
      2 <meta charset="utf-8">
      3 <script src="/resources/testharness.js"></script>
      4 <script src="/resources/testharnessreport.js"></script>
      5 <body></body>
      6 <script>
      7 const controls = ["textarea", "input"];
      8 
      9 function setupControl(control, value) {
     10  document.body.innerHTML = (control === "input") ? '<input type="text">' : '<textarea></textarea>';
     11  const element = document.body.firstElementChild;
     12  element.value = value;
     13  return element;
     14 }
     15 
     16 controls.forEach(control => {
     17  test(() => {
     18    const element = setupControl(control, "A");
     19    const range = new FormControlRange();
     20 
     21    [[0, 0, "", true], [0, 1, "A", false], [1, 1, "", true]].forEach(([start, end, text, collapsed]) => {
     22      range.setFormControlRange(element, start, end);
     23      assert_equals(range.toString(), text);
     24      assert_equals(range.collapsed, collapsed);
     25    });
     26  }, `FormControlRange with single character in ${control}.`);
     27 
     28  test(() => {
     29    const element = setupControl(control, "");
     30    const range = new FormControlRange();
     31 
     32    range.setFormControlRange(element, 0, 0);
     33    assert_equals(range.toString(), "");
     34    assert_true(range.collapsed);
     35  }, `FormControlRange with empty control in ${control}.`);
     36 
     37  test(() => {
     38    const element = setupControl(control, "Hello World");
     39    const range = new FormControlRange();
     40 
     41    [[0, 5, "Hello"], [5, 6, " "], [6, 11, "World"], [11, 11, ""]].forEach(([start, end, expected]) => {
     42      range.setFormControlRange(element, start, end);
     43      assert_equals(range.toString(), expected);
     44    });
     45  }, `FormControlRange boundary positions in ${control}.`);
     46 
     47  test(() => {
     48    const testCases = [
     49      {
     50        // Emoji 😊 with length 2 in UTF-16 ('\uD83D\uDE0A').
     51        text: '\u{1F60A}',
     52        ranges: [[0, 0, ""], [0, 2, "😊"], [2, 2, ""], [0, 1, "\uD83D"], [1, 2, "\uDE0A"]]
     53      },
     54      {
     55        // ZWJ emoji (πŸ‘¨β€πŸ‘©β€πŸ‘§) with length 8 in UTF-16 ('\uD83D\uDC68\u200D\uD83D\uDC69\u200D\uD83D\uDC67').
     56        text: '\u{1F468}\u{200D}\u{1F469}\u{200D}\u{1F467}',
     57        ranges: [[0, 0, ""], [0, 8, "πŸ‘¨β€πŸ‘©β€πŸ‘§"], [8, 8, ""], [0, 2, "πŸ‘¨"], [3, 5, "πŸ‘©"], [6, 8, "πŸ‘§"],
     58          [1, 2, "\uDC68"], [2, 3, "\u200D"]]
     59      },
     60      {
     61        // Mixed ASCII and emoji 😊.
     62        text: 'Hello\u{1F60A}World',
     63        ranges: [[0, 5, "Hello"], [5, 7, "😊"], [7, 12, "World"], [0, 12, "Hello😊World"], [3, 6, "lo\uD83D"],
     64          [6, 9, "\uDE0AWo"],  [4, 8, "o😊W"]]
     65      }
     66    ];
     67 
     68    testCases.forEach(testCase => {
     69      const element = setupControl(control, testCase.text);
     70      const range = new FormControlRange();
     71      testCase.ranges.forEach(([start, end, expected]) => {
     72        range.setFormControlRange(element, start, end);
     73        assert_equals(range.toString(), expected);
     74      });
     75    });
     76  }, `FormControlRange with Unicode characters in ${control}.`);
     77 });
     78 
     79 
     80 test(() => {
     81  // Test textarea with mixed whitespace in light DOM.
     82  document.body.innerHTML = '<textarea>  \n\t  Line1\n  Line2  \t\n  </textarea>';
     83  const textarea = document.body.firstElementChild;
     84  const range = new FormControlRange();
     85 
     86  // Whitespace is preserved in textarea.value.
     87  range.setFormControlRange(textarea, 0, textarea.value.length);
     88  assert_equals(range.toString(), textarea.value);
     89  assert_true(range.toString().includes('\n'));
     90  assert_true(range.toString().includes('\t'));
     91 }, "FormControlRange preserves whitespace in textarea light DOM.");
     92 
     93 test(() => {
     94  document.body.innerHTML = '<textarea>Hello World</textarea>';
     95  const textarea = document.body.firstElementChild;
     96 
     97  // Create a complex DOM structure inside the textarea.
     98  // Child nodes don't affect the textarea's .value, only text content does.
     99  textarea.append(document.createElement("video"));
    100  textarea.append(document.createElement("iframe"));
    101 
    102  const span = document.createElement("span");
    103  span.innerHTML = "more text";
    104  textarea.append(span);
    105 
    106  textarea.append(document.createTextNode("Some rendered content"));
    107  textarea.append(document.createTextNode("Some more rendered content"));
    108 
    109  const range = new FormControlRange();
    110 
    111  // FormControlRange uses element.value, which includes text nodes but ignores element children.
    112  assert_equals(textarea.value, "Hello WorldSome rendered contentSome more rendered content");
    113  range.setFormControlRange(textarea, 0, textarea.value.length);
    114  assert_equals(range.toString(), "Hello WorldSome rendered contentSome more rendered content");
    115 }, "FormControlRange should work correctly with weirdly formed light DOM structure.");
    116 
    117 test(() => {
    118  // Test input with child nodes (which shouldn't exist but might)
    119  document.body.innerHTML = '<input type="text" value="Original">';
    120  const input = document.body.firstElementChild;
    121 
    122  // Malformed: add child nodes to input (shouldn't affect value).
    123  input.appendChild(document.createTextNode("Ignored"));
    124  input.appendChild(document.createElement("span")).textContent = "AlsoIgnored";
    125 
    126  const range = new FormControlRange();
    127  range.setFormControlRange(input, 0, input.value.length);
    128 
    129  // Input.value is unaffected by child nodes.
    130  assert_equals(range.toString(), "Original");
    131 }, "FormControlRange ignores malformed input child nodes.");
    132 </script>