PageRenderTime 55ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/Common/Tests/Utilities.UI/UI/VisualStudioInstance.cs

https://gitlab.com/SplatoonModdingHub/PTVS
C# | 332 lines | 299 code | 11 blank | 22 comment | 2 complexity | e9e85e2251c234ba080bb0bafc46201c MD5 | raw file
  1. // Visual Studio Shared Project
  2. // Copyright(c) Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // Licensed under the Apache License, Version 2.0 (the License); you may not use
  6. // this file except in compliance with the License. You may obtain a copy of the
  7. // License at http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS
  10. // OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY
  11. // IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
  12. // MERCHANTABLITY OR NON-INFRINGEMENT.
  13. //
  14. // See the Apache Version 2.0 License for specific language governing
  15. // permissions and limitations under the License.
  16. using System;
  17. using System.Collections.Generic;
  18. using System.IO;
  19. using System.Linq;
  20. using System.Windows.Automation;
  21. using System.Windows.Input;
  22. using EnvDTE;
  23. using Microsoft.VisualStudio.Shell;
  24. using Microsoft.VisualStudio.Shell.Interop;
  25. using Microsoft.VisualStudio.TestTools.UnitTesting;
  26. using Microsoft.VisualStudioTools.VSTestHost;
  27. using TestUtilities.SharedProject;
  28. namespace TestUtilities.UI {
  29. using Thread = System.Threading.Thread;
  30. /// <summary>
  31. /// Wrapper around a generated SolutionFile. Provides helpers for simplifying
  32. /// interacting with the solution loaded into Solution Explorer.
  33. /// </summary>
  34. public class VisualStudioInstance : IDisposable, IVisualStudioInstance {
  35. private readonly SolutionFile _solution;
  36. private readonly VisualStudioApp _app;
  37. public readonly EnvDTE.Project Project;
  38. private SolutionExplorerTree _solutionExplorer;
  39. private bool _disposed;
  40. public VisualStudioInstance(SolutionFile solution) {
  41. _solution = solution;
  42. _app = new VisualStudioApp();
  43. Project = _app.OpenProject(solution.Filename);
  44. ThreadHelper.Generic.Invoke(Keyboard.Reset);
  45. _solutionExplorer = _app.OpenSolutionExplorer();
  46. SelectSolutionNode();
  47. }
  48. public VisualStudioApp App {
  49. get {
  50. return _app;
  51. }
  52. }
  53. public SolutionExplorerTree SolutionExplorer {
  54. get {
  55. return _solutionExplorer;
  56. }
  57. }
  58. IEditor IVisualStudioInstance.OpenItem(string project, params string[] path) {
  59. return OpenItem(project, path);
  60. }
  61. /// <summary>
  62. /// Opens the specified filename from the specified project name.
  63. /// </summary>
  64. public EditorWindow OpenItem(string project, params string[] path) {
  65. foreach (EnvDTE.Project proj in VSTestContext.DTE.Solution.Projects) {
  66. if (proj.Name == project) {
  67. var items = proj.ProjectItems;
  68. EnvDTE.ProjectItem item = null;
  69. foreach (var itemName in path) {
  70. item = items.Item(itemName);
  71. items = item.ProjectItems;
  72. }
  73. Assert.IsNotNull(item);
  74. var window = item.Open();
  75. window.Activate();
  76. return App.GetDocument(item.Document.FullName);
  77. }
  78. }
  79. throw new InvalidOperationException(
  80. String.Format(
  81. "Failed to find {0} item in project {1}",
  82. String.Join("\\", path),
  83. project
  84. )
  85. );
  86. }
  87. ITreeNode IVisualStudioInstance.FindItem(params string[] path) {
  88. var res = FindItem(path);
  89. if (res != null) {
  90. return new TreeNode(res);
  91. }
  92. return null;
  93. }
  94. public AutomationElement FindItem(params string[] path) {
  95. return SolutionExplorer.FindItem(AddSolutionToPath(path));
  96. }
  97. private string[] AddSolutionToPath(string[] path) {
  98. return new[] { SolutionNodeText }.Concat(path).ToArray();
  99. }
  100. public AutomationElement WaitForItem(params string[] path) {
  101. return SolutionExplorer.WaitForItem(AddSolutionToPath(path));
  102. }
  103. ITreeNode IVisualStudioInstance.WaitForItemRemoved(params string[] path) {
  104. var res = SolutionExplorer.WaitForItemRemoved(AddSolutionToPath(path));
  105. if (res != null) {
  106. return new TreeNode(res);
  107. }
  108. return null;
  109. }
  110. public AutomationElement WaitForItemRemoved(params string[] path) {
  111. return SolutionExplorer.WaitForItemRemoved(AddSolutionToPath(path));
  112. }
  113. public void ExecuteCommand(string command) {
  114. App.ExecuteCommand(command);
  115. }
  116. public string SolutionFilename {
  117. get {
  118. return _solution.Filename;
  119. }
  120. }
  121. public IntPtr WaitForDialog() {
  122. return App.WaitForDialog();
  123. }
  124. public void WaitForDialogDismissed() {
  125. App.WaitForDialogDismissed();
  126. }
  127. public string SolutionDirectory {
  128. get {
  129. return _solution.Directory;
  130. }
  131. }
  132. private string SolutionNodeText {
  133. get {
  134. if (_solution.Projects.Count(sln => !sln.Flags.HasFlag(SolutionElementFlags.ExcludeFromConfiguration) && !sln.Flags.HasFlag(SolutionElementFlags.ExcludeFromSolution)) > 1) {
  135. return String.Format(
  136. "Solution '{0}' ({1} projects)",
  137. Path.GetFileNameWithoutExtension(_solution.Filename),
  138. _solution.Projects.Length
  139. );
  140. }
  141. return String.Format(
  142. "Solution '{0}' (1 project)",
  143. Path.GetFileNameWithoutExtension(_solution.Filename)
  144. );
  145. }
  146. }
  147. /// <summary>
  148. /// Selects the solution node using the mouse.
  149. ///
  150. /// This is used to reset the state of the mouse before a test as some
  151. /// tests can cause the mouse to be left in an odd state - the mouse up
  152. /// event is delivered to solution explorer, but selecting items later
  153. /// doesn't work because the mouse is left in an odd state. If you
  154. /// make this method a nop and try and run all of the tests you'll
  155. /// see the bad behavior.
  156. /// </summary>
  157. public void SelectSolutionNode() {
  158. // May need to reopen Solution Explorer so we can find a clickable
  159. // point.
  160. _solutionExplorer = _app.OpenSolutionExplorer();
  161. var item = SolutionExplorer.WaitForItem(SolutionNodeText);
  162. SolutionExplorer.CenterInView(item);
  163. Mouse.MoveTo(item.GetClickablePoint());
  164. Mouse.Click(MouseButton.Left);
  165. }
  166. #region IDisposable Members
  167. ~VisualStudioInstance() {
  168. Dispose(false);
  169. }
  170. public void Dispose() {
  171. Dispose(true);
  172. GC.SuppressFinalize(this);
  173. }
  174. protected virtual void Dispose(bool disposing) {
  175. if (!_disposed) {
  176. if (disposing) {
  177. _app.Dispose();
  178. _solution.Dispose();
  179. }
  180. _disposed = true;
  181. }
  182. }
  183. #endregion
  184. public void AssertFileExists(params string[] path) {
  185. SolutionExplorer.AssertFileExists(SolutionDirectory, AddSolutionToPath(path));
  186. }
  187. public void AssertFileDoesntExist(params string[] path) {
  188. SolutionExplorer.AssertFileDoesntExist(SolutionDirectory, AddSolutionToPath(path));
  189. }
  190. public void AssertFolderExists(params string[] path) {
  191. SolutionExplorer.AssertFolderExists(SolutionDirectory, AddSolutionToPath(path));
  192. }
  193. public void AssertFolderDoesntExist(params string[] path) {
  194. SolutionExplorer.AssertFolderDoesntExist(SolutionDirectory, AddSolutionToPath(path));
  195. }
  196. public void AssertFileExistsWithContent(string content, params string[] path) {
  197. SolutionExplorer.AssertFileExistsWithContent(SolutionDirectory, content, AddSolutionToPath(path));
  198. }
  199. public void CloseActiveWindow(vsSaveChanges save) {
  200. App.Dte.ActiveWindow.Close(vsSaveChanges.vsSaveChangesNo);
  201. }
  202. ITreeNode IVisualStudioInstance.WaitForItem(params string[] items) {
  203. var res = WaitForItem(items);
  204. if (res != null) {
  205. return new TreeNode(res);
  206. }
  207. return null;
  208. }
  209. public void Type(Key key) {
  210. Keyboard.Type(key);
  211. }
  212. public void ControlC() {
  213. Keyboard.ControlC();
  214. }
  215. public void ControlX() {
  216. Keyboard.ControlX();
  217. }
  218. public void Type(string p) {
  219. Keyboard.Type(p);
  220. }
  221. public void ControlV() {
  222. Keyboard.ControlV();
  223. }
  224. public void PressAndRelease(Key key, params Key[] modifier) {
  225. Keyboard.PressAndRelease(key, modifier);
  226. }
  227. public void CheckMessageBox(params string[] text) {
  228. VisualStudioApp.CheckMessageBox(text);
  229. }
  230. public void CheckMessageBox(MessageBoxButton button, params string[] text) {
  231. VisualStudioApp.CheckMessageBox(button, text);
  232. }
  233. public void Sleep(int ms) {
  234. Thread.Sleep(ms);
  235. }
  236. public void WaitForOutputWindowText(string name, string containsText, int timeout = 5000) {
  237. App.WaitForOutputWindowText(name, containsText, timeout);
  238. }
  239. public IntPtr OpenDialogWithDteExecuteCommand(string commandName, string commandArgs = "") {
  240. return App.OpenDialogWithDteExecuteCommand(commandName, commandArgs);
  241. }
  242. public Project GetProject(string projectName) {
  243. return App.GetProject(projectName);
  244. }
  245. public void SelectProject(Project project) {
  246. SolutionExplorer.SelectProject(project);
  247. }
  248. public IEditor GetDocument(string filename) {
  249. return App.GetDocument(filename);
  250. }
  251. public IAddExistingItem AddExistingItem() {
  252. return AddExistingItemDialog.FromDte(App);
  253. }
  254. public IAddNewItem AddNewItem() {
  255. return NewItemDialog.FromDte(App);
  256. }
  257. public IOverwriteFile WaitForOverwriteFileDialog() {
  258. return OverwriteFileDialog.Wait(App);
  259. }
  260. public void WaitForMode(dbgDebugMode dbgDebugMode) {
  261. App.WaitForMode(dbgDebugMode);
  262. }
  263. public List<IVsTaskItem> WaitForErrorListItems(int expectedItems) {
  264. return App.WaitForErrorListItems(expectedItems);
  265. }
  266. public DTE Dte {
  267. get { return App.Dte; }
  268. }
  269. public void OnDispose(Action action) {
  270. App.OnDispose(action);
  271. }
  272. }
  273. }