public void TestMouseWheel()
        {
            // Use a registry helper to backup and restore registry state before/after test
            using (RegistryHelper reg = new RegistryHelper())
            {
                reg.BackupRegistry();

                // Start our application to test
                using (CmdApp app = new CmdApp(CreateType.ProcessOnly, TestContext))
                {
                    Log.Comment("First ensure that word wrap is off so we can get scroll bars in both directions.");
                    // Make sure wrap is off
                    app.SetWrapState(false);

                    IntPtr handle = app.GetStdOutHandle();
                    Verify.IsNotNull(handle, "Ensure we have the output handle.");

                    Log.Comment("Set up the window so the buffer is larger than the window. Retrieve existing properties then set the viewport to smaller than the buffer.");

                    WinCon.CONSOLE_SCREEN_BUFFER_INFO_EX info = app.GetScreenBufferInfo(handle);

                    info.srWindow.Left   = 0;
                    info.srWindow.Right  = 30;
                    info.srWindow.Top    = 0;
                    info.srWindow.Bottom = 30;

                    info.dwSize.X = 100;
                    info.dwSize.Y = 100;
                    app.SetScreenBufferInfo(handle, info);

                    Log.Comment("Now retrieve the starting position of the window viewport.");

                    Log.Comment("Scroll down one.");
                    VerifyScroll(app, ScrollDir.Vertical, -1);

                    Log.Comment("Scroll right one.");
                    VerifyScroll(app, ScrollDir.Horizontal, 1);

                    Log.Comment("Scroll left one.");
                    VerifyScroll(app, ScrollDir.Horizontal, -1);

                    Log.Comment("Scroll up one.");
                    VerifyScroll(app, ScrollDir.Vertical, 1);
                }
            }
        }
        [TestProperty("Ignore", "True")] // GH#7282 - investigate and reenable
        public void CanExpandToEnclosingUnitTextRangeProvider()
        {
            using (CmdApp app = new CmdApp(CreateType.ProcessOnly, TestContext))
            {
                var sbiex = app.GetScreenBufferInfo();
                sbiex.dwSize.Y = (short)(2 * sbiex.srWindow.Height);
                app.SetScreenBufferInfo(sbiex);

                AutomationElement  textAreaUiaElement = GetTextAreaUiaElement(app);
                TextPattern        textPattern        = textAreaUiaElement.GetCurrentPattern(TextPattern.Pattern) as TextPattern;
                TextPatternRange[] visibleRanges      = textPattern.GetVisibleRanges();
                TextPatternRange   testRange          = visibleRanges.First().Clone();

                // change testRange to a degenerate range and then expand to a line
                testRange.MoveEndpointByRange(TextPatternRangeEndpoint.End, testRange, TextPatternRangeEndpoint.Start);
                Verify.AreEqual(0, testRange.CompareEndpoints(TextPatternRangeEndpoint.Start,
                                                              testRange,
                                                              TextPatternRangeEndpoint.End));
                testRange.ExpandToEnclosingUnit(TextUnit.Line);
                Verify.IsTrue(testRange.Compare(visibleRanges[0]));

                // expand to document size
                testRange.ExpandToEnclosingUnit(TextUnit.Document);
                Verify.IsTrue(testRange.Compare(textPattern.DocumentRange));

                // shrink back to a line
                testRange.ExpandToEnclosingUnit(TextUnit.Line);
                Verify.IsTrue(testRange.Compare(visibleRanges[0]));

                // make the text buffer start to cycle its buffer
                _FillOutputBufferWithData(app);

                // expand to document range again
                testRange.ExpandToEnclosingUnit(TextUnit.Document);
                Verify.IsTrue(testRange.Compare(textPattern.DocumentRange));
            }
        }
        private void TestScrollByOverflowImpl(CmdApp app, ViewportArea area, IntPtr hConsole, WinCon.CONSOLE_SCREEN_BUFFER_INFO_EX sbiex, Queue <EventData> expected, WinCon.CONSOLE_SCREEN_BUFFER_INFO_EX sbiexOriginal)
        {
            // Get original screen information
            sbiexOriginal = app.GetScreenBufferInfo();
            short promptLineEnd = sbiexOriginal.dwCursorPosition.X;

            promptLineEnd--; // prompt line ended one position left of cursor

            // Resize the window to only have two lines left at the bottom to test overflow when we echo some text
            sbiex = sbiexOriginal;
            sbiex.srWindow.Bottom  = sbiex.dwCursorPosition.Y;
            sbiex.srWindow.Bottom += 3;
            app.SetScreenBufferInfo(sbiex);

            string echoText    = "foo";
            string echoCommand = "echo";

            int echoLine = sbiexOriginal.dwCursorPosition.Y + 1;

            expected.Enqueue(new EventData(EventType.UpdateRegion, 0, echoLine, echoText.Length - 1, echoLine));
            expected.Enqueue(new EventData(EventType.UpdateScroll, 0, -1));
            int newPromptLine = echoLine + 2;

            expected.Enqueue(new EventData(EventType.UpdateRegion, 0, newPromptLine, promptLineEnd, newPromptLine));
            expected.Enqueue(new EventData(EventType.Layout));
            expected.Enqueue(new EventData(EventType.CaretVisible, promptLineEnd + 1, newPromptLine));

            // type command to echo foo and press enter
            app.UIRoot.SendKeys($"{echoCommand} {echoText}");
            Globals.WaitForTimeout();
            received.Clear();
            app.UIRoot.SendKeys(Keys.Enter);
            Globals.WaitForTimeout();

            VerifyQueue(expected);
        }
        [TestProperty("Ignore", "True")] // GH#7282 - investigate and reenable
        public void CanMoveEndpointByUnitNearBottomBoundary()
        {
            using (CmdApp app = new CmdApp(CreateType.ProcessOnly, TestContext))
            {
                var sbiex = app.GetScreenBufferInfo();
                sbiex.dwSize.Y = (short)(2 * sbiex.srWindow.Height);
                app.SetScreenBufferInfo(sbiex);

                AutomationElement  textAreaUiaElement = GetTextAreaUiaElement(app);
                TextPattern        textPattern        = textAreaUiaElement.GetCurrentPattern(TextPattern.Pattern) as TextPattern;
                TextPatternRange[] visibleRanges      = textPattern.GetVisibleRanges();
                TextPatternRange   testRange          = visibleRanges.First().Clone();

                // assumes that range is a line range at the bottom of the screen buffer
                Action <TextPatternRange> testBottomBoundary = delegate(TextPatternRange range)
                {
                    // the range is at the bottom of the screen buffer, we
                    // shouldn't be able to move the endpoint endpoint down
                    int moveAmount = range.MoveEndpointByUnit(TextPatternRangeEndpoint.End, TextUnit.Line, 1);
                    Verify.AreEqual(0, moveAmount);

                    // we shouldn't be able to move the starting endpoint down either
                    moveAmount = range.MoveEndpointByUnit(TextPatternRangeEndpoint.Start, TextUnit.Line, 1);
                    Verify.AreEqual(0, moveAmount);
                };

                // move the range to the bottom of the screen
                int rowsToMove = _GetTotalRows(app) - 1;
                int moveCount  = testRange.Move(TextUnit.Line, rowsToMove);
                Verify.AreEqual(rowsToMove, moveCount);

                testBottomBoundary(testRange);

                // we want to test that the boundaries are still observed
                // when the screen buffer index and text buffer index don't align.
                // write a bunch of text to the screen to fill up the text
                // buffer and make it start to reuse its buffer
                _FillOutputBufferWithData(app);
                Globals.WaitForTimeout();

                // move all the way to the top
                visibleRanges = textPattern.GetVisibleRanges();
                testRange     = visibleRanges.First().Clone();
                while (true)
                {
                    int moved = testRange.Move(TextUnit.Line, -1);
                    if (moved == 0)
                    {
                        break;
                    }
                }

                // we're at the top of the screen buffer, so move back to the bottom
                // so we can test
                rowsToMove = _GetTotalRows(app) - 1;
                moveCount  = testRange.Move(TextUnit.Line, rowsToMove);
                Verify.AreEqual(rowsToMove, moveCount);
                testRange.ScrollIntoView(true);

                testBottomBoundary(testRange);
            }
        }
        [TestProperty("Ignore", "True")] // GH#7282 - investigate and reenable
        public void CanMoveRange()
        {
            using (CmdApp app = new CmdApp(CreateType.ProcessOnly, TestContext))
            {
                var sbiex = app.GetScreenBufferInfo();
                sbiex.dwSize.Y = (short)(2 * sbiex.srWindow.Height);
                app.SetScreenBufferInfo(sbiex);

                AutomationElement  textAreaUiaElement = GetTextAreaUiaElement(app);
                TextPattern        textPattern        = textAreaUiaElement.GetCurrentPattern(TextPattern.Pattern) as TextPattern;
                TextPatternRange[] visibleRanges      = textPattern.GetVisibleRanges();
                TextPatternRange   testRange          = visibleRanges.First().Clone();


                // assumes range is at the top of the screen buffer
                Action <TextPatternRange> testMovement = delegate(TextPatternRange range)
                {
                    // the range is at the top of the screen
                    // buffer, we shouldn't be able to move up.
                    int moveAmount = range.Move(TextUnit.Line, -1);
                    Verify.AreEqual(0, moveAmount);

                    // move to the bottom of the screen
                    // - 1 because we're already on the 0th row
                    int rowsToMove = _GetTotalRows(app) - 1;
                    moveAmount = range.Move(TextUnit.Line, rowsToMove);
                    Verify.AreEqual(rowsToMove, moveAmount);

                    // try to move one more row down, we should not be able to
                    moveAmount = range.Move(TextUnit.Line, 1);
                    Verify.AreEqual(0, moveAmount);

                    // move the range up to the top again, one row at a time,
                    // making sure that we have only one line being encompassed
                    // by the range. We check this by counting the number of
                    // bounding rectangles that represent the range.
                    for (int i = 0; i < rowsToMove; ++i)
                    {
                        moveAmount = range.Move(TextUnit.Line, -1);
                        // we need to scroll into view or getting the boundary
                        // rectangles might return 0
                        Verify.AreEqual(-1, moveAmount);
                        range.ScrollIntoView(true);
                        Rect[] boundingRects = range.GetBoundingRectangles();
                        Verify.AreEqual(1, boundingRects.GetLength(0));
                    }

                    // and back down to the bottom, one row at a time
                    for (int i = 0; i < rowsToMove; ++i)
                    {
                        moveAmount = range.Move(TextUnit.Line, 1);
                        // we need to scroll into view or getting the boundary
                        // rectangles might return 0
                        Verify.AreEqual(1, moveAmount);
                        range.ScrollIntoView(true);
                        Rect[] boundingRects = range.GetBoundingRectangles();
                        Verify.AreEqual(1, boundingRects.GetLength(0));
                    }
                };

                testMovement(testRange);

                // test again with unaligned text buffer and screen buffer
                _FillOutputBufferWithData(app);
                Globals.WaitForTimeout();

                visibleRanges = textPattern.GetVisibleRanges();
                testRange     = visibleRanges.First().Clone();
                // move range back to the top
                while (true)
                {
                    int moveCount = testRange.Move(TextUnit.Line, -1);
                    if (moveCount == 0)
                    {
                        break;
                    }
                }

                testMovement(testRange);
            }
        }