tor-browser

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

FormControlRange-interactive-overlap-and-selection.html (3934B)


      1 <!DOCTYPE html>
      2 <meta charset="utf-8">
      3 <script src="/resources/testharness.js"></script>
      4 <script src="/resources/testharnessreport.js"></script>
      5 <script src="/resources/testdriver.js"></script>
      6 <script src="/resources/testdriver-vendor.js"></script>
      7 <script src="/resources/testdriver-actions.js"></script>
      8 <body></body>
      9 <script>
     10 'use strict';
     11 
     12 const KEY_BACKSPACE = '\uE003';
     13 const KEY_DELETE = '\uE017';
     14 const controls = ['input', 'textarea'];
     15 
     16 function setup(control, value) {
     17  document.body.innerHTML = control === 'input' ? '<input type="text">' : '<textarea></textarea>';
     18  const element = document.body.firstElementChild;
     19  element.value = value;
     20  element.focus();
     21  return element;
     22 }
     23 
     24 async function typeKeys(element, text) { await test_driver.send_keys(element, text); }
     25 
     26 function makeRange(element, start, end) {
     27  const range = new FormControlRange();
     28  range.setFormControlRange(element, start, end);
     29  return range;
     30 }
     31 
     32 controls.forEach(control => {
     33  [
     34    // Selection partially overlaps the start of the live range: deletion shrinks and shifts start.
     35    { name:'partial overlap at start (delete selection)',
     36      init:{ value:'ABCDE', rangeStart:2, rangeEnd:4, selA:1, selB:3, key:KEY_BACKSPACE },
     37      expect:{ value:'ADE', start:1, end:2, text:'D' } },
     38    // Selection partially overlaps the end of the live range: deletion contracts end.
     39    { name:'partial overlap at end (delete selection)',
     40      init:{ value:'ABCDE', rangeStart:1, rangeEnd:3, selA:2, selB:4, key:KEY_BACKSPACE },
     41      expect:{ value:'ABE', start:1, end:2, text:'B' } },
     42  ].forEach(tc => {
     43    promise_test(async t => {
     44      const element = setup(control, tc.init.value);
     45      const range = makeRange(element, tc.init.rangeStart, tc.init.rangeEnd);
     46      element.setSelectionRange(tc.init.selA, tc.init.selB);
     47      if (tc.init.key) {
     48        await typeKeys(element, tc.init.key);
     49      } else if (tc.init.text) {
     50        await typeKeys(element, tc.init.text);
     51      }
     52      assert_equals(element.value, tc.expect.value, 'post-edit element.value');
     53      assert_equals(range.startOffset, tc.expect.start, 'range start');
     54      assert_equals(range.endOffset, tc.expect.end, 'range end');
     55      assert_equals(range.toString(), tc.expect.text, 'range text');
     56    }, `Overlap: ${tc.name} (${control}).`);
     57  });
     58 
     59  [
     60    { name:'delete selection exactly equal to range (collapse)',
     61      init:{ value:'ABCDE', rangeStart:1, rangeEnd:3, selA:1, selB:3, key:KEY_BACKSPACE },
     62      expect:{ value:'ADE', start:1, end:1, text:'' } },
     63    { name:'delete subset inside range (contract end)',
     64      init:{ value:'ABCDE', rangeStart:1, rangeEnd:4, selA:2, selB:3, key:KEY_BACKSPACE },
     65      expect:{ value:'ABDE', start:1, end:3, text:'BD' } },
     66  ].forEach(tc => {
     67    promise_test(async t => {
     68      const element = setup(control, tc.init.value);
     69      const range = makeRange(element, tc.init.rangeStart, tc.init.rangeEnd);
     70      element.setSelectionRange(tc.init.selA, tc.init.selB);
     71      await typeKeys(element, tc.init.key);
     72      assert_equals(element.value, tc.expect.value, 'post-delete value');
     73      assert_equals(range.startOffset, tc.expect.start, 'start after delete');
     74      assert_equals(range.endOffset, tc.expect.end, 'end after delete');
     75      assert_equals(range.toString(), tc.expect.text, 'text after delete');
     76      if (tc.expect.start === tc.expect.end) {
     77        assert_true(range.collapsed, 'range collapsed');
     78      }
     79    }, `Selection deletion: ${tc.name} (${control}).`);
     80  });
     81 
     82  promise_test(async t => {
     83    const element = setup(control, 'ABCDE');
     84    const range = makeRange(element, 2, 4);
     85    element.setSelectionRange(1, 1);
     86    await typeKeys(element, KEY_DELETE);
     87    assert_equals(element.value, 'ACDE');
     88    assert_equals(range.startOffset, 1);
     89    assert_equals(range.endOffset, 3);
     90    assert_equals(range.toString(), 'CD');
     91  }, `Boundary forward delete shifts range left (${control}).`);
     92 
     93 });
     94 </script>