Skip to content

Commit b725c1c

Browse files
committed
Add integration tests for scrolling and zooming behavior
1 parent 711ab1c commit b725c1c

File tree

4 files changed

+190
-4
lines changed

4 files changed

+190
-4
lines changed

Tvl.VisualStudio.MouseFastScroll.IntegrationTests/Editor_InProc.cs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ namespace Tvl.VisualStudio.MouseFastScroll.IntegrationTests
55
{
66
using System;
77
using System.Runtime.InteropServices;
8+
using System.Windows;
89
using Microsoft.VisualStudio.Text;
910
using Microsoft.VisualStudio.Text.Editor;
1011
using Microsoft.VisualStudio.TextManager.Interop;
@@ -76,9 +77,45 @@ public void MoveCaret(int position)
7677
});
7778
}
7879

80+
public bool IsCaretOnScreen()
81+
{
82+
return ExecuteOnActiveView(
83+
view =>
84+
{
85+
var caret = view.Caret;
86+
return caret.Left >= view.ViewportLeft
87+
&& caret.Right <= view.ViewportRight
88+
&& caret.Top >= view.ViewportTop
89+
&& caret.Bottom <= view.ViewportBottom;
90+
});
91+
}
92+
7993
protected override ITextBuffer GetBufferContainingCaret(IWpfTextView view)
8094
{
8195
return view.GetBufferContainingCaret();
8296
}
97+
98+
public int GetFirstVisibleLine()
99+
{
100+
return ExecuteOnActiveView(view => view.TextViewLines.FirstVisibleLine.Start.GetContainingLine().LineNumber);
101+
}
102+
103+
public int GetLastVisibleLine()
104+
{
105+
return ExecuteOnActiveView(view => view.TextViewLines.LastVisibleLine.Start.GetContainingLine().LineNumber);
106+
}
107+
108+
public Point GetCenterOfEditorOnScreen()
109+
{
110+
return ExecuteOnActiveView(
111+
view =>
112+
{
113+
var center = new Point(view.VisualElement.ActualWidth / 2, view.VisualElement.ActualHeight / 2);
114+
return view.VisualElement.PointToScreen(center);
115+
});
116+
}
117+
118+
public double GetZoomLevel()
119+
=> ExecuteOnActiveView(view => view.ZoomLevel);
83120
}
84121
}

Tvl.VisualStudio.MouseFastScroll.IntegrationTests/Editor_OutOfProc.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
namespace Tvl.VisualStudio.MouseFastScroll.IntegrationTests
55
{
6+
using System.Windows;
67
using WindowsInput.Native;
78

89
public class Editor_OutOfProc : TextViewWindow_OutOfProc
@@ -33,6 +34,9 @@ internal void SetText(string value)
3334
public void MoveCaret(int position)
3435
=> EditorInProc.MoveCaret(position);
3536

37+
public bool IsCaretOnScreen()
38+
=> EditorInProc.IsCaretOnScreen();
39+
3640
/// <summary>
3741
/// Sends key strokes to the active editor in Visual Studio. Various types are supported by this method:
3842
/// <see cref="string"/> (each character will be sent separately, <see cref="char"/>, and
@@ -43,5 +47,17 @@ public void SendKeys(params object[] keys)
4347
Activate();
4448
VisualStudioInstance.SendKeys.Send(keys);
4549
}
50+
51+
public int GetFirstVisibleLine()
52+
=> EditorInProc.GetFirstVisibleLine();
53+
54+
public int GetLastVisibleLine()
55+
=> EditorInProc.GetLastVisibleLine();
56+
57+
public Point GetCenterOfEditorOnScreen()
58+
=> EditorInProc.GetCenterOfEditorOnScreen();
59+
60+
public double GetZoomLevel()
61+
=> EditorInProc.GetZoomLevel();
4662
}
4763
}

Tvl.VisualStudio.MouseFastScroll.IntegrationTests/NativeMethods.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,8 @@
44
namespace Tvl.VisualStudio.MouseFastScroll.IntegrationTests
55
{
66
using System;
7-
using System.Collections.Generic;
8-
using System.Linq;
97
using System.Runtime.InteropServices;
108
using System.Text;
11-
using System.Threading.Tasks;
129
using IBindCtx = Microsoft.VisualStudio.OLE.Interop.IBindCtx;
1310
using IRunningObjectTable = Microsoft.VisualStudio.OLE.Interop.IRunningObjectTable;
1411

@@ -72,6 +69,9 @@ internal static class NativeMethods
7269
public const uint MAPVK_VK_TO_CHAR = 2;
7370
public const uint MAPVK_VSC_TO_KV_EX = 3;
7471

72+
public const int SM_CXSCREEN = 0;
73+
public const int SM_CYSCREEN = 1;
74+
7575
public static readonly int SizeOf_INPUT = Marshal.SizeOf<INPUT>();
7676

7777
[UnmanagedFunctionPointer(CallingConvention.Winapi, SetLastError = false)]
@@ -152,6 +152,9 @@ internal static class NativeMethods
152152
[DllImport(User32, CharSet = CharSet.Unicode)]
153153
public static extern uint MapVirtualKey(uint uCode, uint uMapType);
154154

155+
[DllImport(User32, CharSet = CharSet.Unicode)]
156+
public static extern int GetSystemMetrics(int nIndex);
157+
155158
[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode, Pack = 8)]
156159
public struct INPUT
157160
{

Tvl.VisualStudio.MouseFastScroll.IntegrationTests/TrivialIntegrationTest.cs

Lines changed: 131 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ namespace Tvl.VisualStudio.MouseFastScroll.IntegrationTests
55
{
66
using System;
77
using System.Linq;
8+
using System.Windows;
9+
using System.Windows.Media;
10+
using WindowsInput;
11+
using WindowsInput.Native;
812
using Xunit;
913
using vsSaveChanges = EnvDTE.vsSaveChanges;
1014

@@ -30,7 +34,7 @@ public void TestOpenAndCloseIDE()
3034
}
3135

3236
[Fact]
33-
public void OpenDocumentAndType()
37+
public void BasicScrollingBehavior()
3438
{
3539
var window = VisualStudioInstance.RetryRpcCall(() => VisualStudio.Dte.ItemOperations.NewFile(Name: Guid.NewGuid() + ".txt"));
3640

@@ -44,8 +48,134 @@ public void OpenDocumentAndType()
4448
Assert.Equal(expected, VisualStudio.Editor.GetText());
4549

4650
Assert.Equal(expected.Length, VisualStudio.Editor.GetCaretPosition());
51+
52+
// Move the caret and verify the final position. Note that the MoveCaret operation does not scroll the view.
53+
int firstVisibleLine = VisualStudio.Editor.GetFirstVisibleLine();
54+
Assert.True(firstVisibleLine > 0, "Expected the view to start after the first line at this point.");
4755
VisualStudio.Editor.MoveCaret(0);
4856
Assert.Equal(0, VisualStudio.Editor.GetCaretPosition());
57+
Assert.Equal(firstVisibleLine, VisualStudio.Editor.GetFirstVisibleLine());
58+
59+
var inputSimulator = new InputSimulator();
60+
VisualStudio.ActivateMainWindow();
61+
inputSimulator.Keyboard
62+
.KeyDown(VirtualKeyCode.CONTROL)
63+
.KeyPress(VirtualKeyCode.HOME)
64+
.KeyUp(VirtualKeyCode.CONTROL);
65+
66+
VisualStudio.WaitForApplicationIdle();
67+
68+
Assert.True(VisualStudio.Editor.IsCaretOnScreen());
69+
firstVisibleLine = VisualStudio.Editor.GetFirstVisibleLine();
70+
Assert.Equal(0, firstVisibleLine);
71+
72+
int lastVisibleLine = VisualStudio.Editor.GetLastVisibleLine();
73+
Assert.True(firstVisibleLine < lastVisibleLine);
74+
75+
Point point = VisualStudio.Editor.GetCenterOfEditorOnScreen();
76+
int horizontalResolution = NativeMethods.GetSystemMetrics(NativeMethods.SM_CXSCREEN);
77+
int verticalResolution = NativeMethods.GetSystemMetrics(NativeMethods.SM_CYSCREEN);
78+
point = new ScaleTransform(65535.0 / horizontalResolution, 65535.0 / verticalResolution).Transform(point);
79+
80+
inputSimulator.Mouse
81+
.MoveMouseTo(point.X, point.Y)
82+
.VerticalScroll(-1);
83+
84+
Assert.Equal(0, VisualStudio.Editor.GetCaretPosition());
85+
Assert.Equal(3, VisualStudio.Editor.GetFirstVisibleLine());
86+
87+
inputSimulator.Mouse
88+
.MoveMouseTo(point.X, point.Y)
89+
.VerticalScroll(1);
90+
91+
Assert.Equal(0, VisualStudio.Editor.GetCaretPosition());
92+
Assert.Equal(0, VisualStudio.Editor.GetFirstVisibleLine());
93+
94+
inputSimulator
95+
.Mouse.MoveMouseTo(point.X, point.Y)
96+
.Keyboard.KeyDown(VirtualKeyCode.CONTROL)
97+
.Mouse.VerticalScroll(-1)
98+
.Keyboard.KeyUp(VirtualKeyCode.CONTROL);
99+
100+
Assert.Equal(0, VisualStudio.Editor.GetCaretPosition());
101+
Assert.Equal(lastVisibleLine, VisualStudio.Editor.GetFirstVisibleLine());
102+
103+
inputSimulator
104+
.Mouse.MoveMouseTo(point.X, point.Y)
105+
.Keyboard.KeyDown(VirtualKeyCode.CONTROL)
106+
.Mouse.VerticalScroll(1)
107+
.Keyboard.KeyUp(VirtualKeyCode.CONTROL);
108+
109+
Assert.Equal(0, VisualStudio.Editor.GetCaretPosition());
110+
Assert.Equal(0, VisualStudio.Editor.GetFirstVisibleLine());
111+
112+
VisualStudioInstance.RetryRpcCall(() => window.Close(vsSaveChanges.vsSaveChangesNo));
113+
}
114+
115+
/// <summary>
116+
/// Verifies that the Ctrl+Scroll operations do not change the zoom level in the editor.
117+
/// </summary>
118+
[Fact]
119+
public void ZoomDisabled()
120+
{
121+
var window = VisualStudioInstance.RetryRpcCall(() => VisualStudio.Dte.ItemOperations.NewFile(Name: Guid.NewGuid() + ".txt"));
122+
123+
string initialText = string.Join(string.Empty, Enumerable.Range(0, 400).Select(i => Guid.NewGuid() + Environment.NewLine));
124+
VisualStudio.Editor.SetText(initialText);
125+
126+
string additionalTypedText = Guid.NewGuid().ToString() + "\n" + Guid.NewGuid().ToString();
127+
VisualStudio.Editor.SendKeys(additionalTypedText);
128+
129+
string expected = initialText + additionalTypedText.Replace("\n", Environment.NewLine);
130+
Assert.Equal(expected, VisualStudio.Editor.GetText());
131+
132+
Assert.Equal(expected.Length, VisualStudio.Editor.GetCaretPosition());
133+
134+
var inputSimulator = new InputSimulator();
135+
VisualStudio.ActivateMainWindow();
136+
inputSimulator.Keyboard
137+
.KeyDown(VirtualKeyCode.CONTROL)
138+
.KeyPress(VirtualKeyCode.HOME)
139+
.KeyUp(VirtualKeyCode.CONTROL);
140+
141+
VisualStudio.WaitForApplicationIdle();
142+
143+
int firstVisibleLine = VisualStudio.Editor.GetFirstVisibleLine();
144+
Assert.Equal(0, firstVisibleLine);
145+
146+
int lastVisibleLine = VisualStudio.Editor.GetLastVisibleLine();
147+
Assert.True(firstVisibleLine < lastVisibleLine);
148+
149+
double zoomLevel = VisualStudio.Editor.GetZoomLevel();
150+
151+
Point point = VisualStudio.Editor.GetCenterOfEditorOnScreen();
152+
int horizontalResolution = NativeMethods.GetSystemMetrics(NativeMethods.SM_CXSCREEN);
153+
int verticalResolution = NativeMethods.GetSystemMetrics(NativeMethods.SM_CYSCREEN);
154+
point = new ScaleTransform(65535.0 / horizontalResolution, 65535.0 / verticalResolution).Transform(point);
155+
156+
inputSimulator
157+
.Mouse.MoveMouseTo(point.X, point.Y)
158+
.Keyboard.KeyDown(VirtualKeyCode.CONTROL)
159+
.Mouse.VerticalScroll(-1)
160+
.Keyboard.KeyUp(VirtualKeyCode.CONTROL);
161+
162+
VisualStudio.WaitForApplicationIdle();
163+
164+
Assert.Equal(0, VisualStudio.Editor.GetCaretPosition());
165+
Assert.Equal(lastVisibleLine, VisualStudio.Editor.GetFirstVisibleLine());
166+
Assert.Equal(zoomLevel, VisualStudio.Editor.GetZoomLevel());
167+
168+
inputSimulator
169+
.Mouse.MoveMouseTo(point.X, point.Y)
170+
.Keyboard.KeyDown(VirtualKeyCode.CONTROL)
171+
.Mouse.VerticalScroll(1)
172+
.Keyboard.KeyUp(VirtualKeyCode.CONTROL);
173+
174+
VisualStudio.WaitForApplicationIdle();
175+
176+
Assert.Equal(0, VisualStudio.Editor.GetCaretPosition());
177+
Assert.Equal(0, VisualStudio.Editor.GetFirstVisibleLine());
178+
Assert.Equal(zoomLevel, VisualStudio.Editor.GetZoomLevel());
49179

50180
VisualStudioInstance.RetryRpcCall(() => window.Close(vsSaveChanges.vsSaveChangesNo));
51181
}

0 commit comments

Comments
 (0)