| // Copyright (c) 2012 The Chromium OS Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| 'use strict'; |
| |
| /** |
| * A mock accessibility reader which will simply record the last string passed |
| * to assertiveAnnounce. |
| */ |
| const MockAccessibilityReader = function() { |
| this.accessibilityEnabled = false; |
| this.lastStringAnnounced = ''; |
| }; |
| |
| /** |
| * Record the string passed to this function, which in a real implementation |
| * would be announced by the screen reader. |
| * |
| * @param {string} str The string to announce. |
| */ |
| MockAccessibilityReader.prototype.assertiveAnnounce = function(str) { |
| this.lastStringAnnounced = str; |
| }; |
| |
| hterm.ScrollPort.Tests = new lib.TestManager.Suite('hterm.ScrollPort.Tests'); |
| |
| hterm.ScrollPort.Tests.prototype.setup = function(cx) { |
| this.setDefaults(cx, |
| { visibleColumnCount: 80, |
| visibleRowCount: 25, |
| totalRowCount: 10000 |
| }); |
| |
| var document = cx.window.document; |
| |
| document.body.innerHTML = ''; |
| |
| this.rowProvider = new MockRowProvider(document, this.totalRowCount); |
| |
| var div = document.createElement('div'); |
| div.style.position = 'relative'; |
| div.style.height = '100%'; |
| div.style.width = '100%'; |
| document.body.appendChild(div); |
| |
| this.scrollPort = new hterm.ScrollPort(this.rowProvider); |
| this.scrollPort.decorate(div); |
| div.style.height = (this.scrollPort.characterSize.height * |
| this.visibleRowCount + 1 + 'px'); |
| this.scrollPort.resize(); |
| }; |
| |
| /** |
| * Ensure the selection is collapsed, row caching is on, and we're at the |
| * top of the scroll port. |
| */ |
| hterm.ScrollPort.Tests.prototype.preamble = function(result, cx) { |
| var selection = cx.window.getSelection(); |
| if (!selection.isCollapsed) |
| selection.collapseToStart(); |
| |
| this.rowProvider.setCacheEnabled(true); |
| |
| this.scrollPort.scrollRowToBottom(this.totalRowCount); |
| this.scrollPort.scrollRowToTop(0); |
| }; |
| |
| /** |
| * Basic test to make sure that the viewport contains the right number of |
| * rows at the right places after some scrolling. |
| */ |
| hterm.ScrollPort.Tests.addTest('basic-scroll', function(result, cx) { |
| var topRow = this.scrollPort.getTopRowIndex(); |
| result.assertEQ(topRow, 0); |
| result.assertEQ(this.scrollPort.getBottomRowIndex(topRow), |
| this.visibleRowCount - 1); |
| |
| this.scrollPort.scrollRowToBottom(this.totalRowCount); |
| topRow = this.scrollPort.getTopRowIndex(); |
| result.assertEQ(topRow, |
| this.totalRowCount - this.visibleRowCount); |
| result.assertEQ(this.scrollPort.getBottomRowIndex(topRow), |
| this.totalRowCount - 1); |
| |
| result.pass(); |
| }); |
| |
| /** |
| * Make sure the hterm.ScrollPort is reusing the same row nodes when it can. |
| */ |
| hterm.ScrollPort.Tests.addTest('node-recycler', function(result, cx) { |
| // Force a sync redraw before we get started so we know we're done |
| // calling getRowNode. |
| this.scrollPort.redraw_(); |
| |
| this.rowProvider.resetCallCount('getRowNode'); |
| this.scrollPort.scrollRowToTop(1); |
| |
| // Sync redraw so we know getRowNode was called again. |
| this.scrollPort.redraw_(); |
| |
| var count = this.rowProvider.getCallCount('getRowNode'); |
| |
| // Scrolling from 0 to 1 should result in only one call to getRowNode. |
| result.assertEQ(count, 1); |
| |
| result.pass(); |
| }); |
| |
| /** |
| * Make sure the selection is maintained even after scrolling off screen. |
| */ |
| hterm.ScrollPort.Tests.addTest('scroll-selection', function(result, cx) { |
| var doc = this.scrollPort.getDocument(); |
| |
| var s = doc.getSelection(); |
| // IE does not supposed the extend method on selections. They support |
| // an approximation using addRange, but it automatically merges sibling |
| // ranges and selects the parent node. Ignore this test on IE for now. |
| if (!s.extend) { |
| result.pass(); |
| return; |
| } |
| |
| // Scroll into a part of the buffer that can be scrolled off the top |
| // and the bottom of the screen. |
| this.scrollPort.scrollRowToTop(50); |
| |
| // Force a synchronous redraw. We'll need to DOM to be correct in order |
| // to alter the selection. |
| this.scrollPort.redraw_(); |
| |
| // And select some text in the middle of the visible range. |
| var anchorRow = this.rowProvider.getRowNode(55); |
| var anchorNode = anchorRow; |
| while (anchorNode.firstChild) |
| anchorNode = anchorNode.firstChild; |
| s.collapse(anchorNode, 0); |
| |
| var focusRow = this.rowProvider.getRowNode(55 + this.visibleRowCount - 10); |
| var focusNode = focusRow; |
| while (focusNode.lastChild) |
| focusNode = focusNode.lastChild; |
| s.extend(focusNode, focusNode.length || 0); |
| |
| for (var i = 0; i < this.visibleRowCount; i++) { |
| this.scrollPort.scrollRowToTop(50 - i); |
| this.scrollPort.redraw_(); |
| result.assertEQ(anchorNode, s.anchorNode); |
| result.assertEQ(focusNode, s.focusNode); |
| } |
| |
| for (var i = 0; i < this.visibleRowCount; i++) { |
| this.scrollPort.scrollRowToTop(50 + i); |
| this.scrollPort.redraw_(); |
| result.assertEQ(anchorNode, s.anchorNode); |
| result.assertEQ(focusNode, s.focusNode); |
| } |
| |
| result.pass(); |
| }); |
| |
| /** |
| * Make sure the selection is maintained for a collapsed selection. |
| */ |
| hterm.ScrollPort.Tests.addTest( |
| 'scroll-selection-collapsed', function(result, cx) { |
| const doc = this.scrollPort.getDocument(); |
| |
| const s = doc.getSelection(); |
| |
| // Scroll into a part of the buffer that can be scrolled off the top |
| // and the bottom of the screen. |
| this.scrollPort.scrollRowToTop(50); |
| |
| // Force a synchronous redraw. We'll need to DOM to be correct in order |
| // to alter the selection. |
| this.scrollPort.redraw_(); |
| |
| // Create a collapsed selection. |
| s.removeAllRanges(); |
| const anchorRow = this.rowProvider.getRowNode(53); |
| const anchorNode = anchorRow; |
| const range = doc.createRange(); |
| range.selectNode(anchorNode.firstChild); |
| range.collapse(true); |
| s.addRange(range); |
| |
| result.assertEQ(anchorNode, s.anchorNode); |
| result.assertEQ(anchorNode, s.focusNode); |
| result.assert(s.isCollapsed); |
| |
| // When accessibility is enabled, the selection should be preserved after |
| // scrolling. |
| const mockAccessibilityReader = new MockAccessibilityReader(); |
| mockAccessibilityReader.accessibilityEnabled = true; |
| this.scrollPort.setAccessibilityReader(mockAccessibilityReader); |
| |
| for (let i = 0; i < this.visibleRowCount; i++) { |
| this.scrollPort.scrollRowToTop(50 - i); |
| this.scrollPort.redraw_(); |
| result.assertEQ(anchorNode, s.anchorNode); |
| result.assertEQ(anchorNode, s.focusNode); |
| } |
| |
| for (let i = 0; i < this.visibleRowCount; i++) { |
| this.scrollPort.scrollRowToTop(50 + i); |
| this.scrollPort.redraw_(); |
| result.assertEQ(anchorNode, s.anchorNode); |
| result.assertEQ(anchorNode, s.focusNode); |
| } |
| |
| // When accessibility isn't enabled, the selection shouldn't be preserved |
| // after scrolling. |
| mockAccessibilityReader.accessibilityEnabled = false; |
| |
| for (let i = 0; i < this.visibleRowCount; i++) { |
| this.scrollPort.scrollRowToTop(50 - i); |
| this.scrollPort.redraw_(); |
| } |
| |
| for (let i = 0; i < this.visibleRowCount; i++) { |
| this.scrollPort.scrollRowToTop(50 + i); |
| this.scrollPort.redraw_(); |
| } |
| |
| result.assert(anchorNode != s.anchorNode); |
| result.assert(anchorNode != s.focusNode); |
| |
| result.pass(); |
| }); |
| |
| /** |
| * Test the select-all function. |
| */ |
| hterm.ScrollPort.Tests.addTest('select-all', function(result, cx) { |
| this.scrollPort.selectAll(); |
| result.assertEQ(0, this.scrollPort.selection.startRow.rowIndex); |
| result.assertEQ(this.totalRowCount - 1, |
| this.scrollPort.selection.endRow.rowIndex); |
| result.pass(); |
| }); |
| |
| /** |
| * Test that the page up/down buttons are onscreen when selected but offscreen |
| * otherwise. |
| */ |
| hterm.ScrollPort.Tests.addTest('page-up-down-visible', function(result, cx) { |
| const doc = this.scrollPort.getDocument(); |
| |
| this.scrollPort.allowScrollButtonsToDisplay_ = true; |
| const mockAccessibilityReader = new MockAccessibilityReader(); |
| mockAccessibilityReader.accessibilityEnabled = true; |
| this.scrollPort.setAccessibilityReader(mockAccessibilityReader); |
| |
| const selection = doc.getSelection(); |
| |
| const pageUp = doc.getElementById('hterm:a11y:page-up'); |
| result.assert(pageUp.getBoundingClientRect().bottom <= 0); |
| |
| selection.removeAllRanges(); |
| let range = document.createRange(); |
| range.selectNodeContents(pageUp.firstChild); |
| selection.addRange(range); |
| doc.dispatchEvent(new Event('selectionchange')); |
| |
| result.assert(pageUp.getBoundingClientRect().top >= 0); |
| |
| const pageDown = doc.getElementById('hterm:a11y:page-down'); |
| result.assert(pageDown.getBoundingClientRect().top >= |
| this.scrollPort.getScreenHeight()); |
| |
| selection.removeAllRanges(); |
| range = document.createRange(); |
| range.selectNodeContents(pageDown.firstChild); |
| selection.addRange(range); |
| doc.dispatchEvent(new Event('selectionchange')); |
| |
| result.assert(pageDown.getBoundingClientRect().bottom <= |
| this.scrollPort.getScreenHeight()); |
| |
| result.pass(); |
| }); |
| |
| /** |
| * Test that the page up/down buttons aren't moved onscreen when accessibility |
| * isn't enabled. |
| * |
| */ |
| hterm.ScrollPort.Tests.addTest('page-up-down-hidden', function(result, cx) { |
| const doc = this.scrollPort.getDocument(); |
| |
| this.scrollPort.allowScrollButtonsToDisplay_ = true; |
| const mockAccessibilityReader = new MockAccessibilityReader(); |
| mockAccessibilityReader.accessibilityEnabled = false; |
| this.scrollPort.setAccessibilityReader(mockAccessibilityReader); |
| |
| const selection = doc.getSelection(); |
| |
| const pageUp = doc.getElementById('hterm:a11y:page-up'); |
| result.assert(pageUp.getBoundingClientRect().bottom <= 0); |
| |
| selection.removeAllRanges(); |
| let range = document.createRange(); |
| range.selectNodeContents(pageUp.firstChild); |
| selection.addRange(range); |
| doc.dispatchEvent(new Event('selectionchange')); |
| |
| result.assert(pageUp.getBoundingClientRect().bottom <= 0); |
| |
| const pageDown = doc.getElementById('hterm:a11y:page-down'); |
| result.assert(pageDown.getBoundingClientRect().top >= |
| this.scrollPort.getScreenHeight()); |
| |
| selection.removeAllRanges(); |
| range = document.createRange(); |
| range.selectNodeContents(pageDown.firstChild); |
| selection.addRange(range); |
| doc.dispatchEvent(new Event('selectionchange')); |
| |
| result.assert(pageDown.getBoundingClientRect().top >= |
| this.scrollPort.getScreenHeight()); |
| |
| result.pass(); |
| }); |
| |
| /** |
| * Test that clicking page up/down causes the viewport to scroll up/down. |
| */ |
| hterm.ScrollPort.Tests.addTest('page-up-down-scroll', function(result, cx) { |
| const doc = this.scrollPort.getDocument(); |
| |
| const topRow = 50; |
| this.scrollPort.scrollRowToTop(topRow); |
| result.assertEQ(this.scrollPort.getTopRowIndex(), topRow); |
| |
| const pageDown = doc.getElementById('hterm:a11y:page-down'); |
| pageDown.dispatchEvent(new Event('click')); |
| result.assertEQ(this.scrollPort.getTopRowIndex(), topRow + 24); |
| |
| const pageUp = doc.getElementById('hterm:a11y:page-up'); |
| pageUp.dispatchEvent(new Event('click')); |
| result.assertEQ(this.scrollPort.getTopRowIndex(), topRow); |
| |
| result.pass(); |
| }); |
| |
| /** |
| * Test that the page up/down buttons are enabled/disabled correctly at the top |
| * and bottom of the scrollport. |
| */ |
| hterm.ScrollPort.Tests.addTest('page-up-down-state', function(result, cx) { |
| const doc = this.scrollPort.getDocument(); |
| const pageUp = doc.getElementById('hterm:a11y:page-up'); |
| const pageDown = doc.getElementById('hterm:a11y:page-down'); |
| |
| this.scrollPort.scrollRowToTop(0); |
| this.scrollPort.redraw_(); |
| result.assertEQ(pageUp.getAttribute('aria-disabled'), 'true'); |
| result.assertEQ(pageDown.getAttribute('aria-disabled'), 'false'); |
| |
| this.scrollPort.scrollRowToTop(50); |
| this.scrollPort.redraw_(); |
| result.assertEQ(pageUp.getAttribute('aria-disabled'), 'false'); |
| result.assertEQ(pageDown.getAttribute('aria-disabled'), 'false'); |
| |
| this.scrollPort.scrollRowToTop(10000); |
| this.scrollPort.redraw_(); |
| result.assertEQ(pageUp.getAttribute('aria-disabled'), 'false'); |
| result.assertEQ(pageDown.getAttribute('aria-disabled'), 'true'); |
| |
| result.pass(); |
| }); |
| |
| /** |
| * Test that paging up/down causes the screen contents to be announced |
| * correctly. |
| */ |
| hterm.ScrollPort.Tests.addTest('page-up-down-announce', function(result, cx) { |
| const doc = this.scrollPort.getDocument(); |
| |
| this.scrollPort.scrollRowToTop(0); |
| const mockAccessibilityReader = new MockAccessibilityReader(); |
| this.scrollPort.setAccessibilityReader(mockAccessibilityReader); |
| |
| const pageDown = doc.getElementById('hterm:a11y:page-down'); |
| pageDown.dispatchEvent(new Event('click')); |
| result.assertEQ( |
| mockAccessibilityReader.lastStringAnnounced, |
| '0% scrolled,\n' + |
| 'This is line 24 red green yellow blue magenta cyan\n' + |
| 'This is line 25 red green yellow blue magenta cyan\n' + |
| 'This is line 26 red green yellow blue magenta cyan\n' + |
| 'This is line 27 red green yellow blue magenta cyan\n' + |
| 'This is line 28 red green yellow blue magenta cyan\n' + |
| 'This is line 29 red green yellow blue magenta cyan\n' + |
| 'This is line 30 red green yellow blue magenta cyan\n' + |
| 'This is line 31 red green yellow blue magenta cyan\n' + |
| 'This is line 32 red green yellow blue magenta cyan\n' + |
| 'This is line 33 red green yellow blue magenta cyan\n' + |
| 'This is line 34 red green yellow blue magenta cyan\n' + |
| 'This is line 35 red green yellow blue magenta cyan\n' + |
| 'This is line 36 red green yellow blue magenta cyan\n' + |
| 'This is line 37 red green yellow blue magenta cyan\n' + |
| 'This is line 38 red green yellow blue magenta cyan\n' + |
| 'This is line 39 red green yellow blue magenta cyan\n' + |
| 'This is line 40 red green yellow blue magenta cyan\n' + |
| 'This is line 41 red green yellow blue magenta cyan\n' + |
| 'This is line 42 red green yellow blue magenta cyan\n' + |
| 'This is line 43 red green yellow blue magenta cyan\n' + |
| 'This is line 44 red green yellow blue magenta cyan\n' + |
| 'This is line 45 red green yellow blue magenta cyan\n' + |
| 'This is line 46 red green yellow blue magenta cyan\n' + |
| 'This is line 47 red green yellow blue magenta cyan\n' + |
| 'This is line 48 red green yellow blue magenta cyan\n'); |
| |
| const pageUp = doc.getElementById('hterm:a11y:page-up'); |
| pageUp.dispatchEvent(new Event('click')); |
| const linesOneToTwentyFive = '0% scrolled,\n' + |
| 'This is line 0 red green yellow blue magenta cyan\n' + |
| 'This is line 1 red green yellow blue magenta cyan\n' + |
| 'This is line 2 red green yellow blue magenta cyan\n' + |
| 'This is line 3 red green yellow blue magenta cyan\n' + |
| 'This is line 4 red green yellow blue magenta cyan\n' + |
| 'This is line 5 red green yellow blue magenta cyan\n' + |
| 'This is line 6 red green yellow blue magenta cyan\n' + |
| 'This is line 7 red green yellow blue magenta cyan\n' + |
| 'This is line 8 red green yellow blue magenta cyan\n' + |
| 'This is line 9 red green yellow blue magenta cyan\n' + |
| 'This is line 10 red green yellow blue magenta cyan\n' + |
| 'This is line 11 red green yellow blue magenta cyan\n' + |
| 'This is line 12 red green yellow blue magenta cyan\n' + |
| 'This is line 13 red green yellow blue magenta cyan\n' + |
| 'This is line 14 red green yellow blue magenta cyan\n' + |
| 'This is line 15 red green yellow blue magenta cyan\n' + |
| 'This is line 16 red green yellow blue magenta cyan\n' + |
| 'This is line 17 red green yellow blue magenta cyan\n' + |
| 'This is line 18 red green yellow blue magenta cyan\n' + |
| 'This is line 19 red green yellow blue magenta cyan\n' + |
| 'This is line 20 red green yellow blue magenta cyan\n' + |
| 'This is line 21 red green yellow blue magenta cyan\n' + |
| 'This is line 22 red green yellow blue magenta cyan\n' + |
| 'This is line 23 red green yellow blue magenta cyan\n' + |
| 'This is line 24 red green yellow blue magenta cyan\n' |
| result.assertEQ(mockAccessibilityReader.lastStringAnnounced, |
| linesOneToTwentyFive); |
| |
| // Test that other forms of scrolling won't cause announcements. |
| this.scrollPort.scrollRowToTop(2000); |
| result.assertEQ(mockAccessibilityReader.lastStringAnnounced, |
| linesOneToTwentyFive); |
| |
| // Ensure the percentage is computed correctly. |
| pageDown.dispatchEvent(new Event('click')); |
| result.assertEQ( |
| mockAccessibilityReader.lastStringAnnounced, |
| '20% scrolled,\n' + |
| 'This is line 2024 red green yellow blue magenta cyan\n' + |
| 'This is line 2025 red green yellow blue magenta cyan\n' + |
| 'This is line 2026 red green yellow blue magenta cyan\n' + |
| 'This is line 2027 red green yellow blue magenta cyan\n' + |
| 'This is line 2028 red green yellow blue magenta cyan\n' + |
| 'This is line 2029 red green yellow blue magenta cyan\n' + |
| 'This is line 2030 red green yellow blue magenta cyan\n' + |
| 'This is line 2031 red green yellow blue magenta cyan\n' + |
| 'This is line 2032 red green yellow blue magenta cyan\n' + |
| 'This is line 2033 red green yellow blue magenta cyan\n' + |
| 'This is line 2034 red green yellow blue magenta cyan\n' + |
| 'This is line 2035 red green yellow blue magenta cyan\n' + |
| 'This is line 2036 red green yellow blue magenta cyan\n' + |
| 'This is line 2037 red green yellow blue magenta cyan\n' + |
| 'This is line 2038 red green yellow blue magenta cyan\n' + |
| 'This is line 2039 red green yellow blue magenta cyan\n' + |
| 'This is line 2040 red green yellow blue magenta cyan\n' + |
| 'This is line 2041 red green yellow blue magenta cyan\n' + |
| 'This is line 2042 red green yellow blue magenta cyan\n' + |
| 'This is line 2043 red green yellow blue magenta cyan\n' + |
| 'This is line 2044 red green yellow blue magenta cyan\n' + |
| 'This is line 2045 red green yellow blue magenta cyan\n' + |
| 'This is line 2046 red green yellow blue magenta cyan\n' + |
| 'This is line 2047 red green yellow blue magenta cyan\n' + |
| 'This is line 2048 red green yellow blue magenta cyan\n'); |
| |
| result.pass(); |
| }); |
| |
| /** |
| * Test that paging up/down when at the top/bottom of the screen doesn't trigger |
| * any announcement. |
| */ |
| hterm.ScrollPort.Tests.addTest( |
| 'page-up-down-dont-announce', function(result, cx) { |
| const doc = this.scrollPort.getDocument(); |
| |
| this.scrollPort.scrollRowToTop(0); |
| const mockAccessibilityReader = new MockAccessibilityReader(); |
| this.scrollPort.setAccessibilityReader(mockAccessibilityReader); |
| |
| const pageUp = doc.getElementById('hterm:a11y:page-up'); |
| pageUp.dispatchEvent(new Event('click')); |
| result.assertEQ(mockAccessibilityReader.lastStringAnnounced, ''); |
| |
| this.scrollPort.scrollRowToTop(10000); |
| const pageDown = doc.getElementById('hterm:a11y:page-down'); |
| pageDown.dispatchEvent(new Event('click')); |
| result.assertEQ(mockAccessibilityReader.lastStringAnnounced, ''); |
| |
| result.pass(); |
| }); |
| |
| /** |
| * Remove the scrollPort that was set up and leave the user with a full-page |
| * scroll port. |
| * |
| * This should always be the last test of the suite, since it leaves the user |
| * with a full page scrollPort to poke at. |
| */ |
| hterm.ScrollPort.Tests.addTest('fullscreen', function(result, cx) { |
| var document = cx.window.document; |
| |
| document.body.innerHTML = ''; |
| |
| this.rowProvider = new MockRowProvider(document, this.totalRowCount); |
| |
| var div = document.createElement('div'); |
| div.style.position = 'absolute'; |
| div.style.height = '100%'; |
| div.style.width = '100%'; |
| document.body.appendChild(div); |
| |
| this.scrollPort = new hterm.ScrollPort(this.rowProvider, |
| this.fontSize, this.lineHeight); |
| this.scrollPort.decorate(div); |
| |
| cx.window.scrollPort = this.scrollPort; |
| |
| var divSize = hterm.getClientSize(div); |
| |
| result.assert(divSize.height > 0); |
| result.assert(divSize.width > 0); |
| result.assertEQ(divSize.height, |
| hterm.getClientHeight(this.scrollPort.iframe_)); |
| |
| result.pass(); |
| }); |
| |
| /** |
| * Make sure that offscreen elements are marked hidden. |
| */ |
| hterm.ScrollPort.Tests.addTest('scroll-selection-hidden', function(result, cx) { |
| const doc = this.scrollPort.getDocument(); |
| |
| const s = doc.getSelection(); |
| // IE does not supposed the extend method on selections. They support |
| // an approximation using addRange, but it automatically merges sibling |
| // ranges and selects the parent node. Ignore this test on IE for now. |
| if (!s.extend) { |
| result.pass(); |
| return; |
| } |
| |
| // Scroll into a part of the buffer that can be scrolled off the top |
| // and the bottom of the screen. |
| this.scrollPort.scrollRowToTop(1000); |
| |
| // Force a synchronous redraw. We'll need to DOM to be correct in order |
| // to alter the selection. |
| this.scrollPort.redraw_(); |
| |
| // And select some text in the middle of the visible range. |
| const anchorRow = this.rowProvider.getRowNode(1003); |
| let anchorNode = anchorRow; |
| while (anchorNode.firstChild) |
| anchorNode = anchorNode.firstChild; |
| s.collapse(anchorNode, 0); |
| |
| const focusRow = this.rowProvider.getRowNode(1004); |
| let focusNode = focusRow; |
| while (focusNode.lastChild) |
| focusNode = focusNode.lastChild; |
| s.extend(focusNode, focusNode.length || 0); |
| |
| function getVisibility(row) { |
| return doc.defaultView.getComputedStyle(row).getPropertyValue('visibility'); |
| }; |
| |
| result.assert(getVisibility(anchorRow) != 'hidden'); |
| result.assert(getVisibility(focusRow) != 'hidden'); |
| |
| this.scrollPort.scrollRowToTop(0); |
| this.scrollPort.redraw_(); |
| |
| result.assertEQ(getVisibility(anchorRow), 'hidden'); |
| result.assertEQ(getVisibility(focusRow), 'hidden'); |
| |
| this.scrollPort.scrollRowToTop(1000); |
| this.scrollPort.redraw_(); |
| |
| result.assert(getVisibility(anchorRow) != 'hidden'); |
| result.assert(getVisibility(focusRow) != 'hidden'); |
| |
| this.scrollPort.scrollRowToTop(2000); |
| this.scrollPort.redraw_(); |
| |
| result.assertEQ(getVisibility(anchorRow), 'hidden'); |
| result.assertEQ(getVisibility(focusRow), 'hidden'); |
| |
| result.pass(); |
| }); |
| |
| hterm.ScrollPort.DragAndDropTests = |
| new lib.TestManager.Suite('hterm.ScrollPort.DragAndDrop.Tests'); |
| |
| /** |
| * We can't generate useful DragEvents as the dataTransfer member is forced |
| * read-only, so create a fake object and call the drag handler directly. |
| * This is a bit ugly, but the web makes us do it. |
| */ |
| const MockDragEvent = function(shift) { |
| this.dataTransfer = new DataTransfer(); |
| this.shiftKey = !!shift; |
| this.preventDefault = () => {}; |
| }; |
| |
| hterm.ScrollPort.DragAndDropTests.prototype.preamble = function(cx) { |
| // Create a new port since so the subscribe event doesn't stick to |
| // this.scrollPort across multiple tests. |
| this.scrollPort = new hterm.ScrollPort(); |
| }; |
| |
| /** |
| * A single text/plain element. |
| */ |
| hterm.ScrollPort.DragAndDropTests.addTest('drag-drop-text', function(result, cx) { |
| const e = new MockDragEvent(); |
| e.dataTransfer.setData('text/plain', 'plain'); |
| |
| this.scrollPort.subscribe('paste', (e) => { |
| result.assertEQ('plain', e.text); |
| result.pass(); |
| }); |
| this.scrollPort.onDragAndDrop_(e); |
| |
| result.requestTime(200); |
| }); |
| |
| /** |
| * Pick between text & html based on shift key not pressed. |
| */ |
| hterm.ScrollPort.DragAndDropTests.addTest('drag-drop-text-no-shift', function(result, cx) { |
| const e = new MockDragEvent(); |
| e.dataTransfer.setData('text/html', 'html'); |
| e.dataTransfer.setData('text/plain', 'plain'); |
| |
| this.scrollPort.subscribe('paste', (e) => { |
| result.assertEQ('plain', e.text); |
| result.pass(); |
| }); |
| this.scrollPort.onDragAndDrop_(e); |
| |
| result.requestTime(200); |
| }); |
| |
| /** |
| * Pick between text & html based on shift key pressed. |
| */ |
| hterm.ScrollPort.DragAndDropTests.addTest('drag-drop-text-shift', function(result, cx) { |
| const e = new MockDragEvent(true /* shift */); |
| e.dataTransfer.setData('text/html', 'html'); |
| e.dataTransfer.setData('text/plain', 'plain'); |
| |
| this.scrollPort.subscribe('paste', (e) => { |
| result.assertEQ('html', e.text); |
| result.pass(); |
| }); |
| this.scrollPort.onDragAndDrop_(e); |
| |
| result.requestTime(200); |
| }); |
| |
| /** |
| * Verify fallback when first source is empty & shift key is not pressed. |
| */ |
| hterm.ScrollPort.DragAndDropTests.addTest('drag-drop-text-fallback-no-shift', function(result, cx) { |
| const e = new MockDragEvent(); |
| e.dataTransfer.setData('text/html', ''); |
| e.dataTransfer.setData('text/plain', 'plain'); |
| |
| this.scrollPort.subscribe('paste', (e) => { |
| result.assertEQ('plain', e.text); |
| result.pass(); |
| }); |
| this.scrollPort.onDragAndDrop_(e); |
| |
| result.requestTime(200); |
| }); |
| |
| /** |
| * Verify fallback when first source is empty & shift key is pressed. |
| */ |
| hterm.ScrollPort.DragAndDropTests.addTest('drag-drop-text-fallback-shift', function(result, cx) { |
| const e = new MockDragEvent(true /* shift */); |
| e.dataTransfer.setData('text/html', ''); |
| e.dataTransfer.setData('text/plain', 'plain'); |
| |
| this.scrollPort.subscribe('paste', (e) => { |
| result.assertEQ('plain', e.text); |
| result.pass(); |
| }); |
| this.scrollPort.onDragAndDrop_(e); |
| |
| result.requestTime(200); |
| }); |
| |
| /** |
| * Verify bad sources don't trigger paste events. |
| */ |
| hterm.ScrollPort.DragAndDropTests.addTest('drag-drop-unusable', function(result, cx) { |
| const e = new MockDragEvent(); |
| this.scrollPort.subscribe('paste', () => result.fail()); |
| |
| // Binary only data shouldn't trigger an event. |
| e.dataTransfer.setData('application/x-executable', 'plain'); |
| this.scrollPort.onDragAndDrop_(e); |
| |
| // Neither should empty text. |
| e.dataTransfer.setData('text/plain', ''); |
| this.scrollPort.onDragAndDrop_(e); |
| |
| result.requestTime(1000); |
| setTimeout(() => result.pass(), 100); |
| }); |