| <!doctype html> |
| <script src="../../resources/testharness.js"></script> |
| <script src="../../resources/testharnessreport.js"></script> |
| <script src="../assert_selection.js"></script> |
| <script> |
| // For https://bugs.webkit.org/show_bug.cgi?id=57340, which introduce |
| // VisibleSelection::Visible{Base,Extent}() and |original_base_| in |
| // |SelectionController|. |
| |
| // TODO(editing-dev): We should make this test faster[1], e.g. do not drag |
| // all characters. |
| // [1] http://crbug.com/741259 |
| const kFontSize = '20px'; |
| const kMouseStep = 5; |
| |
| function fold(string) { |
| const results = []; |
| for (let i = 0; i < string.length; i++) { |
| let code = string.charCodeAt(i); |
| if (0x05d0 <= code && code <= 0x05ea)// Hebrew Alef |
| code += -0x05d0 + 'A'.charCodeAt(0); |
| results.push(String.fromCharCode(code)); |
| } |
| return results.join(''); |
| } |
| |
| function startDrag(x, y) { |
| assert_own_property(window, 'eventSender', 'This test requires window.eventSender'); |
| eventSender.dragMode = false; |
| |
| // Clear click count |
| eventSender.mouseMoveTo(0, 0); |
| eventSender.mouseDown(); |
| eventSender.mouseUp(); |
| |
| eventSender.mouseMoveTo(x, y); |
| eventSender.mouseDown(); |
| } |
| |
| function endDrag() { |
| eventSender.mouseUp(); |
| } |
| |
| class StaticRange { |
| constructor(selection) { |
| this.anchorNode_ = selection.anchorNode; |
| this.anchorOffset_ = selection.anchorOffset; |
| this.focusNode_ = selection.focusNode; |
| this.focusOffset_ = selection.focusOffset; |
| } |
| |
| equals(other) { |
| return this.anchorNode_ == other.anchorNode_ && |
| this.anchorOffset_ == other.anchorOffset_ && |
| this.focusNode_ == other.focusNode_ && |
| this.focusOffset_ == other.focusOffset_; |
| } |
| } |
| |
| function moveRightUntilSelectionChanged(selection, left, right, y) { |
| const startRange = new StaticRange(selection); |
| for (let x = left; x <= right; x += kMouseStep) { |
| eventSender.mouseMoveTo(x, y); |
| if (!startRange.equals(new StaticRange(selection))) |
| return x; |
| } |
| throw 'moveRightUntilSelectionChanged failed'; |
| } |
| |
| function moveLeftUntilSelectionChanged(selection, left, right, y) { |
| const startRange = new StaticRange(selection); |
| for (let x = right; x >= left; x -= kMouseStep) { |
| eventSender.mouseMoveTo(x, y); |
| if (!startRange.equals(new StaticRange(selection))) |
| return x; |
| } |
| throw 'moveLeftUntilSelectionChanged failed'; |
| } |
| |
| function dragLeftToRight(selection, count) { |
| const target = selection.document.querySelector('.target'); |
| const left = selection.computeLeft(target); |
| const right = left + target.offsetWidth; |
| const y = selection.computeTop(target); |
| startDrag(left, y); |
| let x = left; |
| for (let i = 0; i < count; ++i) |
| x = moveRightUntilSelectionChanged(selection, x, right, y); |
| endDrag(); |
| } |
| |
| function dragRightToLeft(selection, numberOfSelectionChanges) { |
| const target = selection.document.querySelector('.target'); |
| const left = selection.computeLeft(target); |
| const right = left + target.offsetWidth - 1; |
| const y = selection.computeTop(target); |
| startDrag(right, y); |
| let x = right; |
| for (let i = 0; i < numberOfSelectionChanges; ++i) |
| x = moveLeftUntilSelectionChanged(selection, left, x, y); |
| endDrag(); |
| } |
| |
| function testIt(drag, caseIndex, count, sample, expected, expectedText) { |
| test(() => assert_selection( |
| sample, |
| selection => { |
| selection.document.body.style.fontFamily = 'monospace'; |
| selection.document.body.style.fontSize = kFontSize; |
| drag(selection, count); |
| assert_equals(fold(selection.toString()), expectedText); |
| }, |
| expected), |
| `${caseIndex}-${count}: ${drag.name} expects "${expectedText}".`); |
| } |
| |
| const kSample1 = '<span class="target">abc\u05d0\u05d1\u05d2</span>'; |
| testIt(dragLeftToRight, 1, 1, kSample1, |
| '<span class="target">^a|bc\u05d0\u05d1\u05d2</span>', 'a'); |
| testIt(dragLeftToRight, 1, 2, kSample1, |
| '<span class="target">^ab|c\u05d0\u05d1\u05d2</span>', 'ab'); |
| testIt(dragLeftToRight, 1, 3, kSample1, |
| '<span class="target">^abc|\u05d0\u05d1\u05d2</span>', 'abc'); |
| testIt(dragLeftToRight, 1, 4, kSample1, |
| '<span class="target">^abc\u05d0\u05d1|\u05d2</span>', 'abcAB'); |
| testIt(dragLeftToRight, 1, 5, kSample1, |
| '<span class="target">^abc\u05d0|\u05d1\u05d2</span>', 'abcA'); |
| testIt(dragLeftToRight, 1, 6, kSample1, |
| '<span class="target">^abc\u05d0\u05d1\u05d2|</span>', 'abcABC'); |
| |
| testIt(dragRightToLeft, 1, 1, kSample1, |
| '<span class="target">abc^\u05d0|\u05d1\u05d2</span>', 'A'); |
| testIt(dragRightToLeft, 1, 2, kSample1, |
| '<span class="target">abc^\u05d0\u05d1|\u05d2</span>', 'AB'); |
| testIt(dragRightToLeft, 1, 3, kSample1, |
| '<span class="target">abc|\u05d0\u05d1\u05d2^</span>', 'ABC'); |
| testIt(dragRightToLeft, 1, 4, kSample1, |
| '<span class="target">ab|c\u05d0\u05d1\u05d2^</span>', 'cABC'); |
| testIt(dragRightToLeft, 1, 5, kSample1, |
| '<span class="target">a|bc\u05d0\u05d1\u05d2^</span>', 'bcABC'); |
| testIt(dragRightToLeft, 1, 6, kSample1, |
| '<span class="target">|abc\u05d0\u05d1\u05d2^</span>', 'abcABC'); |
| |
| const kSample2 = '<span class="target">\u05d0\u05d1\u05d2def</span>'; |
| testIt(dragLeftToRight, 2, 1, kSample2, |
| '<span class="target">\u05d0\u05d1|\u05d2^def</span>', 'C'); |
| testIt(dragLeftToRight, 2, 2, kSample2, |
| '<span class="target">\u05d0|\u05d1\u05d2^def</span>', 'BC'); |
| testIt(dragLeftToRight, 2, 3, kSample2, |
| '<span class="target">^\u05d0\u05d1\u05d2|def</span>', 'ABC'); |
| testIt(dragLeftToRight, 2, 4, kSample2, |
| '<span class="target">^\u05d0\u05d1\u05d2d|ef</span>', 'ABCd'); |
| testIt(dragLeftToRight, 2, 5, kSample2, |
| // TODO(editing-dev): This should be 'ABCef' instead of 'ABCde'. |
| '<span class="target">^\u05d0\u05d1\u05d2de|f</span>', 'ABCde'); |
| testIt(dragLeftToRight, 2, 6, kSample2, |
| '<span class="target">^\u05d0\u05d1\u05d2def|</span>', 'ABCdef'); |
| |
| testIt(dragRightToLeft, 2, 1, kSample2, |
| '<span class="target">\u05d0\u05d1\u05d2de|f^</span>', 'f'); |
| testIt(dragRightToLeft, 2, 2, kSample2, |
| '<span class="target">\u05d0\u05d1\u05d2d|ef^</span>', 'ef'); |
| testIt(dragRightToLeft, 2, 3, kSample2, |
| '<span class="target">\u05d0\u05d1\u05d2|def^</span>', 'def'); |
| testIt(dragRightToLeft, 2, 4, kSample2, |
| '<span class="target">\u05d0|\u05d1\u05d2def^</span>', 'BCdef'); |
| testIt(dragRightToLeft, 2, 5, kSample2, |
| '<span class="target">\u05d0\u05d1|\u05d2def^</span>', 'Cdef'); |
| testIt(dragRightToLeft, 2, 6, kSample2, |
| '<span class="target">|\u05d0\u05d1\u05d2def^</span>', 'ABCdef'); |
| |
| const kSample3 = 'abc<span class="target">\u05d0\u05d1\u05d2</span>def'; |
| testIt(dragLeftToRight, 3, 1, kSample3, |
| 'abc<span class="target">\u05d0\u05d1|\u05d2^</span>def', 'C'); |
| testIt(dragLeftToRight, 3, 2, kSample3, |
| 'abc<span class="target">\u05d0|\u05d1\u05d2^</span>def', 'BC'); |
| testIt(dragLeftToRight, 3, 3, kSample3, |
| 'abc<span class="target">^\u05d0\u05d1\u05d2|</span>def', 'ABC'); |
| |
| testIt(dragRightToLeft, 3, 1, kSample3, |
| 'abc<span class="target">^\u05d0|\u05d1\u05d2</span>def', 'A'); |
| testIt(dragRightToLeft, 3, 2, kSample3, |
| 'abc<span class="target">^\u05d0\u05d1|\u05d2</span>def', 'AB'); |
| testIt(dragRightToLeft, 3, 3, kSample3, |
| 'abc<span class="target">|\u05d0\u05d1\u05d2^</span>def', 'ABC'); |
| |
| const kSample4 = [ |
| '<div dir="rtl">', |
| '<span class="target">\u05d0\u05d1\u05d2</span>def', |
| '</div>', |
| ].join(''); |
| testIt(dragLeftToRight, 4, 1, kSample4, |
| '<div dir="rtl"><span class="target">\u05d0\u05d1|\u05d2^</span>def</div>', |
| 'C'); |
| testIt(dragLeftToRight, 4, 2, kSample4, |
| '<div dir="rtl"><span class="target">\u05d0|\u05d1\u05d2^</span>def</div>', |
| 'BC'); |
| testIt(dragLeftToRight, 4, 3, kSample4, |
| '<div dir="rtl"><span class="target">|\u05d0\u05d1\u05d2^</span>def</div>', |
| 'ABC'); |
| |
| testIt(dragRightToLeft, 4, 1, kSample4, |
| '<div dir="rtl"><span class="target">^\u05d0|\u05d1\u05d2</span>def</div>', |
| 'A'); |
| testIt(dragRightToLeft, 4, 2, kSample4, |
| '<div dir="rtl"><span class="target">^\u05d0\u05d1|\u05d2</span>def</div>', |
| 'AB'); |
| testIt(dragRightToLeft, 4, 3, kSample4, |
| '<div dir="rtl"><span class="target">^\u05d0\u05d1\u05d2|</span>def</div>', |
| 'ABC'); |
| |
| const kSample5 = '\u05d0\u05d1\u05d2d<span class="target">ef</span>'; |
| testIt(dragLeftToRight, 5, 1, kSample5, |
| '\u05d0\u05d1\u05d2d<span class="target">^e|f</span>', 'e'); |
| testIt(dragLeftToRight, 5, 2, kSample5, |
| '\u05d0\u05d1\u05d2d<span class="target">^ef|</span>', 'ef'); |
| |
| testIt(dragRightToLeft, 5, 1, kSample5, |
| '\u05d0\u05d1\u05d2d<span class="target">e|f^</span>', 'f'); |
| testIt(dragRightToLeft, 5, 2, kSample5, |
| '\u05d0\u05d1\u05d2d<span class="target">|ef^</span>', 'ef'); |
| |
| const kSample6 = 'abc<span class="target">\u05d0\u05d1</span>\u05d2'; |
| testIt(dragLeftToRight, 6, 1, kSample6, |
| 'abc<span class="target">\u05d0|\u05d1^</span>\u05d2', 'B'); |
| testIt(dragLeftToRight, 6, 2, kSample6, |
| 'abc<span class="target">|\u05d0\u05d1^</span>\u05d2', 'AB'); |
| |
| testIt(dragRightToLeft, 6, 1, kSample6, |
| 'abc<span class="target">^\u05d0|\u05d1</span>\u05d2', 'A'); |
| testIt(dragRightToLeft, 6, 2, kSample6, |
| 'abc<span class="target">^\u05d0\u05d1|</span>\u05d2', 'AB'); |
| |
| const kSample7 = 'a\u05e7\u05dc<span class="target">12</span>\u05d9\u05ddd'; |
| testIt(dragLeftToRight, 7, 1, kSample7, |
| 'a\u05e7\u05dc<span class="target">^1|2</span>\u05d9\u05ddd', '1'); |
| testIt(dragLeftToRight, 7, 2, kSample7, |
| 'a\u05e7\u05dc<span class="target">^12|</span>\u05d9\u05ddd', '12'); |
| |
| testIt(dragRightToLeft, 7, 1, kSample7, |
| 'a\u05e7\u05dc<span class="target">1|2^</span>\u05d9\u05ddd', '2'); |
| testIt(dragRightToLeft, 7, 2, kSample7, |
| 'a\u05e7\u05dc<span class="target">|12^</span>\u05d9\u05ddd', '12'); |
| |
| const kSample8 = [ |
| '<div dir="rtl">', |
| '<span class="target">\u05d0\u05d1\u05d2 123</span>', |
| '</div>', |
| ].join(''); |
| testIt(dragLeftToRight, 8, 1, kSample8, |
| '<div dir="rtl"><span class="target">\u05d0\u05d1\u05d2 ^1|23</span></div>', |
| '1'); |
| testIt(dragLeftToRight, 8, 2, kSample8, |
| '<div dir="rtl"><span class="target">\u05d0\u05d1\u05d2 ^12|3</span></div>', |
| '12'); |
| testIt(dragLeftToRight, 8, 3, kSample8, |
| '<div dir="rtl"><span class="target">\u05d0\u05d1\u05d2 |123^</span></div>', |
| '123'); |
| testIt(dragLeftToRight, 8, 4, kSample8, |
| '<div dir="rtl"><span class="target">\u05d0\u05d1\u05d2| 123^</span></div>', |
| ' 123'); |
| testIt(dragLeftToRight, 8, 5, kSample8, |
| '<div dir="rtl"><span class="target">\u05d0\u05d1|\u05d2 123^</span></div>', |
| 'C 123'); |
| testIt(dragLeftToRight, 8, 6, kSample8, |
| '<div dir="rtl"><span class="target">\u05d0|\u05d1\u05d2 123^</span></div>', |
| 'BC 123'); |
| testIt(dragLeftToRight, 8, 7, kSample8, |
| '<div dir="rtl"><span class="target">|\u05d0\u05d1\u05d2 123^</span></div>', |
| 'ABC 123'); |
| |
| testIt(dragRightToLeft, 8, 1, kSample8, |
| '<div dir="rtl"><span class="target">^\u05d0|\u05d1\u05d2 123</span></div>', |
| 'A'); |
| testIt(dragRightToLeft, 8, 2, kSample8, |
| '<div dir="rtl"><span class="target">^\u05d0\u05d1|\u05d2 123</span></div>', |
| 'AB'); |
| testIt(dragRightToLeft, 8, 3, kSample8, |
| '<div dir="rtl"><span class="target">^\u05d0\u05d1\u05d2| 123</span></div>', |
| 'ABC'); |
| testIt(dragRightToLeft, 8, 4, kSample8, |
| '<div dir="rtl"><span class="target">^\u05d0\u05d1\u05d2 |123</span></div>', |
| 'ABC '); |
| testIt(dragRightToLeft, 8, 5, kSample8, |
| '<div dir="rtl"><span class="target">^\u05d0\u05d1\u05d2 12|3</span></div>', |
| 'ABC 12'); |
| testIt(dragRightToLeft, 8, 6, kSample8, |
| '<div dir="rtl"><span class="target">^\u05d0\u05d1\u05d2 1|23</span></div>', |
| 'ABC 1'); |
| testIt(dragRightToLeft, 8, 7, kSample8, |
| '<div dir="rtl"><span class="target">^\u05d0\u05d1\u05d2 123|</span></div>', |
| 'ABC 123'); |
| |
| const kSample9 = '<span class="target">\u05d0\u05d1\u05d2 123</span>'; |
| testIt(dragLeftToRight, 9, 1, kSample9, |
| '<span class="target">\u05d0\u05d1\u05d2 ^1|23</span>', '1'); |
| testIt(dragLeftToRight, 9, 2, kSample9, |
| '<span class="target">\u05d0\u05d1\u05d2 ^12|3</span>', '12'); |
| testIt(dragLeftToRight, 9, 3, kSample9, |
| // TODO(editing-dev): This should be ' 123' instead of '123'. |
| '<span class="target">\u05d0\u05d1\u05d2 ^123|</span>', '123'); |
| testIt(dragLeftToRight, 9, 4, kSample9, |
| // TODO(editing-dev): This should be 'C 123' instead of ' '. |
| '<span class="target">\u05d0\u05d1\u05d2| ^123</span>', ' '); |
| testIt(dragLeftToRight, 9, 5, kSample9, |
| // TODO(editing-dev): This should be 'BC 123' instead of 'C '. |
| '<span class="target">\u05d0\u05d1|\u05d2 ^123</span>', 'C '); |
| testIt(dragLeftToRight, 9, 6, kSample9, |
| // TODO(editing-dev): This should be 'ABC 123' instead of 'BC '. |
| '<span class="target">\u05d0|\u05d1\u05d2 ^123</span>', 'BC '); |
| testIt(dragLeftToRight, 9, 7, kSample9, |
| // TODO(editing-dev): This should be '' instead of '123'. |
| '<span class="target">\u05d0\u05d1\u05d2 ^123|</span>', '123'); |
| |
| testIt(dragRightToLeft, 9, 1, kSample9, |
| '<span class="target">^\u05d0|\u05d1\u05d2 123</span>', 'A'); |
| testIt(dragRightToLeft, 9, 2, kSample9, |
| '<span class="target">^\u05d0\u05d1|\u05d2 123</span>', 'AB'); |
| testIt(dragRightToLeft, 9, 3, kSample9, |
| '<span class="target">^\u05d0\u05d1\u05d2| 123</span>', 'ABC'); |
| testIt(dragRightToLeft, 9, 4, kSample9, |
| // TODO(editing-dev): This should be 'ABC ' instead of ''. |
| '<span class="target">\u05d0\u05d1\u05d2 123|</span>', ''); |
| testIt(dragRightToLeft, 9, 5, kSample9, |
| '<span class="target">^\u05d0\u05d1\u05d2 12|3</span>', 'ABC 12'); |
| testIt(dragRightToLeft, 9, 6, kSample9, |
| '<span class="target">^\u05d0\u05d1\u05d2 1|23</span>', 'ABC 1'); |
| testIt(dragRightToLeft, 9, 7, kSample9, |
| // TODO(editing-dev): This should be 'ABC 123' instead of ''. |
| '<span class="target">\u05d0\u05d1\u05d2 |123^</span>', '123'); |
| |
| // For https://bugs.webkit.org/show_bug.cgi?id=73056 |
| const kStyle10 = 'position: absolute; left: 0px; top: 0px; z-index: -5;'; |
| const kSample10 = [ |
| '<div style="position: relative;">', |
| 'a\u05d0\u05d1\u05d2b', |
| `<div style="${kStyle10}">`, |
| 'a<span class="target">\u05d0\u05d1\u05d2</span>b', |
| '</div>', |
| '</div>' |
| ].join(''); |
| |
| testIt(dragLeftToRight, 10, 1, kSample10, |
| [ |
| '<div style="position: relative;">', |
| 'a\u05d0\u05d1|\u05d2^b', |
| `<div style="${kStyle10}">`, |
| 'a<span class="target">\u05d0\u05d1\u05d2</span>b', |
| '</div>', |
| '</div>' |
| ].join(''), 'C'); |
| testIt(dragLeftToRight, 10, 2, kSample10, |
| [ |
| '<div style="position: relative;">', |
| 'a\u05d0|\u05d1\u05d2^b', |
| `<div style="${kStyle10}">`, |
| 'a<span class="target">\u05d0\u05d1\u05d2</span>b', |
| '</div>', |
| '</div>' |
| ].join(''), 'BC'); |
| testIt(dragLeftToRight, 10, 3, kSample10, |
| [ |
| '<div style="position: relative;">', |
| 'a^\u05d0\u05d1\u05d2|b', |
| `<div style="${kStyle10}">`, |
| 'a<span class="target">\u05d0\u05d1\u05d2</span>b', |
| '</div>', |
| '</div>' |
| ].join(''), 'ABC'); |
| |
| testIt(dragRightToLeft, 10, 1, kSample10, |
| [ |
| '<div style="position: relative;">', |
| 'a^\u05d0|\u05d1\u05d2b', |
| `<div style="${kStyle10}">`, |
| 'a<span class="target">\u05d0\u05d1\u05d2</span>b', |
| '</div>', |
| '</div>' |
| ].join(''), 'A'); |
| testIt(dragRightToLeft, 10, 2, kSample10, |
| [ |
| '<div style="position: relative;">', |
| 'a^\u05d0\u05d1|\u05d2b', |
| `<div style="${kStyle10}">`, |
| 'a<span class="target">\u05d0\u05d1\u05d2</span>b', |
| '</div>', |
| '</div>' |
| ].join(''), 'AB'); |
| ; |
| testIt(dragRightToLeft, 10, 3, kSample10, |
| [ |
| '<div style="position: relative;">', |
| 'a|\u05d0\u05d1\u05d2^b', |
| `<div style="${kStyle10}">`, |
| 'a<span class="target">\u05d0\u05d1\u05d2</span>b', |
| '</div>', |
| '</div>' |
| ].join(''), 'ABC'); |
| |
| const kSample11 = '<span class="target" dir="rtl">\u05d0\u05d1\u05d2<br></span>'; |
| testIt(dragLeftToRight, 11, 1, kSample11, |
| '<span class="target" dir="rtl">\u05d0\u05d1|\u05d2^<br></span>', 'C'); |
| testIt(dragLeftToRight, 11, 2, kSample11, |
| '<span class="target" dir="rtl">\u05d0|\u05d1\u05d2^<br></span>', 'BC'); |
| testIt(dragLeftToRight, 11, 3, kSample11, |
| '<span class="target" dir="rtl">^\u05d0\u05d1\u05d2|<br></span>', 'ABC'); |
| |
| testIt(dragRightToLeft, 11, 1, kSample11, |
| '<span class="target" dir="rtl">^\u05d0|\u05d1\u05d2<br></span>', 'A'); |
| testIt(dragRightToLeft, 11, 2, kSample11, |
| '<span class="target" dir="rtl">^\u05d0\u05d1|\u05d2<br></span>', 'AB'); |
| testIt(dragRightToLeft, 11, 3, kSample11, |
| '<span class="target" dir="rtl">|\u05d0\u05d1\u05d2^<br></span>', 'ABC'); |
| </script> |